Java异常处理及spring boot异常统一处理

程序代码在没有问题的情况下是可以按照预定的业务逻辑正常的运行,并输出预定的结果;程序因为某些入参或程序未覆盖的逻辑以及一些资源限制等等导致程序不能按照预定逻辑正常执行,出现程序中断的情况就是异常。而针对异常往往需要修改代码避免出现异常或出现异常时进行特殊处理保证程序的正常运行,不对程序整体产生影响以及对于出现异常的业务后续也能跟踪处理。

一、异常

异常的顶级父类是 java.lang.Throwable ,异常整体分为两种:

1、java.lang.Error

对于 Error 错误来说,代表系统的严重错误,比如硬件层面、JVM错误或者内存不足等等,对于这类错误通常不需要特别关注处理,因为往往不是因为程序代码问题导致的,也就没办法通过修改代码加以修复。比如:java.lang.OutOfMemoryError: Java heap space 错误,要么尝试修改内存大小,要么调整出现OOM异常的代码能否占用更小的内存实现功能。

2、java.lang.Exception

对于 Exception 异常来说,是遇到的最多异常,这类异常往往是项目中需要着重处理关注的点,也有两种分类:
受检异常:即编码过程中一些编码软件就能出现提示的异常或程序运行前进行编译的过程中编译无法通过的异常,导致程序无法运行起来,这部分异常在测试前就能发现并修改并且必须处理才能运行,所有不是 RuntimeException 的异常就是受检异常。
非受检异常:即编译能够通过,编码软件不提示异常;程序可以正常运行,但出现某些特殊情况就会导致程序处理异常;这种异常只能在运行中才会出现,如果测试不全面可能会带到生产环境;这种异常就是 java.lang.RuntimeException 运行时异常,不需要强制处理。

异常产生:
当jvm执行程序时,执行到异常程序处会检测到这个异常的信息,然后创建一个对应的异常对象(这个异常对象中包含:异常的内容、原因、代码位置等信息);此时异常处后续代码的执行中断,然后检测产生异常的代码是否有异常处理机制(try/catch),如果有则按照异常处理机制的内容进行异常处理,如果没有异常处理机制则直接抛出这个异常对象给方法的调用者由方法调用者来处理这个异常,如果调用者也没有异常处理机制则继续向上抛出给调用者,最终检测到某个调用者有异常处理机制则按照异常处理机制执行,如果所有调用者都没有异常处理机制则最终交给jvm处理这个异常,jvm首先将异常对象打印在控制台(如果有配置日志记录,也会将控制台的信息记录在日志记录中)并中断当前产生异常的程序执行。

抛出异常:
throw
作用:可以使用throw关键字在指定的方法中抛出指定的导常
使用格式:throw new xxxException(“异常产生的原因”)
注意:
1、throw关键字必须写在方法的内部。
2、throw关键字后边new的对象必须是Exception或者Exception的子类对象。
3、throw关键字抛出指定的异常对象,我们就必须处理这个异常对象,如果throw关键字后边创建的是RuntimeException或RuntimeException的子类对象,可以不处理,默认会交给JVM处理(即打印异常对象并中断程序);如果throw关键字后边创建的是受检异常(编码软件提示或编译无法通过),就必须处理这个异常,否则程序无法运行,处理方式可以通过 throws 在方法上抛出异常 或 try/catch 处理异常。

二、异常处理

1、throws异常处理:
throws 关键字异常处理方式是交给调用者处理产生的异常。
当方法内部抛出异常对象的时候就必须处理这个异常对象,可以使用throws关键字处理异常对象把异常对象声明抛出给方法的调用者处理(自己不处理,给别人处理),如果调用者也不处理最终交给JVM处理。
使用格式:在方法声明时使用 throws xxxExcepiton,yyyExcepiton {throw new xxxException("产生原因”);throw new yyyException("产生原因”)}。
主意:
1、throws关键字必须写在方法声明处
2、throws关键字后边声明的异常必须是Exception或者是Exception的子类
3、方法内部如果抛出了多个异常对象,那么throws后边必须也声明多个异常如果抛出的多个异常对象有父子类关系,那么直接声明父类异常即可
4、调用了一个声明抛出异常的方法,则必须处理声明的异常,可以继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM处理,或者使用try/catch自己处理异常

