imooc-SpringBoot进阶之Web进阶

本文档介绍了SpringBoot在Web领域的进阶内容,包括表单验证,使用AOP处理请求,统一异常处理以及单元测试。通过@Min等注解实现表单验证,利用AOP实现面向切面编程,如@Before和@After注解。此外,还讲解了如何创建统一的异常处理机制和进行Service与API的单元测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

imooc-SpringBoot进阶之Web进阶

第1章 课程介绍

第2章 Web进阶

2-0 表单验证

  • 设置需要验证的属性

    • 实体类中,在属性前加@Min/.注解,其中有value设置阈,message设置返回信息

      @Min(value = 20 , message = "金额少于20")
      private BigDecimal money;
      
    • controller中,传入整个实体(而不是某一属性),并加注解@Vaild,并加入参数BindingResult对象储存信息

      /**
       * 创建红包(发红包)
       */
      @PostMapping("/luckymoney")
      public Luckymoney create(@Valid Luckymoney luckymoney,BindingResult bindingResult){
          if (bindingResult.hasErrors()){
              System.out.println(bindingResult.getFieldError().getDefaultMessage());
              return null;
          }
          luckymoney.setProducer(luckymoney.getProducer());
          luckymoney.setMoney(luckymoney.getMoney());
          return repository.save(luckymoney);
      }
      

2-1.2.3 使用AOP处理请求

  • AOP是一种编程范式

    • 与语言无关,是一种编程思想
      • 面向切片(AOP)
      • 面向对象(OOP)
      • 面向过程(POP)
    • 将通用逻辑从业务逻辑中分离出来
  • @Before注解:在方法执行之前执行

    @After注解:在方法执行之后执行

    @Aspect
    @Component
    public class HttpAspect {
    
       //拦截controller类中list方法的任何参数
        @Before("execution(public * com.imooc.luckymoney.controller.LuckymoneyController.list(..))")
      //拦截controller类中任何方法
      @Before("execution(public * com.imooc.luckymoney.controller.LuckymoneyController.*(..))")
        public void log(){
            System.out.println("1");
        }
      
      @After("execution(public * com.imooc.luckymoney.controller.LuckymoneyController.*(..))")
        public void doAfter(){
            System.out.println("2");
        }
    }
    
  • @Pointcut注解:设置切点,在其他拦截中直接调用log()方法

    @Aspect
    @Component
    public class HttpAspect {
    
      @Pointcut("execution(public * com.imooc.luckymoney.controller.LuckymoneyController.*(..))")
        public void log(){
        }
      
      @Before("log()")
        public void doBefore(){
            System.out.println("1");
        }
      
      @After("log()")
        public void doAfter(){
            System.out.println("2");
        }
    }
    
  • 记日志建议采用Logger类中的几个级别,而不是直接打印在控制台

    @Aspect
    @Component
    public class HttpAspect {
      
      private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
    
      @Pointcut("execution(public * com.imooc.luckymoney.controller.LuckymoneyController.*(..))")
        public void log(){
        }
      
      @Before("log()")
        public void doBefore(){
            logger.info("info");
            logger.error("error");
        }
    }
    
  • 记录一次http请求及处理结果

    @Aspect
    @Component
    public class HttpAspect {
    
        private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
    
        @Pointcut("execution(public * com.imooc.luckymoney.controller.LuckymoneyController.*(..))")
        public void log(){}
    
        //记录http请求的内容
        @Before("log()")
        public void doBefore(JoinPoint joinPoint){
    
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
    
            //url
            logger.info("url={}",request.getRequestURL());
    
            //method
            logger.info("method={}",request.getMethod());
    
            //ip
            logger.info("ip={}",request.getRemoteAddr());
    
            //类方法
            logger.info("class_method={}",joinPoint.getSignature().getDeclaringTypeName() + "." +joinPoint.getSignature().getName());
    
            //参数
            logger.info("args={}",joinPoint.getArgs());
    
        }
    
        //记录http请求后,服务器返回的结果
        @AfterReturning(returning = "object",pointcut = "log()")
        public void doAfterReturning(Object object){
            logger.info("response={}",object.toString());
        }
    
    }
    

