功能:所有的方法中的参数都封装在一个实体类中,基于aop实现统一的验证。那么有人要说了,假如我有一个参数param1,现在两个方法A, B其中A方法需要验证参数param1,B方法又不需要验证怎么办呢?spring-boot提供了参数分组的概念,下面是一个比较完整的例子。基于注解 aop的分组参数验证,下面的例子还包括了全局异常处理,算是生产实践可以直接借鉴的,如果有不懂得地方请留言。
一:Control层
@RestController
public class SearchControl {
@Autowired
private LoginService loginService;
@RequestMapping(value = "/search", method = RequestMethod.GET)
public void getIndex(HttpServletResponse response) throws IOException {
System.out.println( "search" );
response.sendRedirect( "index.html" );
}
// @CrossOrigin
// @ResponseBody
// @RequestMapping(value = "/list", method = RequestMethod.GET)
// public Map searchAndCount(@RequestParam("offset") Integer offset, @RequestParam("size") Integer size) {
// System.out.println( "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" );
// return loginService.searchAndCount( offset, size );
// }
@CrossOrigin
@ResponseBody
@ParamValid
@RequestMapping(value = "/list", method = RequestMethod.GET)
public Map searchAndCount(@Validated(value = ParamVerify.Userlist.class) ParamVerify paramVerify, BindingResult result) {
System.out.println( "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" );
Integer offset = paramVerify.getOffset();
Integer size = paramVerify.getSize();
return loginService.searchAndCount( offset, size );
}
/*
* @author pg
* @date 2019-09-11 17:38
* @param paramVerify 类为自定义参数验证的类,接口中传入的方法都会
* 被这个类的属性接受并做了合法性的验证,使得传入service层的参数都是
* 合法的,若是验证没有通过,就会抛出异常。 这个异常会被GlobalExceptionHandle根据异常类型捕捉处理
* @return-type Map
*/
@CrossOrigin
@ResponseBody
@ParamValid
@RequestMapping(value = "/userinfo", method = RequestMethod.GET)
public Object test(@Validated(value = ParamVerify.Userinfo.class) ParamVerify paramVerify, BindingResult result) {
System.out.println( "111111111111111111111111111111111111111111111111111111111111111111111111" );
// BindingResult results
// if (results.hasErrors()) {
// for (ObjectError objectError : results.getAllErrors()) {
// String errormessage= objectError.getObjectName() + ": " + objectError.getDefaultMessage();
// throw new IllegalParamException(errormessage);
// }
// }
String username = paramVerify.getUsername();
Integer offset = paramVerify.getOffset();
Integer size = paramVerify.getSize();
return loginService.searchAndCountUser( username, offset, size );
}
}
二:AOP
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamValid {}
import java.util.List;
@Aspect
@Configuration
@Component
public class ParamValidAspect {
private static final org.slf4j.Logger log = LoggerFactory.getLogger(ParamValidAspect.class);
@Around("@annotation(paramValid)")
public Object paramValid(ProceedingJoinPoint joinPoint, ParamValid paramValid) throws Throwable {
BindingResult bindingResult = null;
for(Object arg:joinPoint.getArgs()){//遍历被通知方法的参数列表
if(arg instanceof BindingResult){
bindingResult = (BindingResult) arg;
}
}
if(bindingResult != null){
if(bindingResult.hasErrors()){
System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
String errorInfo = "";
List errors = bindingResult.getFieldErrors();//获取字段参数不合法的错误集合
for(FieldError error : errors){
errorInfo = errorInfo + "[" + error.getField() + " " + error.getDefaultMessage() + "]";
}
//下面是我自定义的异常,注意在这里我抛出的异常,会由全局的异常处理类处理。
throw new IllegalParamException("参数校验异常:" + errorInfo);
}
}else {
System.out.println("####################################################");
}
System.out.println("成功。。成功....成功成功成功成功成功成功成功成功成功成功成功成功成功成功成功成功成功成功成功成功成功成功成功");
return joinPoint.proceed();//执行目标方法
}
}
三:参数注解类
package com.log.service.demo.Common;
import org.springframework.stereotype.Component;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Component
public class ParamVerify {
public interface Userinfo{}
public interface Userlist{}
//开启分组验证, 在这里用户详细信息要验证 name offset size 用户列表只需验证offset size
@NotBlank(message = "username 不能为null也不能为空字符串",groups = Userinfo.class)
private String username;
@Min( value = 1, message = "offset 越界 最小值为1" ,groups = {Userinfo.class,Userlist.class})
private Integer offset;
@Min( value = 1, message = "size 越界 最小值为1" ,groups = {Userinfo.class,Userlist.class})
private Integer size;
public Integer getOffset() {
return offset;
}
public void setOffset(Integer offset) {
this.offset = offset;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
@Override
public String toString() {
return "ParamVerify{" +
"username='" + username + '\'' +
", offset=" + offset +
", size=" + size +
'}';
}
}
五. 全局异常处理类 以及自定义的异常
package com.log.service.demo.ExceptionHandle;
import com.log.service.demo.Common.HttpCode;
import com.log.service.demo.Common.LogHelper;
import com.log.service.demo.Exception.IllegalParamException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandle {
private static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandle.class);
@ExceptionHandler(value = IllegalParamException.class)
public Object jsonErrorHandler(HttpServletRequest req, IllegalParamException e) throws Exception {
Map result = new HashMap<>();
result.put("code", HttpCode.SERVER_ERROR.getCode());
result.put("message",e.getMessage());
LogHelper.warn(logger,"参数不合法 - Url:[{}],Params:[{}]",req.getRequestURI(),req.getQueryString());
return result;
}
}
package com.log.service.demo.Exception;
public class IllegalParamException extends RuntimeException {
public IllegalParamException(String msg) {
super(msg);
}
}
//@RestControllerAdvice表明这是一个全局异常处理的类 ,
//@ExceptionHandler(value = IllegalParamException.class)表明下面的方法是处理
//IllegalParamException.class的异常的方法,这个类就是我自定义的异常。