如果父类的方法使用 throws 抛出了异常那么子类在重写父类的该方法时可以有以下几种选择:
1、可以保持和父类一样 throws 抛出相同的异常
2、可以 throws 抛出父类该方法异常的子类异常
3、可以不抛出异常
如果父类方法没有使用 throws 抛出异常,那么子类重写时也不能抛出异常,如果有异常只能在内部try/catch处理

2、try/catch异常处理:
try/catch方式是自己处理异常在方法内部直接处理异常而不将异常抛出给调用者。
使用格式:try{可能产生异常的代码}catch(定义一个异常的变量,用来接收try中抛出的异常对象,需要和try中抛出的异常类型匹配或其父类否则不会被捕获){异常的处理逻辑};一般来说异常处理逻辑中会将异常进行记录,并按照业务进行处理。
注意:
1、try中可能会抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象,每个catch处理不同类型的异常
2、如果try中产生了异常就会执行对应catch中的异常处理逻辑,执行完毕catch中的处理逻辑,会继续执行try/catch之后的代码;如果try中没有产生异常就不会执行catch中异常的处理逻辑,执行完try中的代码,继续执行try/catch之后的代码
3、如果定义的catch中没有try中抛出异常的类型或其父类,则没有catch的处理逻辑会被执行;且最终还是交由JVM处理(打印异常,中断程序),try/catch后续逻辑也不会执行
4、try中代码块出现异常的代码之后的程序也不会执行

try/catch针对多个异常代码处理异常一般有以下几种方式:
1、每个会出现异常的代码都分别进行try/catch,这种写法没问题,但是代码比较臃肿,不建议使用。
2、所有会出现异常的代码都写在一个try中,然后通过多个catch分别处理这些异常,注意点在于范围小的异常类型catch写在范围大的异常类型catch前面即子类异常catch写在父类异常的catch前面,否则抛出的异常会直接被前面的父类catch捕获,后面的子类catch没有作用也会编译不通过
3、同样将会出现异常的代码写在一个try中,但是只写一个catch,这个catch的类型是所有可能抛出异常的类型的父类,这样就可以实现所有抛出的异常都被这一个catch捕获
推荐使用第二种,使用第二种既不显得代码臃肿相比于第三种也可以更精细的处理异常,可以根据每个异常的类型做不同的处理逻辑,同时可以最后写一个比较顶级的异常类型做兜底,防止所有catch都匹配不上。

finally关键字:
finally不能单独使用,需要配合try使用不论是否有catch都行;作用在于不论try中是否出现异常,不论出现的异常是否被catch捕获(或没有catch),finally中的逻辑都会执行,所以一般用来做收尾工作,比如资源的释放,连接的关闭等等;try/catch/finally执行顺序按照先后顺序执行,即先执行try,如果出现异常并且通过catch进行捕获,就执行catch中的逻辑,最后执行finally中的逻辑,如果没有catch或catch没有匹配异常类型则执行try之后就执行finally逻辑。
注意:finally中避免使用return语句,因为finally中的逻辑必执行且在try执行之后,所以如果try中没有异常,try中返回的值会最终被finally中的return语句覆盖,那么调用方法返回的值将永远是finally中return的值,所以要避免在finally中使用return语句。

3、异常对象操作方法:
e.getMessage():获取异常提示信息
e.toString():获取异常类型及异常提示信息
e.printStackTrace():打印异常全部信息(如果有集成日志,采用log的记录日志方法可将整个异常对象记录在日志中,记录的信息可以和e.printStackTrace()输出的信息一致)
e.getClass():获取异常类型