2-4.5.6 统一异常处理

  • 统一成功和失败的返回结果格式

    • Result实体类为格式

      /**
       * http请求返回的最外层对象
       */
      public class Result<T> {
      
          //错误码
          private Integer code;
          //提示信息
          private String msg;
          //具体的内容
          private T data;
      
          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; }
      
          public T getData() { return data; }
          public void setData(T data) { this.data = data; }
      }
      
    • 封装ResultUtil小工具

      public class ResultUtil {
      
          public static Result success(Object object){
              Result result = new Result();
              result.setCode(0);
              result.setMsg("成功");
              result.setData(object);
              return result;
          }
      
          public static Result success(){
              return success(null);
          }
      
          public static Result error(Integer code,String msg){
              Result result = new Result();
              result.setCode(code);
              result.setMsg(msg);
              return result;
          }
      }
      
    • 在controller中应用

      /**
       * 创建红包(发红包)
       */
      @PostMapping("/luckymoney")
      public Result<Luckymoney> create(@Valid Luckymoney luckymoney, BindingResult bindingResult){
          if (bindingResult.hasErrors()){
              return ResultUtil.error(1,bindingResult.getFieldError().getDefaultMessage());
          }
      
          luckymoney.setProducer(luckymoney.getProducer());
          luckymoney.setMoney(luckymoney.getMoney());
      
          return ResultUtil.success(repository.save(luckymoney));
      }
      
  • 统一异常处理

    • 采用枚举的方式,进行对返回给客户端的错误信息进行统一管理

      public enum ResultEnum {
      
          UNKNOW_ERROR(-1,"未知错误"),
          SUCCESS(0,"成功"),
          EQUAL_TEN(100,"刚好10元"),
          NOT_TEN(101,"不是10元"),
      
          ;
      
          private Integer code;
          private String msg;
      
          ResultEnum(Integer code, String msg) {
              this.code = code;
              this.msg = msg;
          }
      
          public Integer getCode() { return code; }
      
          public String getMsg() { return msg; }
      }
      
    • 新建自己的异常类,继承RuntimeException(spring框架只对RuntimeException抛出的异常进行事务回滚)

      public class LuckymoneyException extends RuntimeException{
      
          private Integer code;
      
          public LuckymoneyException(ResultEnum resultEnum) {
              super(resultEnum.getMsg());
              this.code = resultEnum.getCode();
          }
      
          public Integer getCode() { return code; }
          public void setCode(Integer code) { this.code = code; }
      }
      
    • service层中进行逻辑处理,不同的条件处理直接按异常抛出

      public void getMoney(Integer id) throws Exception{
          Luckymoney luckymoney = repository.findById(id).orElse(null);
          BigDecimal money = luckymoney.getMoney();
          if (money.equals(new BigDecimal("10"))){
                  //刚好10元钱
                  throw new LuckymoneyException(ResultEnum.EQUAL_TEN);
              }else {
                  //不是10元
                  throw new LuckymoneyException(ResultEnum.NOT_TEN);
              }
      }
      
    • controller层中直接调用service层中的方法

      @GetMapping("/luckymoneys/getMoney/{id}")
      public void getMoney(@PathVariable("id") Integer id) throws Exception{
          service.getMoney(id);
      }
      
    • 新建一个ExceptionHandle进行异常的捕获,达到异常可以直接按统一格式返回给客户端的效果

      @ControllerAdvice
      public class ExceptionHandle {
        
      private final static Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);
      
          @ExceptionHandler(value = Exception.class)
          @ResponseBody
          public Result handle(Exception e){
              if (e instanceof LuckymoneyException){
                  LuckymoneyException luckymoneyException = (LuckymoneyException) e;
                  return ResultUtil.error(luckymoneyException.getCode(),luckymoneyException.getMessage());
              }else {
                  logger.error("【系统异常】{}",e);
                  return ResultUtil.error(-1,"未知错误");
              }
          }
      }
      

2-7 单元测试

测试Service
  • 自己创建测试类

    @Runwith(SpringRunner.class)
    @SpringBootTest
    public class LuckymoneyServicesTest {
    
        @Autowired
        private LuckymoneyService luckymoneyService;
    
        @Test
        public void findOneTest(){
            Luckymoney luckymoney = luckymoneyService.findOne(3);
            Assert.assertEquals(new BigDecimal(122),luckymoney.getMoney());
        }
      
    }
    
  • service中的方法>>右键>>GoTo>>Test>>Create

测试API
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class LuckymoneyControllerTest {

    @Autowired
    private MockMvc mvc;

    @Test
    public void girlLisr() throws Exception{
        mvc.perform(MockMvcRequestBuilders.get("/luckymoneys"))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.content().string("abc"));
    }

}
  • 在对项目打包的时候,会自动的执行单元测试
    • 有错误的单元测试,在打包是可以自动跳过

第3章 课程总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值