@Min(value = 18, message = "未成年少女禁止入门")
private Integer age;
在控制器的验证方法中加入:
@PostMapping(value = "/girls")
public Result girlAdd(@Valid Girl girl, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return ResultUtil.error(1, bindingResult.getFieldError().getDefaultMessage());
}
girl.setCupSize(girl.getCupSize());
girl.setAge(girl.getAge());
return ResultUtil.success(girlRepository.save(girl));
}
@valid用于验证参数的正确性,BindingResult对象用来显示错误信息!
使用方法:
引入依赖 starter-aop
pom.xml
org.springframework.boot
spring-boot-starter-aop
创建aspect包(放处理文件,包名随意,自己明白就好)
@Before("execution(public * com.hx.girl.GirlController.*(..))")
拦截GirlController中的所有方法,在方法运行前运行被Before注释的代码
execution()是最常用的切点函数,其语法如下所示:
@Pointcut 注解中填写的内容与 @Before @After 两注解是一样的
为了避免代码重复书写,定义一个公用方法,@Pointcut注解声明切入点
@Before @After 两注解直接复用该方法切入点
@Aspect
@Component
public class HttpAspect {
private final static Logger logger= LoggerFactory.getLogger(HttpAspect.class); //Logger引用org.slf4j 是Spring自带的日志框架
@Pointcut("execution(public * com.example.project.web.CustomerContorller.*(..))")
public void log(){
}
@Before("log()")
public void doBefore(){
logger.info("run before");
}
@After("log()")
public void doAfter(){
logger.info("run after");
}
}
用于记录http请求的信息的代码:
// 请求参数
ServletRequestAttributes attributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
// 请求对象
javax.servlet.http.HttpServletRequest request = attributes.getRequest();
// url
request.getRequestURL();
// method
request.getMethod();
// ip
request.getRemoteAddr();
// doBefore(JoinPoint joinPoint)
joinPoint.getSignature().getDeclaringTypeName() // 类名
joinPoint.getSignature().getName() // 类方法名
// 参数
joinPoint.getArgs()
//获取返回的内容
@AfterReturning(returning = "object", pointcut = "log()")
public void doAfterReturning(Object object){
logger.info("response={}",object.toString()); //添加toString()方法用于详细打印
}
写代码时发现重复时,即时优化。
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;
}
}
写ExceptionHandle类来捕获异常,同时使用ResultUtil的方法使数据格式统一。
@ControllerAdvice
public class ExceptionHandle{
@ExceptionHandle(value = Exception.class)
@ResponseBody
public Result handle(Exception e){
return ResultUtil.error(100,e.getMessage());
}
}
当需要对不同错误设置不同error code时,Exception就无法满足,于是就需要自定义一个Exception
public class GirlException extends RuntimeException{
private Integer code;
public GirlException(Integer code, String message){
super(message);
this.code = code;
}
...getset方法
}
@ControllerAdvice
public class ExceptionHandle{
@ExceptionHandle(value = Exception.class)
@ResponseBody
public Result handle(Exception e){
if(e instanceof GirlException){
GirlException ge = (GirlException) e;
return ResultUtil.error(ge.getCode(),ge.getMessage());
}else{
return ResultUtil.error(-1,"未知错误");
}
}
}
当抛的异常属于未知错误时,就会不知道具体错误信息,这时候就可以用日志将其打印记录下来。
@ControllerAdvice
public class ExceptionHandle{
private final static Logger logger= LoggerFactory.getLogger(ExceptionHandle.class);
@ExceptionHandle(value = Exception.class)
@ResponseBody
public Result handle(Exception e){
if(e instanceof GirlException){
GirlException ge = (GirlException) e;
return ResultUtil.error(ge.getCode(),ge.getMessage());
}else{
logger.error("[系统异常]{}",e);
return ResultUtil.error(-1,"未知错误");
}
}
}
ResultEnum 统一管理异常码和异常信息
public enum ResultEnum{
UNKOWN_ERROR(-1,"未知错误"),
SUCCESS(0."成功"),
PRIMARY_SCHOOL(100,"小学生"),
MIDDLE_SCHOOL(101,"初中生"),
;
private Integer code;
private String msg;
ResultEnum(Integer code, String msg){
this.code = code;
this.msg = msg;
}
...get方法
}
GirlException(resultEnum) 构造方法传枚举就可以了
@RunWith(SpringRunner.class)
@SpringBootTest
public class GrilServiceTest {
@Autowired
private GrilService grilService;
@Test
public void findOneTest(){
Girl girl = girlService.findOneTest(3);
Assert.assertEquals(new Integer(13),gril.getAge());
}
}
可以右键代码空白区域,选择Run "GrilServiceTest"测试整个类
测试controller 如果还用上面的那个方式测试就无法测试url的请求
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class GrilController {
@Autowired
private MockMvc mvc;
@Test
public void girlList() throws Exception {
mvc.perform(
MockMvcRequestBuilders.get("/girls")) //请求的url 如果请求是post,就改为.post("/girls"))
.andExpect(MockMvcResultMatchers.status().isOk()) //期望返回状态码是200
.andExpect(MockMvcResultMatchers.content().string("hi")); //期望返回内容是hi
}
}
在使用项目打包时,就会进行单元测试