Java 如何在控制器方法之前检查参数值格式?
在我的控制器中,我有如下方法:Java 如何在控制器方法之前检查参数值格式?,java,spring,spring-mvc,spring-aop,Java,Spring,Spring Mvc,Spring Aop,在我的控制器中,我有如下方法: public QueryResult<TrsAccount> listExclude(String codeAccount, String searchFilter, String order, int pageNumber, int pageSize){} 因为这在我的应用程序中非常常见,而且不仅仅是这种情况,我需要一种检查参数格式的通用方法。我现在使用的是AOP,其中: @Aspect public class HijackBefore
public QueryResult<TrsAccount> listExclude(String codeAccount, String searchFilter, String order, int pageNumber,
int pageSize){}
因为这在我的应用程序中非常常见,而且不仅仅是这种情况,我需要一种检查参数格式的通用方法。我现在使用的是AOP,其中:
@Aspect
public class HijackBeforeMethod {
@Pointcut("within(@org.springframework.stereotype.Controller *)")
public void controllerBean() {
}
@Pointcut("execution(* *(..))")
public void methodPointcut() {
}
@Before(value = "controllerBean() && methodPointcut()", argNames = "joinPoint")
public void before(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Object[] args = joinPoint.getArgs();
String[] paramNames = signature.getParameterNames();
for (int count = 0; count < paramNames.length; count++) {
String tempParam = paramNames[count];
Object tempValue = args[count];
if (tempParam.toLowerCase().equalsIgnoreCase("codeAccount") && Assert.isNotNull(tempValue)
&& Assert.isNotEmpty((String) tempValue)) {
Assert.TRUE(((String) tempValue).matches("^[0-9]{1,20}$"));
}
}
}
}
@方面
公共类劫持方法{
@切入点(“在(@org.springframework.stereotype.Controller*)内)
公共无效控制器bean(){
}
@切入点(“执行(**(..)”)
公共void方法切入点(){
}
@在(value=“controllerBean()&&methodPointcut()”之前,argNames=“joinPoint”)
前公共无效(连接点连接点){
MethodSignature=(MethodSignature)joinPoint.getSignature();
对象[]args=joinPoint.getArgs();
字符串[]paramNames=signature.getParameterNames();
对于(int count=0;count
如您所见,这是一个非常基本且容易出错的代码段。是否有更好的解决方案???不建议在控制器中使用AOP。更好的方法是,但这可能需要将字符串包装到值对象中,然后相应地对其进行注释 如果您坚持用AOP解决这个问题,就像前面所说的那样,使用
Bean验证更可取
首先,定义一个从org.springframework.validation.Validator
扩展而来的类,如下所示:
@Component
public class CodeAccountValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return String.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
if (Assert.isNotNull(target) && Assert.isNotEmpty((String) target)) {
Assert.TRUE(((String) target).matches("^[0-9]{1,20}$"));
}
}
}
用AOP解决这个问题是不应该做的。而是使用对象绑定属性并验证该对象
public class QueryCriteria {
private String codeAccount;
private String searchFilter;
private int pageNumber;
private int pageSize;
private String order;
// Getters / Setters.
}
然后修改控制器方法
public QueryResult<TrsAccount> listExclude(@Valid QueryCriteria criteria, BIndingResult result) { ... }
在控制器方法的@InitBinder
中注册此验证器
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setValidator(new QueryCriteriaValidator());
}
当使用JSR-303时,您不需要这个,您可以简单地用@模式注释codecomport
字段
@Pattern(regexp="^[0-9]{1,20}$")
private String codeAccount;
验证与SpringMVC以及使用I18N的错误报告一起工作得很好。因此,不要试图用异常来绕过它,而是使用框架
我建议您阅读和Spring参考指南 我怎样才能用ControllerAdvice做到这一点?谢谢,只是不要。。。使用对象并通过JSR303验证或自定义验证程序验证该对象。有趣,但CodeAccountValidator
不起作用。参数codeAccount
可以使用@RequestParam注释吗?可能,但这里没有。这有什么区别吗?请按照@M.Deinum所说的去做,这是一个标准的解决方案。我的需要一些更多的设置,你可以检查。
public QueryCriteriaValidator implements Validator {
private final Pattern ACCOUNT_EXPR = Pattern.compile("^[0-9]{1,20}$");
public boolean supports(Class<?> clazz) {
return QueryCriteria.isAssignable(clazz);
}
public void validate(Object target, Errors errors) {
final QueryCriteria criteria = (QueryCriteria) target;
if (!ACCOUNT_EXPR.matcher(criteria.getCodeAccount()).matches()) {
errors.rejectValue("codeAccount", "invalid.format");
}
}
}
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setValidator(new QueryCriteriaValidator());
}
@Pattern(regexp="^[0-9]{1,20}$")
private String codeAccount;