前言
参数验证是一个常见的问题,无论是前端还是后台,都需要对用户输入进行验证,以此来保证系统数据的正确性。对于web来说,有些人可能理所当然的想在前端验证就行了,但是这样是非常错误的想法,前端代码对于用户来说是透明的,稍微有点技术的人就可以绕过这个验证,直接提交数据到后台。无论是前端网页接口的提交还是提供给外部的接口,参数验证随处可见,也是必不可少的。前端做验证只是为了用户体验,比如控制按钮的显示隐藏,单页应用的路由跳转等等,后端才是最重的保障。总之一切用户的输入都是不可信的,需要我们去进行验证辨别。
常见的验证方式
前端的校验是必须的,后台的校验更是必须的,下面介绍几种验证的方式:
1.表现层验证:SpringMVC提供对JSR-303的表现层验证;
2.业务逻辑层验证:Spring3.1提供对业务逻辑层的方法验证(当然方法验证也可以出现在其他层,但个人认为方法验证应该属于业务逻辑层);
3.DAO层验证:Hibernate提供DAO层的模型数据的验证;
4.数据库端的验证:通过数据库约束来进行;
5.客户端验证支持:JSR-303页提供编程式验证支持
1.通过if-if判断
if(string.IsNullOrEmpty(info.UserName))
{
return FailJson("用户名不能为空");
}
这种方式简单,但是,参数多了的话就会很繁琐了;
2.自定义注解实现参数校验
切面拦截controller方法,然后捕获带@ChechParam注解方法参数实例,最后反射实例校验。
controller:
@RequestMapping(value = "update" )
@ResponseBody
public ResultBean update(@CheckParam User user){
return ResultBean.ok();
}
model:
public class User implements Serializable{
@CheckParam(notNull = true)
private String username;
}
annotation:
@Target(value={ElementType.PARAMETER,ElementType.FIELD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CheckParam {
boolean notNull() default false;
}
aspect:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@Component
@Aspect
public class CheckParamAspect {
@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
public void methodPointCut() {}
/**
* 环绕切入方法
**/
@Around("methodPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature msig = (MethodSignature) point.getSignature();
Method method = msig.getMethod();
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
Object[] args = point.getArgs();
for (int i = 0; i < args.length; i++) {
Object obj = args[i];
MethodParameter mp = new MethodParameter(method,i);
mp.initParameterNameDiscovery(u);
GenericTypeResolver.resolveParameterType(mp, method.getClass());//Spring处理参数
//String paramName = mp.getParameterName();//参数名
CheckParam anno = mp.getParameterAnnotation(CheckParam.class);//参数注解
if(anno != null){
check(o