另外一个博客站点

SpringBoot写出简单的后端接口

所需依赖包

<!--web依赖包,web应用必备-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

参数校验 Validator + BindResult进行校验

Validator可以非常方便的制定校验规则,并自动帮你完成校验。首先在入参里需要校验的字段加上注解,每个注解对应不同的校验规则,并可制定校验失败后的信息:
实体类 参数加上校验注解

@Data
public class User {
    @NotNull(message = "用户id不能为空")
    private Long id;

    @NotNull(message = "用户账号不能为空")
    @Size(min = 6, max = 11, message = "账号长度必须是6-11个字符")
    private String account;

    @NotNull(message = "用户密码不能为空")
    @Size(min = 6, max = 11, message = "密码长度必须是6-16个字符")
    private String password;

    @NotNull(message = "用户邮箱不能为空")
    @Email(message = "邮箱格式不正确")
    private String email;
}

校验规则和错误提示信息配置完毕后,接下来只需要在接口需要校验的参数上加上@Valid注解,并添加BindResult参数即可方便完成验证:

@RestController
@RequestMapping("user")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping("/addUser")
    public String addUser(@RequestBody @Valid User user, BindingResult bindingResult) {
        // 如果有参数校验失败,会将错误信息封装成对象组装在BindingResult里
        for (ObjectError error : bindingResult.getAllErrors()) {
            return error.getDefaultMessage();
        }
        return userService.addUser(user);
    }
}

这样当请求数据传递到接口的时候Validator就自动完成校验了,校验的结果就会封装到BindingResult中去,如果有错误信息我们就直接返回给前端,业务逻辑代码也根本没有执行下去。

现在可以看一下参数校验效果。我们故意给这个接口传递一个不符合校验规则的参数,先传递一个错误数据给接口,故意将password这个字段不满足校验条件:

错误参数:
在这里插入图片描述
正确参数:
在这里插入图片描述
这样是不是方便很多?不难看出使用Validator校验有如下几个好处:

  • 简化代码: 之前业务层那么一大段校验代码都被省略掉了。
  • 使用方便: 那么多校验规则可以轻而易举的实现,比如邮箱格式验证,之前自己手写正则表达式要写那么一长串,还容易出错,用Validator直接一个注解搞定。
  • 更多注解 释义:
  • 在这里插入图片描述
  • 减少耦合度: 使用Validator能够让业务层只关注业务逻辑,从基本的参数校验逻辑中脱离出来。使用Validator+ BindingResult已经是非常方便实用的参数校验方式了,在实际开发中也有很多项目就是这么做的,不过这样还是不太方便,因为每写一个接口都要添加一个BindingResult参数,然后再提取错误信息返回给前端。这样有点麻烦,并且重复代码很多,可以 直接将 BindingResult参数 去掉,也可以编写全局异常处理 !

去掉BindingResult参数:

@PostMapping("/addUser")
public String addUser(@RequestBody @Valid User user) {
    return userService.addUser(user);
}

去掉之后会试验一下,还是按照之前一样故意传递一个不符合校验规则的参数给接口。此时观察控制台可以发现接口已经引发MethodArgumentNotValidException异常了:
自动返回了非明文的错误信息,其实这样就已经达到我们想要的效果了,参数校验不通过自然就不执行接下来的业务逻辑。不过事情还没有完,异常是引发了,可并没有编写返回错误信息的代码呀,那参数校验失败了会响应什么数据给前端呢?

全局异常处理

参数校验失败会自动引发异常,我们当然不可能再去手动捕捉异常进行处理,不然还不如用之前BindingResult方式呢。又不想手动捕捉这个异常,又要对这个异常进行处理,那正好使用SpringBoot全局异常处理来达到一劳永逸的效果!
处理参数校验异常>>>:

首先,我们需要新建一个类,在这个类上加上
@ControllerAdvice或@RestControllerAdvice注解这个类就配置成全局处理类了。
(这个根据你的Controller层用的是@Controller还是@RestController来决定)然后在类中新建方法,在方法上加上@ExceptionHandler注解并指定你想处理的异常类型,接着在方法内编写对该异常的操作逻辑,就完成了对该异常的全局处理!我们现在就来演示一下对参数校验失败抛出的MethodArgumentNotValidException全局处理:

