AOP为Aspect Oriented Programming的缩写,意为:面向切面编程
使用spring框架开发基本都会使用AOP功能,实现项目对日志记录,性能统计,安全控制,事务处理,异常处理等
前两天项目开发中使用@Aspect注解做了登录验证,以后会经常用到,所以把主要代码提取出来,在此记录一下。
首先,在spring配置文件中引入
<!-- 支持Controller的AOP代理 -->
<aop:aspectj-autoproxy />
SecurityAspect.java--拦截类
package com.wdk.mpm.comm.aspect;
import com.wdk.mpm.annotation.IgnoreSecurity;
import com.wdk.mpm.comm.authorization.SecurityLocaleManager;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
/**
* Title:Aspect定义的切面,实现一个登录验证
*/
@Component
@Aspect
public class SecurityAspect {
private static final Logger log = Logger.getLogger(SecurityAspect.class);
private SecurityLocaleManager securityLocaleManager;
public SecurityLocaleManager getSecurityLocaleManager() {
return securityLocaleManager;
}
@Resource(name = "securityLocaleManager")
public void setSecurityLocaleManager(SecurityLocaleManager securityLocaleManager) {
this.securityLocaleManager = securityLocaleManager;
}
//@Around是方法执行的前后均调用
@Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
public Object execute(ProceedingJoinPoint pjp) throws Throwable {
//先要获取目标方法中的信息
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
log.debug("methodSignature : " + methodSignature);
Method method = methodSignature.getMethod();
//IgnoreSecurity.class 自定义注解 用于忽视安全性检查 method.isAnnotationPresent 判断方法上是否有注解
//若目标方法忽略了安全性检查,则直接调用目标方法
if (method.isAnnotationPresent(IgnoreSecurity.class)) {
log.debug(method.getName() + "忽视安全检查");
return pjp.proceed();
} else {
//获得方法参数列表
Object[] args = pjp.getArgs();
//获取请求中的request对象
HttpServletRequest request = (HttpServletRequest) args[0];
//这个方法就是获取session用户信息进行验证
boolean falt = securityLocaleManager.checkUserLogin(request);
if (!falt) {
//如果校验失败,直接抛出异常,如果在项目中可以做个全局异常处理进行页面跳转等操做
throw new Exception("安全检查未通过,请先登录!");
} else {
log.debug("安全检查通过");
return pjp.proceed();
}
}
}
}
IgnoreSecurity.java 自定义注解,使用此注解,不进行安全检查
package com.wdk.mpm.annotation;
import java.lang.annotation.*;
/**
* Title:自定义注解
* Description: 使用此注解忽略安全检查
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreSecurity {
}
UserController.java
SecurityAspect中使用@annotation(org.springframework.web.bind.annotation.RequestMapping) 定义使用@RequestMapping才会被拦截
@RequestMapping("/queryUser")
public void queryUser(HttpServletRequest request,
HttpServletResponse response) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
map.put("userName", request.getParameter("name"));
List<User> userList = userService.findUserPageHelper(map);
JSONArray jsonArray = JSONArray.fromObject(userList);
log.info("request: users/queryUser , result: " + userList.size());
ResponseUtil.write(response, jsonArray);
}
上述没有加@IgnoreSecurity,不登录,直接访问queryUser方法会被拦截
增加@IgnoreSecurity
@IgnoreSecurity
@RequestMapping("/queryUser")
public void queryUser(HttpServletRequest request,
HttpServletResponse response) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
map.put("userName", request.getParameter("name"));
List<User> userList = userService.findUserPageHelper(map);
JSONArray jsonArray = JSONArray.fromObject(userList);
log.info("request: users/queryUser , result: " + userList.size());
ResponseUtil.write(response, jsonArray);
}
不登录也可以直接访问queryUser方法