一:拦截器的应用场景
1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page VIEW)等。
2、权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;
3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
4、通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现。
5、OpenSessionInView:如Hibernate,在进入处理器打开SESSION,在完成后关闭SESSION。
二:拦截器与过滤器的区别
1、拦截器是基于Java的反射机制的,而过滤器是基于函数回调。
2、拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
3、拦截器只能对ACTION请求起作用,而过滤器则可以对几乎所有的请求起作用。
4、拦截器可以访问ACTION上下文、值栈里的对象,而过滤器不能访问。
5、在ACTION的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
6、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
三:拦截器的实现
1.过滤器是JavaEE标准,采用函数回调的方式进行。是在请求进入容器之后,还未进入Servlet之前进行预处理,并且在请求结束返回给前端这之间进行后期处理。
-
@Override
-
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
-
System.out.println("before...");
-
chain.doFilter(request, response);
-
System.out.println("after...");
-
}
chain.doFilter(request, response);这个方法的调用作为分水岭。事实上调用Servlet的doService()方法是在chain.doFilter(request, response);这个方法中进行的。
2.拦截器是被包裹在过滤器之中的。
-
@Override
-
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
-
System.out.println("preHandle");
-
return true;
-
}
-
-
@Override
-
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
-
System.out.println("postHandle");
-
}
-
-
@Override
-
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
-
System.out.println("afterCompletion");
-
}
a.preHandle()这个方法是在过滤器的chain.doFilter(request, response)方法的前一步执行,也就是在 [System.out.println("before...")][chain.doFilter(request, response)]之间执行。
b.preHandle()方法之后,在RETURN ModelAndView之前进行,可以操控Controller的ModelAndView内容。
c.afterCompletion()方法是在过滤器返回给前端前一步执行,也就是在[chain.doFilter(request, response)][System.out.println("after...")]之间执行。
四:SpringMvc 拦截器和过滤器执行流程
五:实例
-
public class SystemAccessInterceper extends HandlerInterceptorAdapter {
-
-
private final String checkpointName = "DO_CHECKPOINT";
-
private final String shareType = "enjoylink_share";
-
String[] noFilters = ConfigureUtil.getStringArray("nofilter.urls");
-
-
private final Logger logger = Logger.getLogger(getClass());
-
-
@Override
-
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
-
throws Exception {
-
String userAgent = request.getHeader("user-agent");
-
userAgent = StringUtils.startsWith(userAgent, Constants.USER_AGENT) ? userAgent
-
: request.getHeader("x-user-agent");
-
String type = request.getParameter("shareType");
-
String requestUri = request.getRequestURI();
-
if (isFilter(requestUri)) {
-
return true;
-
}
-
logger.info("User-Agent:" + userAgent);
-
if (!StringUtils.equalsIgnoreCase(shareType, type) && (!StringUtils.startsWith(userAgent, Constants.USER_AGENT)
-
|| 2 > StringUtils.indexOfAny(userAgent, "|"))) {
-
logger.info("非法请求接口!!");
-
return false;
-
}
-
-
try {
-
if (StringUtils.contains(userAgent, "|")) {
-
String[] agts = userAgent.split("\\|");
-
request.setAttribute(Constants.HEAD_SYS, agts[1]);
-
request.setAttribute(Constants.HEAD_VERSION, agts[2]);
-
}
-
request.setAttribute(Constants.LOG_ACCESS_TIME, System.currentTimeMillis());
-
return super.preHandle(request, response, handler);
-
}
-
catch (Exception e) {
-
logger.error("拦截器验证失败!", e);
-
return false;
-
}
-
}
-
-
/**
-
* TODO: 检查是否需要过滤
-
*
-
* @param uri
-
* @return
-
*/
-
private boolean isFilter(String uri) {
-
if (org.apache.commons.lang3.ArrayUtils.isEmpty(noFilters)) {
-
return Boolean.TRUE;
-
}
-
-
for (String noFilter : noFilters) {
-
if (StringUtils.contains(uri, noFilter)) {
-
return Boolean.TRUE;
-
}
-
}
-
-
return Boolean.FALSE;
-
}
-
-
@Override
-
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
-
throws Exception {
-
super.afterCompletion(request, response, handler, ex);
-
Object obj = request.getAttribute(Constants.LOG_ACCESS_TIME);
-
if (null != obj) {
-
Object rb = request.getAttribute(Constants.RETURN_BODY);
-
long accessTime = (long) obj;
-
if (null == rb || StringUtils.isEmpty(rb.toString())) {
-
logger.info("不进行检查点处理!");
-
logger.info("处理请求" + request.getRequestURI() +"耗时"+ (System.currentTimeMillis() - accessTime) + "毫秒!");
-
return;
-
}
-
Object userId = request.getAttribute(Constants.REQUEST_USERID);
-
String system = request.getAttribute(Constants.HEAD_SYS).toString();
-
String version = request.getAttribute(Constants.HEAD_VERSION).toString();
-
-
logger.warn("处理请求|" + ((null == userId || "".equals(userId.toString())) ? "0" : userId.toString()) + "|"
-
+ system + "|" + version + "|" + request.getRequestURI() + "|"
-
+ GbdDateUtils.format(Calendar.getInstance().getTime(), "yyyy-MM-dd HH:mm:ss") + "|"
-
+ (System.currentTimeMillis() - accessTime) + "|毫秒!");
-
try {
-
HandlerMethod handlerMethod = (HandlerMethod) handler;
-
BusinessCheckPoint checkPoint = handlerMethod.getMethodAnnotation(BusinessCheckPoint.class);
-
if (null != checkPoint) {
-
String checkpointKey = checkPoint.checkName();
-
-
// 业务处理结果为正确时。发送积分或者信用累积
-
if (null != rb && null != userId && StringUtils.isNotEmpty(userId.toString())) {
-
ReturnBody returnBody = (ReturnBody) rb;
-
// 检查点检测,如果是检查点则发送消息
-
if (returnBody.getCode() > 0) {
-
// 发送检查点消息
-
CodeDesc codeDesc = new CodeDesc();
-
codeDesc.setJmsType(checkpointName);
-
codeDesc.setName(checkpointKey);
-
codeDesc.setBusinessCode(returnBody.getCheckpointCode());
-
codeDesc.setUserId(Integer.valueOf(userId.toString()));
-
JmsUtil.pushToUserQueue(codeDesc);
-
}
-
}
-
}
-
}
-
catch (Exception e) {
-
logger.error("发送积分消息失败!", e);
-
}
-
}
-
}
-
-
}
-
<!-- 拦截器配置 -->
-
<mvc:interceptors>
-
<bean class="com.gemdale.ghome.business.intercepter.SystemAccessInterceper" />
-
</mvc:interceptors>
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/28624388/viewspace-2130071/
,如需转载,请注明出处,否则将追究法律责任。