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"));
}
}
- 在对项目打包的时候,会自动的执行单元测试
- 有错误的单元测试,在打包是可以自动跳过