什么是AOP,面向切面的工程,可以通过类似于插入一个切点以实现一些业务,比如我们要做的登录拦截。
1.自定义注解
//注解使用在哪个上面
@Target({ElementType.METHOD})
//生命周期,在执行的时候
@Retention(RetentionPolicy.RUNTIME)
//
@Documented
@Mapping
//自定义注解类@GlobalInterceptor
public @interface GlobalInterceptor {
/***
* 校验参数
*
* @return
*/
boolean checkParams() default false;
/***
* 登录拦截器
* @return
*/
boolean checkLogin() default false;
/***
* 校验超级管理员
* @return
*/
boolean checkAdmin() default false;
}
2.声明切面类
-
声明切面类@Aapect
-
设置切点@Pointcut(@annotation(com.easypan.annotation.GlobalInterceptor))
-
设置执行方法@Before("requsetInterceptor"),在切点前进行执行
//声明是个切面类
@Aspect
//声明是个spring类的组件,并指定bean名
@Component("globalOperatcionAspect")
public class GlobalOperatcionAspect {
private static final Logger logger = LoggerFactory.getLogger(GlobalOperatcionAspect.class);
//定义基本需要校验的类型
private static final String TYPE_BASE[] = {"java.lang.String", "java.lang.Integer", "java.lang.Long"};
private final OrderedFormContentFilter formContentFilter;
public GlobalOperatcionAspect(OrderedFormContentFilter formContentFilter) {
this.formContentFilter = formContentFilter;
}
//定义切点,加了@GlobalInterceptor()进行拦截
@Pointcut("@annotation(com.easypan.annotation.GlobalInterceptor)")
//请求拦截
private void requsetInterceptor() {
}
//在切点方法requsetInterceptor()之前执行
@Before("requsetInterceptor()")
public void interceptorDo(JoinPoint point) throws BusinessException {
try{
//拿到的目标
Object target = point.getTarget();
//可以拿到的参数
Object[] args = point.getArgs();
String methodName = point.getSignature().getName();
//获取参数类型
Class<?>[] parameterTypes = ((MethodSignature)point.getSignature()).getParameterTypes();
//反射获取方法对象,sendEmailCode
Method method = target.getClass().getMethod(methodName, parameterTypes);
// 获取方法上的GlobalInterceptor注解
GlobalInterceptor interceptor = method.getAnnotation(GlobalInterceptor.class);
//没用注解直接返回,没有@GlobalInterceptor(checkParams = true)
if (interceptor == null) {
return;
}
/***
* 校验登录
*/
if(interceptor.checkLogin() || interceptor.checkAdmin()){
checkLogin(interceptor.checkAdmin());
}
/***
* 参数校验
*/
if (interceptor.checkParams()){
validateParams(method, args);
}
} catch (BusinessException e){
logger.error("全局拦截器异常");
throw e;
} catch (Exception e) {
logger.error("全局拦截器异常");
throw new BusinessException(ResponseCodeEnum.CODE_500);
} catch (Throwable e){
logger.error("全局拦截器异常");
throw new BusinessException(ResponseCodeEnum.CODE_500);
}
}
3.设置检查点(参数验证,登录验证)
可以设置检查点的有下面三个
public @interface GlobalInterceptor {
/***
* 校验参数
*
* @return
*/
boolean checkParams() default false;
/***
* 登录拦截器
* @return
*/
boolean checkLogin() default false;
/***
* 校验超级管理员
* @return
*/
boolean checkAdmin() default false;
}
验证是否需要登录
private void checkLogin(boolean checkAdmin) throws BusinessException {
//在方法类中获得session对象
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
SessionWebUserDto userDto = (SessionWebUserDto)session.getAttribute(Constants.SESSION_KEY);
if(null == userDto){
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
if(checkAdmin && !userDto.getAdmin()){
throw new BusinessException(ResponseCodeEnum.CODE_404);
}
}
使用方法
添加注解@GlobalInterceptor(checkLogin = True)
如果没有登录,会报错。
参数验证
//校验方法
private void validateParams(Method m, Object[] args) throws BusinessException {
Parameter[] paramters = m.getParameters();
for (int i = 0; i < paramters.length; i++) {
//参数类型
Parameter param = paramters[i];
//参数的值
Object value = args[i];
//获取参数上的VerifyParam注解
VerifyParam verifyParam = param.getAnnotation(VerifyParam.class);
if (verifyParam == null) {
continue;
}
//是否是基本类型,进行基本校验
if(ArrayUtils.contains(TYPE_BASE, param.getParameterizedType().getTypeName())){
checkValue(value, verifyParam);
}else{
}
}
}
private void checkValue(Object value, VerifyParam verifyParam) throws BusinessException {
Boolean isEmpty = value==null || StringTools.isEmpty(value.toString());
Integer length = value==null?0:value.toString().length();
/***
* 校验空
*/
if(isEmpty && verifyParam.required()){
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
/***
* 校验长度
*/
if(!isEmpty && (verifyParam.max() != -1 && length > verifyParam.max()||verifyParam.min() != -1 && length < verifyParam.min())){
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
/***
* 校验正则
*/
if(! isEmpty && !StringTools.isEmpty(verifyParam.regex().getRegex()) && !VerifyUtils.verify(verifyParam.regex(), String.valueOf(value))){
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
}
使用方法:
@GlobalInterceptor(checkParams = true)
public ResponseVO changeFileFolder(HttpSession session,
@VerifyParam(required = true) String fileIds,
@VerifyParam(required = true) String filePid
){
SessionWebUserDto webUserDto = getUserInfoFromSession(session);
fileInfoService.changeFileFolder(fileIds, filePid, webUserDto.getUserId());
//List<FileInfo> fileInfoList = fileInfoService.findListByParam(infoQuery);
return getSuccessResponseVO(null);
}
-
@GlobalInterceptor(checkParams = true, checkLogin = false)
-
@VerfyParam(min = 1, max = 100, required = true, regex = VerifyRegexEnum.EMAIL) ,最大值,最小值,正则化,是否需要验证
-
其中VerifyParam verifyParam = param.getAnnotation(VerifyParam.class);使用参数上的注解内容
3.使用@GlobalInterceptor进行登录拦截
@RequestMapping("/login")
//需要参数验证,不需要登录
@GlobalInterceptor(checkParams = true, checkLogin = false)
public ResponseVO login(HttpSession session,
@VerifyParam(required = true) String email,
@VerifyParam(required = true) String password,
@VerifyParam(required = true) String checkCode) throws BusinessException {
try{
//判断图像验证码是否正确
if (!checkCode.equalsIgnoreCase(key_code)) {
throw new BusinessException("图片验证码不正确");
}
//
SessionWebUserDto sessionWebUserDto = userInfoService.login(email, password);
session.setAttribute(Constants.SESSION_KEY, sessionWebUserDto);
return getSuccessResponseVO(sessionWebUserDto);
} finally {
session.removeAttribute(Constants.CHECK_CODE_KEY);
key_code = null;
}
}