三、自定义异常

如果Java自带的异常类型不满足需求时,这时就可以自定义异常,使用自定义的异常去处理一些场景。
注意:自定义异常类需要继承 Exception 或 RuntimeException,如果继承Exception表示当前异常是受检异常抛出该类型异常必须处理(throws或try/catch处理),如果继承RuntimeException表示非受检异常,可以不处理
方式一:该种自定义异常最简洁,只能输入异常提示

package com.my.test.member.biz.exception;/*** 注意:* 1、需要继承 Exception 或 RuntimeException,如果继承Exception表示当前异常是受检异常抛出该类型异常必须处理(throws或try/catch处理),如果继承RuntimeException表示非受检异常,可以不处理* 2、添加一个无参构造器以及一个带异常信息的构造器,无参构造器默认类就有一个,但是添加了其他构造器之后这个默认的无参构造器就没了,所以这两个构造器都要显示的写出来*/
public class CustomException extends RuntimeException{public CustomException(){super();}public CustomException(String msg){//这个msg异常消息会在日志中打印出来,如果不传msg,那么抛出异常时不会打印异常消息super(msg);}}

方式二:自定义异常并自定义设置状态码和消息(一般在项目中用于设置不同的错误提示用不同状态码和消息表示)

package com.my.test.member.biz.exception;public class CustomException extends RuntimeException{public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}private int code;private String msg;public CustomException(int code,String msg){super();this.code = code;this.msg = msg;}
}

测试代码:

package com.my.test.member.biz.exception;public class TestExceptiion {public static void main(String[] args) {test();}public static void test(){try {//抛出异常throw new CustomException("自定义异常触发!");}catch (CustomException e){//catch捕获异常,CustomException继承自RuntimeException,是RuntimeException子类所以写在RuntimeException前面,可以通过log将异常信息记录在日志中System.out.println(e);}catch (RuntimeException e){//RuntimeException写在后面作为兜底异常处理,可以通过log将异常信息记录在日志中System.out.println(e);}}}

四、spring boot异常处理

针对spring boot的异常处理,首先程序中应当定义一个统一的返回类型,这样不论是否成功、是否异常,客户端都能按照特定的格式解析数据和消息,否则客户端解析太乱。
自定义返回类型 R :

package com.my.test.member.api;import com.my.test.member.api.constant.CodeConstant;import java.io.Serializable;public class R<T> implements Serializable {private static final long serialVersionUID = 1L;/*** 返回编码 0-成功1-失败*/private int code;/*** 返回消息*/private String message;/*** 返回数据*/private T data;public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}/*** 返回成功,无数据,默认消息* @return*/public static R ok() {return setResult(CodeConstant.SUCCESS,CodeConstant.OK_MSG,null);}/*** 返回成功,自定义消息和数据* @param msg* @param data* @param <T>* @return*/public static <T> R ok(String msg,T data) {return setResult(CodeConstant.SUCCESS,msg,data);}/*** 返回成功,自定义数据* @param data* @param <T>* @return*/public static <T> R ok(T data) {return setResult(CodeConstant.SUCCESS,CodeConstant.OK_MSG,data);}/*** 返回成功,自定义状态码、消息、数据,针对一些特殊情况的处理,可以自定义状态码,否则一般都是采用成功的默认状态码* @param code* @param message* @param data* @param <T>* @return*/public static <T> R ok(int code,String message,T data) {return setResult(code,message,data);}/*** 返回失败,无数据,默认消息* @return*/public static R fail() {return setResult(CodeConstant.FAIL,CodeConstant.FAIL_MSG,null);}/*** 返回失败,自定义消息* @param message* @return*/public static R fail(String message) {return setResult(CodeConstant.FAIL,message,null);}/*** 返回失败,自定义消息和数据* @param msg* @param data* @param <T>* @return*/public static <T> R fail(String msg,T data) {return setResult(CodeConstant.FAIL,msg,data);}/*** 返回失败,自定义状态码、消息和数据,针对一些特殊情况的处理,可以自定义状态码,否则一般都是采用失败的默认状态码* @param code* @param message* @param data* @param <T>* @return*/public static <T> R fail(int code,String message,T data) {return setResult(code,message,data);}/*** 负责创建应答对象* @param code* @param message* @param data* @param <T>* @return*/private static <T> R<T> setResult(int code,String message,T data){R<T> result = new R();result.setCode(code);result.setMessage(message);result.setData(data);return result;}
}

常量类 CodeConstant :

package com.my.test.member.api.constant;public class CodeConstant {/*** 成功code标识*/public static final int SUCCESS = 0;/*** 失败code标识*/public static final int FAIL = 1;/*** 消息提示成功*/public static final String OK_MSG = "OK";/*** 消息提示失败*/public static final String FAIL_MSG = "FAIL";}

自定义异常(根据项目需要选择是否自定义异常):

package com.my.test.member.biz.exception;/*** 自定义异常*/
public class CustomException extends RuntimeException{public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}private int code;private String msg;/*** 抛出没有异常消息的异常*/public CustomException(){super();}/*** 自定义状态码和消息的异常* @param code* @param msg*/public CustomException(int code,String msg){super(msg);this.code = code;this.msg = msg;}/*** 根据统一异常枚举设置状态码和消息的异常* @param exceptionEnum*/public CustomException(ExceptionEnum exceptionEnum){super(exceptionEnum.getMsg());this.code = exceptionEnum.getCode();this.msg = exceptionEnum.getMsg();}}

自定义异常枚举类(ExceptionEnum统一维护异常信息):

package com.my.test.member.biz.exception;/*** 异常提示枚举类,将系统中的异常情况全部定义在这里,统一维护规范异常信息,可以将code设定为具有标识意义的值,比如code前两位标识哪个模块,后几位标识状态码信息*/
public enum ExceptionEnum {NAME_NULL_EXCEPTION(1001,"名称为空!"),USER_NOT_EXIST_EXCEPTION(1002,"用户数据不存在!"),PASSWORD_ERROR_EXCEPTION(1003,"密码错误!");public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}/*** 状态码*/private Integer code;/*** 消息*/private String msg;ExceptionEnum(Integer code, String msg) {this.code = code;this.msg = msg;}/*** 根据code获取对应枚举对象* @param code* @return*/public static ExceptionEnum getException(Integer code){for (ExceptionEnum exceptionEnum : ExceptionEnum.values()) {if(code.equals(exceptionEnum.getCode())){return exceptionEnum;}}return null;}
}

全局统一异常处理类(核心类):

package com.my.test.member.biz.exception;import com.my.test.member.api.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;import java.util.List;/*** 全局异常统一处理*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {/*** 全局异常处理 @ExceptionHandler 该注解用于表示当前方法处理哪种类型的异常,@ExceptionHandler标注的方法可以写多个,每个方法处理不同类型的异常* 一般将子类型的异常处理方法写在父类型的前面* @param e* @return*/@ExceptionHandler(Exception.class)public R handleGlobalException(Exception e) {log.error("全局异常信息 e:{}", e);if (e instanceof CustomException){CustomException ce = (CustomException) e;//如果是自定义异常,那么返回自定义的code和消息return R.fail(ce.getCode(),ce.getMsg(),null);}else if (e instanceof MethodArgumentNotValidException){//MethodArgumentNotValidException异常是使用 JSR303(javax.validation.constraints包下面的注解) 比如javax.validation.constraints.NotNull 注解验证参数时,框架抛出的异常类型//参数不满足条件时会把参数的验证错误信息,放入到FieldErrors中MethodArgumentNotValidException mnve = (MethodArgumentNotValidException) e;//getFieldErrors获取所有不满足验证条件的字段的错误提示信息List<FieldError> fieldErrors = mnve.getBindingResult().getFieldErrors();//取多个异常信息中的第一个返回即可,javax.validation.constraints下的注解是对参数的验证,所以这里状态码定为400,fieldErrors里面记录的第一个错误信息不一定是类中字段对应的顺序return R.fail(400,fieldErrors.get(0).getDefaultMessage(),null);}//非前面判断的异常直接返回默认失败状态码和消息return R.fail(e.getMessage());}
}

接口测试:
参数类 dto:

package com.my.test.member.api.dto;import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;/*** 用户dto*/
public class UserDTO {public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}/*** 用户id* 使用JSR303相关注解对字段进行验证,groups用于指定当前验证规则(如:@NotNull、@Null、@NotBlank等等)的分组* controller接口参数加入 @Validated 注解验证规则才能生效,并且验证规则是否生效和 @Validated 注解指定的分组对应* 验证规则指定分组为 UpdateException 则 @Validated 也要指定分组为 UpdateException 那么当前验证规则才能生效* 如果 @Validated 注解不指定分组,那么也只对验证规则不指定分组的验证规则生效,如下面 password 的验证规则未指定分组* 分组接口如:UpdateException 是一个空接口即可*/@NotNull(message = "用户id不能为空!",groups = {UpdateException.class,SelectException.class})@Null(message = "用户id必须为空!",groups = {AddException.class})private Integer id;/*** 用户名称*/@NotBlank(message = "用户名称不能为空!",groups = {AddException.class,UpdateException.class})@NotBlank(message = "用户名称不能为空!")private String name;/*** 用户密码*/@NotBlank(message = "用户密码不能为空!")private String password;}

接口类 controller:

package com.my.test.member.biz.controller;import com.my.test.member.api.R;
import com.my.test.member.api.dto.UserDTO;
import com.my.test.member.biz.exception.CustomException;
import com.my.test.member.biz.exception.ExceptionEnum;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.validation.annotation.Validated;/*** 异常测试controller*/
@RestController
@RequestMapping("exception")
public class TestExceptionController {/*** @Validated({UpdateException.class,SelectException.class})  表示启用JSR303的验证功能,其中UpdateException.class,SelectException.class表示当前的参数验证* 只对分组为UpdateException和SelectException的字段进行对应规则的验证,如果不写分组,表示只对验证规则没有指定分组的字段进行验证* @param userDTO* @return*/@PostMapping(value = "/login")public R info(@RequestBody @Validated({UpdateException.class,SelectException.class}) UserDTO userDTO){if (!userDTO.getName().equals("张三")){throw new CustomException(ExceptionEnum.USER_NOT_EXIST_EXCEPTION);}if (!userDTO.getPassword().equals("123456")){throw new CustomException(1003,"密码错误!");}return R.ok("查询成功,用户:"+userDTO.getName());}}

注意上面的示例中使用了JSR303的验证方式,按照上面的使用方式需要做如下操作:
1、导入JSR303的jar包

