SpringBoot参数非空校验在网上已经有很多资料了,自己最近要实现这一个功能,大概看了下觉得没什么难度,不想在过程中还是遇到了一些问题,在此记录,希望有遇到和我一样问题的人和过路大神不吝指教。
需求是做一个全局请求参数非空校验和异常拦截,spring提供的@Validated和Hibernate提供的@Valid目前不支持请求参数为基本类型的非空判断,只能是请求参数封装为对象时,判断对象属性非空,所以要自己实现一个对基本类型的非空判断。
首先说下网上原创转载最多的一个思路:实现一个指向方法的注解,注解中创建一个String[]属性,用来存放方法中需要非空判断的参数的名称 -----> 创建AOP,切点为注解的方法,增强方法中拿到注解中的String[],然后遍历判断是否为空,如果为空则抛出一个自定义异常 -----> 实现一个全局异常处理类,捕获抛出的自定义异常,进行后续处理。
首先说下根据这个思路的实现非常简单,也很实用,只是有两个吹毛求疵的问题。第一,注解需要写成@CheckParam({param1,param2})这样的形式加在方法上,还需要手动写param1,param2这样的要进行非空判断的参数的名称,而不是像@RequestParam注解直接加在参数上就OK了。第二,@RequestParam注解本身会判断非空,一起使用时,自己的注解无效。
下面先说第一个问题,这个问题首先想到拦截器实现。
代码1:继承HandlerInterceptorAdapter ,实现拦截器。代码说明:(代码中的CheckParamNull是自定义注解,ResponseBo是自定义的json返回类)
1 public class ParameterNotBlankInterceptor extends HandlerInterceptorAdapter { 2 //在请求处理之前进行调用(Controller方法调用之前 3 @Override 4 public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { 5 6 //如果不是映射到方法直接通过 7 if (!(o instanceof HandlerMethod)) { 8 return true; 9 } 10 HandlerMethod handlerMethod = (HandlerMethod) o; 11 Parameter[] methodParameters = handlerMethod.getMethod().getParameters(); 12 for (int i = 0; i< methodParameters.length; i++){ 13 if(methodParameters[i].getAnnotation(ParamNotBlank.class) != null){ 14 CheckParamNull noblank =methodParameters[i].getAnnotation(CheckParamNull.class); 15 Object obj = httpServletRequest.getParameter(methodParameters[i].getName()); 16 httpServletResponse.setCharacterEncoding("UTF-8"); 17 if (obj == null){ 18 httpServletResponse.getWriter().write(JSON.toJSONString(ResponseBo.error(noblank.message()))); 19 return false; 20 }else if(obj instanceof String && StringUtils.isBlank((String)obj)){ 21 httpServletResponse.getWriter().write(JSON.toJSONString(ResponseBo.error(noblank.message()))); 22 return false; 23 } 24 return true; 25 } 26 } 27 return true; 28 } 29 30 //请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后) 31 @Override 32 public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { 33 34 } 35 36 //在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作) 37 @Override 38 public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { 39 40 } 41 }