/**
 * 错误请求控制器
 */
@RestControllerAdvice
@CrossOrigin
public class exceptionController {
    public static Logger log = LoggerFactory.getLogger(exceptionController.class);

    /** 自定义 处理  MethodArgumentNotValidException 参数校验错误
     * @param e
     * @return 根据自定义返回结果 返回对应内容
     * 如果 使用的是 org.hibernate.validator jar 的话 使用:
     * MethodArgumentNotValidException.class 捕捉参数校验异常
     * 如果是 SpringBoot默认的校验  使用:
     * org.springframework.validation.BindException.class 捕捉参数校验异常
     * 我这里使用的是  SpringBoot默认的
     */
    @ExceptionHandler(value = BindException.class)
    public String BindException(BindException e) {
      StringBuilder sb = new StringBuilder();
      for (ObjectError error: e.getBindingResult().getAllErrors()) {
        sb.append(error.getDefaultMessage());
        sb.append("、");
      }
      String errorMsg = sb.substring(0,sb.length() - 1).toString();
      return errorMsg;
    }

}

404异常处理
因为 是后端接口都是API 返回的是JSON内容,并不是 使用模板引擎html页面,但是SpringBoot 在发生404的时候会自动去映射,会去找对应模版, 需要将SpringBoot的错误自动映射给关闭:
1、关闭 SpringBoot错误自动映射,打开application.properties

# 关闭SpringBoot 错误自动映射 ,如 404错误 会自动映射寻找对应模板,系统使用全局异常处理了返回结果
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

2、在全局异常类中 处理 NoHandlerFoundException 404 异常

/**
 * 错误请求控制器
 */
@RestControllerAdvice
@CrossOrigin
public class exceptionController {
    public static Logger log = LoggerFactory.getLogger(exceptionController.class);

    /** 自定义异常 处理  NoHandlerFoundException  404 异常
     * @param e
     * @return 根据自定义返回结果 返回对应内容
     */
    @ExceptionHandler(value = NoHandlerFoundException.class)
    public String NoHandlerFoundException(NoHandlerFoundExceptione) {
        String msg = "请求错误,接口路径错误!不存在";
        // org.springframework.web.servlet.NoHandlerFoundException 为 404错误
		return msg;
    }


	// 或者 在全局 异常中判断处理
    @ExceptionHandler(value = Exception.class)
    public StringexceptionHandler(Exception e){
        String msg = null;
        // org.springframework.web.servlet.NoHandlerFoundException 为 404错误
        if( e instanceof  NoHandlerFoundException){
            msg = "请求错误,接口路径错误!不存在";
        }else{
            msg = "请求错误[{"+e.getMessage()+"}]";
        }
        return msg ;
    }
  }

自定义异常

全局处理当然不会只能处理一种异常,用途也不仅仅是对一个参数校验方式进行优化。在实际开发中,如何对异常处理其实是一个很麻烦的事情。

1、 定义一个 运行异常实体类:

/**
 * 自定义异常
 */
public class itException extends  RuntimeException {
    private String errorMsg;

    public String getErrorMsg() {
        return errorMsg;
    }
	// 创建 构造方法,传入错误内容
    public itException (String message) {
        super(message);
        this.errorMsg = message;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }
}

2、在全局异常类中 处理 自定义的异常类

/**
 * 错误请求控制器
 */
@RestControllerAdvice
@CrossOrigin
public class exceptionController {
    public static Logger log = LoggerFactory.getLogger(exceptionController.class);

    /** 自定义异常类  itException 
     * @param e
     * @return 根据自定义返回结果 返回对应内容
     */
    @ExceptionHandler(value = itException .class)
    public String MethodArgumentNotValidException(itException e) {
 		String msg = e.getErrorMsg()
 		return msg; 
    }

}

3、使用:

	public static void main(String[] args) {
		// 测试自定义异常
		throw  new foundException("自定义异常");
	}

异常结果:忽略我的 这个异常类和上面的 itException不一样,因为 我临时用的一个异常类 随便娶的名字
在这里插入图片描述

到这里 SpringBoot写出简单的后端接口 就结束咯

posted @ 2020-11-17 11:41  z-7  阅读(1800)  评论(1编辑  收藏  举报
另外一个博客站点