1. pom引入

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-validation</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-web</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.projectlombok</groupId>
  11. <artifactId>lombok</artifactId>
  12. <optional>true</optional>
  13. </dependency>

image.png

2. 异常处理

  1. 全局异常拦截处理 ```java package com.afei.unified.handler;

import com.afei.unified.common.ResultVO; import com.afei.unified.common.enums.ResultCodeEnum; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.ArrayList; import java.util.List;

/**

  • @author shihengfei
  • @date 2020/8/7 15:39
  • @description: 全局异常处理类 */ @RestControllerAdvice @Slf4j public class GlobalExceptionHandler {

    /**

    • 自定义异常CustomException */ @ExceptionHandler(CustomException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ResultVO CustomExceptionHandler(CustomException e) { log.error(“api异常”); return new ResultVO<>(ResultCodeEnum.FAILED, e.getMsg()); }

      /**

    • 方法参数错误异常
    • @param e
    • @return */ @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ResultVO MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) { log.error(“方法参数错误异常”); List list=new ArrayList<>(); // 从异常对象中拿到ObjectError对象 if (!e.getBindingResult().getAllErrors().isEmpty()){

      1. for(ObjectError error:e.getBindingResult().getAllErrors()){
      2. list.add(error.getDefaultMessage().toString());
      3. }

      } // 提取错误提示信息进行返回 return new ResultVO<>(ResultCodeEnum.VALIDATE_FAILED, list); }

      /**

    • 全局未知异常
    • @param e
    • @return */ @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ResultVO ExceptionHandler(Exception e) { log.error(“未知异常”); // 返回未知异常 return new ResultVO<>(ResultCodeEnum.ERROR); } } b. 自定义异常java package com.afei.unified.handler;

      import com.afei.unified.common.enums.ResultCodeEnum; import lombok.Getter;

      /**

      • 自定义异常处理
      • @author shihengfei */ @Getter public class CustomException extends RuntimeException { private int code; private String msg;

        public CustomException() {

        1. this(ResultCodeEnum.FAILED);

        }

        public CustomException(ResultCodeEnum failed) {

        1. this.code=failed.getCode();
        2. this.msg=failed.getMsg();

        } } ```

        3. 统一响应

        a. 响应体 ```java package com.afei.unified.common;

      import com.afei.unified.common.enums.ResultCodeEnum; import lombok.Getter; import lombok.Setter;

      /**

      • @author shihengfei
      • @description: 自定义统一响应体 / @Getter @Setter public class ResultVO { /*

        • 状态码,比如1000代表响应成功 / private int code; /*
        • 响应信息,用来说明响应情况 / private String msg; /*
        • 响应的具体数据 */ private T data;

          public ResultVO(T data) { this(ResultCodeEnum.SUCCESS, data); }

          public ResultVO(ResultCodeEnum resultCode, T data) { this.code = resultCode.getCode(); this.msg = resultCode.getMsg(); this.data = data; } } b. 响应枚举java package com.afei.unified.common.enums;

      import lombok.Getter;

      /**

      • 响应码枚举
      • @author shihengfei */ @Getter public enum ResultCodeEnum {

        1. /** 1*** 通用错误 */
        2. SUCCESS(1000, "操作成功"),
        3. FAILED(1001, "接口错误"),
        4. VALIDATE_FAILED(1002, "参数校验失败"),
        5. ERROR(1003, "未知错误"),
        6. /** 2*** 用户错误 */
        7. USER_NOT_EXIST(2000,"用户不存在"),
        8. USER_LOGIN_FAIL(2001,"用户名或密码错误"),
        9. USER_NOT_LOGIN(2002,"用户还未登录,请先登录"),
        10. NO_PERMISSION(2003,"权限不足,请联系管理员");
        11. private int code;
        12. private String msg;

        ResultCodeEnum(int code, String msg) {

        1. this.code = code;
        2. this.msg = msg;
        3. }

        }

      1. c. 全局响应拦截包装
      2. ```java
      3. package com.afei.unified.handler;
      4. import com.afei.unified.common.ResultVO;
      5. import com.fasterxml.jackson.core.JsonProcessingException;
      6. import com.fasterxml.jackson.databind.ObjectMapper;
      7. import org.springframework.core.MethodParameter;
      8. import org.springframework.http.MediaType;
      9. import org.springframework.http.converter.HttpMessageConverter;
      10. import org.springframework.http.server.ServerHttpRequest;
      11. import org.springframework.http.server.ServerHttpResponse;
      12. import org.springframework.web.bind.annotation.RestControllerAdvice;
      13. import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
      14. /**
      15. * @author shihengfei
      16. * @description: 全局处理增强版Controller,避免Controller里返回数据每次都要用响应体来包装
      17. */
      18. @RestControllerAdvice(basePackages = {"com.afei.unified.controller"})
      19. public class ResponseControllerAdvice implements ResponseBodyAdvice<Object> {
      20. @Override
      21. public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> aClass) {
      22. // 如果接口返回的类型本身就是ResultVO那就没有必要进行额外的操作,返回false
      23. return !returnType.getGenericParameterType().equals(ResultVO.class);
      24. }
      25. @Override
      26. public Object beforeBodyWrite(Object data, MethodParameter returnType, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
      27. // String类型不能直接包装,所以要进行些特别的处理
      28. if (returnType.getGenericParameterType().equals(String.class)) {
      29. ObjectMapper objectMapper = new ObjectMapper();
      30. try {
      31. // 将数据包装在ResultVO里后,再转换为json字符串响应给前端
      32. return objectMapper.writeValueAsString(new ResultVO<>(data));
      33. } catch (JsonProcessingException e) {
      34. throw new CustomException();
      35. }
      36. }
      37. // 将原本的数据包装在ResultVO里
      38. return new ResultVO<>(data);
      39. }
      40. }

      4. 参数校验

      1. package com.afei.unified.model;
      2. import lombok.Builder;
      3. import lombok.Data;
      4. import lombok.NoArgsConstructor;
      5. import lombok.ToString;
      6. import javax.validation.constraints.Email;
      7. import javax.validation.constraints.NotNull;
      8. import javax.validation.constraints.Size;
      9. /**
      10. * @author shihengfei
      11. * @description: 用户
      12. */
      13. @Data
      14. @ToString
      15. @NoArgsConstructor
      16. public class User {
      17. @NotNull(message = "用户id不能为空")
      18. private Long id;
      19. @NotNull(message = "用户账号不能为空")
      20. @Size(min = 11, max = 20, message = "账号长度必须是11-20个字符")
      21. private String account;
      22. @NotNull(message = "用户密码不能为空")
      23. @Size(min = 8, max = 16, message = "密码长度必须是8-16个字符")
      24. private String password;
      25. @NotNull(message = "用户邮箱不能为空")
      26. @Email(message = "邮箱格式不正确")
      27. private String email;
      28. }

      5. 测试controller

      1. package com.afei.unified.controller;
      2. import com.afei.unified.common.enums.ResultCodeEnum;
      3. import com.afei.unified.handler.CustomException;
      4. import com.afei.unified.model.User;
      5. import org.springframework.web.bind.annotation.GetMapping;
      6. import org.springframework.web.bind.annotation.PostMapping;
      7. import org.springframework.web.bind.annotation.RequestBody;
      8. import org.springframework.web.bind.annotation.RestController;
      9. import javax.validation.Valid;
      10. /**
      11. * @author shihengfei
      12. * @description: 测试controller
      13. */
      14. @RestController
      15. public class DemoController {
      16. @GetMapping("/getUser")
      17. public User getUser() {
      18. try {
      19. // int i = 1/0;
      20. User user = new User();
      21. user.setId(1L);
      22. user.setAccount("12345678");
      23. user.setPassword("12345678");
      24. user.setEmail("12345678@qq.com");
      25. return user;
      26. }catch (Exception e){
      27. e.printStackTrace();
      28. throw new CustomException(ResultCodeEnum.FAILED);
      29. }
      30. }
      31. @PostMapping("/addUser")
      32. public void addUser(@Valid @RequestBody User user){
      33. }
      34. }

      6. 单元测试

      1. package com.afei.unified.controller;
      2. import com.afei.unified.model.User;
      3. import org.junit.jupiter.api.Test;
      4. import org.springframework.beans.factory.annotation.Autowired;
      5. import org.springframework.boot.test.context.SpringBootTest;
      6. @SpringBootTest
      7. public class DemoControllerTest {
      8. @Autowired
      9. private DemoController demoController;
      10. @Test
      11. public void getUser(){
      12. User user = demoController.getUser();
      13. System.out.println(user);
      14. }
      15. @Test
      16. public void addUser(){
      17. User user = new User();
      18. user.setId(2L);
      19. user.setAccount("1111111");
      20. user.setPassword("545425");
      21. user.setEmail("4456454@qq.com");
      22. demoController.addUser(user);
      23. }
      24. }