        <!-- spring boot项目导入 spring-boot-starter-validation 包即可(已包含hibernate-validator包) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency><!-- 非spring boot项目导入 hibernate-validator 包 --><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>6.2.3.Final</version></dependency>

2、添加验证规则分组接口:
AddException:

package com.my.test.member.api.group.exception;public interface AddException {
}

DeleteException:

package com.my.test.member.api.group.exception;public interface DeleteException {
}

SelectException:

package com.my.test.member.api.group.exception;public interface SelectException {
}

UpdateException:

package com.my.test.member.api.group.exception;public interface UpdateException {
}

Java日志框架JUL、Log4j、logback、log4j2使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/21124.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【iOS RunLoop】

文章目录 前言-什么是RunLoop&#xff1f;默认情况下主线程的RunLoop原理 1. RunLoop对象RunLoop对象的获取 CFRunLoopRef源码部分&#xff08;引入线程相关&#xff09; 2. RunLoop和线程3. RunLoop相关的类RunLoop相关类的实现CFRunLoopModeRef五种运行模式CommonModes CFRun…

【MMCV】mmpretrain/mmclassification概览、环境安装与验证

概览 MMPretrain 是一个全新升级的预训练开源算法框架,旨在提供各种强大的预训练主干网络, 并支持了不同的预训练策略。MMPretrain 源自著名的开源项目 MMClassification 和 MMSelfSup,并开发了许多令人兴奋的新功能。 目前,预训练阶段对于视觉识别至关重要,凭借丰富而强…

MySQL - 9、存储过程和函数

创建存储过程、修改存储过程、删除存储过程、创建函数、修改函数、删除函数&#xff0c;以及调用存储过程和函数的操作&#xff1a; -- 创建存储过程 DELIMITER // CREATE PROCEDURE sp_example_procedure() BEGIN-- 存储过程的具体逻辑SELECT * FROM employees; END // DELIM…

C高级--day2(用户相关操作 磁盘相关操作 shell脚本 修改环境变量)

#include<myhead.h>void fun(int n) {if(n>9){fun(n/10);printf("%d\t",n%10);putchar(10);return;}else{printf("%d\n",n%10);return;} } int main(int argc, const char *argv[]) {int num;printf("请输入一个整数&#xff1a;");sca…

Maven引入本地第三方Jar包

背景 引入第三方的Jar包&#xff0c;本来是在项目结构的库里面引入的jar包&#xff0c;但是用maven打包时报错&#xff0c;所以后面想着用maven引入本地地址的方式。 解决方法 1.将Jar包放到根目录里面&#xff0c;我这边放在了lib文件中,如图所示&#xff1a; 2.在pom文件…

Mybatis引出的一系列问题-Mybatis缓存机制的探究

Mybatis 使用到了两种缓存&#xff1a;本地缓存&#xff08;local cache&#xff09;和二级缓存&#xff08;second level cache&#xff09;。 一级缓存默认是开启的&#xff0c;而且不能关闭&#xff0c;MyBatis的一些关键特性&#xff08;例如通过<association>和<…

机器人“瓦力”近在咫尺?谷歌最新的RT-2 AI模型简介

“首创”的机器人 AI 模型能够识别垃圾并执行复杂的动作。 上周五&#xff0c;谷歌 DeepMind 宣布了机器人变形器 2&#xff08;RT-2&#xff09;&#xff0c;这是一种“首次推出”的视觉-语言-行动&#xff08;VLA&#xff09;模型&#xff0c;利用从互联网上抓取的数据&…

Linux学习之延时计划任务anacontab和锁文件flock

cat /etc/redhat-release看到操作系统的版本是CentOS Linux release 7.6.1810 (Core)&#xff0c;uname -r可以看到内核版本是3.10.0-957.21.3.el7.x86_64 参考的博客有&#xff1a; 1.《Linux anacron命令用法详解》 2.《详解anacron 命令》 3.《Anacron的用法》 4.《shell脚…

C#的yield

在 C# 中&#xff0c;yield 关键字用于定义迭代器方法&#xff08;Iterator Methods&#xff09;&#xff0c;并使其返回一个可枚举的序列。通过使用 yield 关键字&#xff0c;可以简化迭代器的实现&#xff0c;使其更加直观和易于理解。 使用 yield 关键字定义的方法被称为迭…

Libevent开源库的介绍与应用

libeventhttps://libevent.org/ 一、初识 1、libevent介绍 Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库&#xff0c;主要有以下几个亮点&#xff1a;事件驱动&#xff08; event-driven&#xff09;&#xff0c;高性能;轻量级&#xff0c;专注于网络&#xff…

【雕爷学编程】MicroPython动手做(37)——驱动LCD与图文显示

MixPY——让爱(AI)触手可及 MixPY布局 主控芯片&#xff1a;K210&#xff08;64位双核带硬件FPU和卷积加速器的 RISC-V CPU&#xff09; 显示屏&#xff1a;LCD_2.8寸 320*240分辨率&#xff0c;支持电阻触摸 摄像头&#xff1a;OV2640&#xff0c;200W像素 扬声器&#…

【Ajax】笔记-设置CORS响应头实现跨域

CORS CORS CORS是什么&#xff1f; CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS是官方的跨域解决方案&#xff0c;它的特点是不需要在客户端做任何特殊的操作&#xff0c;完全在服务器中进行处理&#xff0c;支持get和post请求。跨域资源共享标准新增了一组HTTP首…

页面技术基础-html

页面技术基础-html 环境准备&#xff1a;在JDBC中项目上完成代码定义 1. 新建一个 Module:filr->右键 -》Module -》Java-》next->名字(html_day1)->finish 2. 在 Moudle上右键-》第二个选项&#xff1a;add framework .. -> 选择JavaEE下第一个选项 Web Apllicat…

Vue系列第六篇:axios封装,登录逻辑优化,404页面实现,Go语言跨域处理

第五篇利用vue实现了登录页面&#xff0c;用go语言开发了服务端并最后在nginx上进行了部署。本篇将axios封装&#xff0c;登录逻辑优化&#xff0c;404页面实现。 目录 1.前端 1.1代码结构 1.2源码 2.服务端 2.1源码 3.运行效果 4.注意事项 4.1webpack.config.js和vue…

Docker安装RabbitMQ集群

一、安装单机版 1、更新yum源安装 vim、net-tools等工具 yum update -yyum install vim -yyum install net-tools -y 2、安装单机版 #创建挂载路径 mkdir /data/rabbitmq -p#拉取镜像 docker pull rabbitmq:3.9-management#创建容器并启动 docker run -d -it --name rabbi…

【ES】使用日志记录

1、修改操作 1、要删除Elasticsearch索引的分区下的数据 <index_name>是要删除数据的索引名称。这个命令会删除该索引下的所有数据。 POST /<index_name>/_delete_by_query {"query": {"match_all": {}} }2、删除特定条件下的数据 要删除a…

从k8s 的声明式API 到 GPT的 提示语

命令式 命令式有时也称为指令式&#xff0c;命令式的场景下&#xff0c;计算机只会机械的完成指定的命令操作&#xff0c;执行的结果就取决于执行的命令是否正确。GPT 之前的人工智能就是这种典型的命令式&#xff0c;通过不断的炼丹&#xff0c;告诉计算机要怎么做&#xff0…

Sheel编写关于mysqldump实现分库分表备份

编写脚本&#xff0c;使用mysqldump实现分库分表备份。 #编辑脚本文件 [rootlocalhost scripts]# vim bak_tb1.sh#脚本内容&#xff1a; #设置变量&#xff0c;减少代码冗余 mysql_cmd-uroot -p123 exclude_dbDatabase|information_schema|-S|mysql|performance_schema|sys ba…

Cesium 加载ArcGIS Server切片服务错级问题

1.首先上官方api说明 ArcGisMapServerImageryProvider - Cesium Documentation 里面没有 zoomoffset参数!!! 2.如果按照互联网栅格切片规则 3857、4326、4490常用切片层级参数,则直接加载显示地图 viewer.imageryLayers.addImageryProvider(new Cesium.ArcGisMapServerI…

词法分析器

词法分析器 在早期编译1.0时代&#xff0c;我们的目标是完成程序语言到机器语言的翻译&#xff0c;所以重点在编译器前端&#xff0c;于是我们花费大量时间研究词法分析、语法分析、语义分析等内容。如今的本科编译原理课程&#xff0c;基本上也就到这一层面吧。 在编译2.0时…