Spring拦截器中通过request获取到该请求对应Controller中的method对象
背景:项目使用Spring 3.1.0.RELEASE,从dao到Controller层全部是基于注解配置。我的需求是想在自定义的Spring拦截器中通过request获取到该请求对应于Controller中的目标method方法对象。Controller和拦截器代码如下:
AdminController
@Controller
@RequestMapping("/admin")
public class AdminController { /**
* init:初始页面. <br/>
*
* @author chenzhou
* @param request 请求
* @param response 响应
* @return 登陆页
* @since JDK 1.6
*/
@RequestMapping("/init")
public ModelAndView init(HttpServletRequest request,
HttpServletResponse response){
Map<String, Object> model = new HashMap<String, Object>();
List<Role> roleList = this.adminService.getRoleList();
model.put("roleList", roleList);
return new ModelAndView(this.getLoginPage(), model);
} //……
}
LoginInterceptor
public class LoginInterceptor extends HandlerInterceptorAdapter {
/**
* This implementation always returns <code>true</code>.
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
/**
* This implementation is empty.
*/
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
}
/**
* This implementation is empty.
*/
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
servlet xml配置文件定义:
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<bean class="com.chenzhou.examples.erm.util.interceptor.LoginInterceptor"/>
</list>
</property>
</bean>
我的需求是想在preHandle方法中通过request获取该请求访问的目标Controller中的方法对象。之前找了很久也没有找到比较好的方案,就采取了最老土的通过比较requestURL和Controller类和方法上的RequestMappingURL来进行获取,这样也能勉强实现,但是这种方式我自己都觉得特别恶心。首先,这种方式需要使用反射来获取Controller中的所有方法,然后遍历method数组,逐个进行RequestMappingURL的比对,效率低下。其次,如果RequestMapping定义了类似于@RequestMapping("/{id}")这种动态参数url,则无法进行比较。
因为上面这种方式不好,我就一直想找一个更好的方案。不得已只能向人求助,第一个就想到了Iteye上对于Spring研究得很熟悉的jinnianshilongnian龙年兄,我相信经常上iteye的博友们对龙年兄应该都很熟悉。龙年兄给了我一个方案,就是通过把handler对象转换为HandlerMethod类型,然后直接getMethod,代码如下:
/**
* This implementation always returns <code>true</code>.
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("*********************preHandle********************");
System.out.println(handler.getClass());
HandlerMethod handlerMethod = (HandlerMethod) handler;
System.out.println(handlerMethod.getMethod());
return true;
}
注:HandlerMethod类是Spring 3.1.0.RELEASE版本中才有的,之前我使用的Spring 3.0.6.RELEASE版本,里面是找不到这个类的
根据龙年兄提供的方法,测试之后报错,报错信息如下:
*********************preHandle********************
class com.chenzhou.examples.erm.web.AdminController
-- :: org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet erm threw exception
java.lang.ClassCastException: com.chenzhou.examples.erm.web.AdminController cannot be cast to org.springframework.web.method.HandlerMethod
at com.chenzhou.examples.erm.util.interceptor.LoginInterceptor.preHandle(LoginInterceptor.java:)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:)
……
根据错误提示可以看出是HandlerMethod handlerMethod = (HandlerMethod) handler;这一步报错了,根据System.out.println(handler.getClass());打印的结果可以得知handler是该请求访问的Controller类,无法转换成HandlerMethod对象。这次还是龙年兄帮我找出了原因,解决方案是使用
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
替换
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
因为DefaultAnnotationHandlerMapping只能返回Controller对象,不会映射到Controller中的方法级别。替换之后servlet xml配置如下:
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="interceptors">
<list>
<bean class="com.chenzhou.examples.erm.util.interceptor.LoginInterceptor"/>
</list>
</property>
</bean>
重启tomcat测试之后发现再次报错,报了另外一个错误,具体信息如下:
-- :: org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet erm threw exception
javax.servlet.ServletException: No adapter for handler [public org.springframework.web.servlet.ModelAndView com.chenzhou.examples.erm.web.AdminController.init(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)]: Does your handler implement a supported interface like Controller?
……
这一次,请求根本没有到达拦截器容器就已经报错了,错误提示的意思是找不到handler对象对应的Adapter类。我在RequestMappingHandlerMapping类对应的spring-webmvc-3.1.0.RELEASE.jar 包里找到了该类对应的Adapter类:RequestMappingHandlerAdapter,然后在servlet xml中进行了配置:
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="interceptors">
<list>
<bean class="com.chenzhou.examples.erm.util.interceptor.LoginInterceptor"/>
</list>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
然后重新启动tomcat后访问http://localhost:8080/erm/admin/init 结果正常,控制台日志信息如下:
Shell代码
*********************preHandle********************
class org.springframework.web.method.HandlerMethod
public org.springframework.web.servlet.ModelAndView com.chenzhou.examples.erm.web.AdminController.init(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
从日志信息可以看出,handler对象在经过类型转换后转换成了HandlerMethod类型,通过handler.getMethod方法,获取到了该请求访问的方法为com.chenzhou.examples.erm.web.AdminController.init
注:非常感谢jinnianshilongnian 开涛兄的帮助。
Spring拦截器中通过request获取到该请求对应Controller中的method对象的更多相关文章
- spring拦截器中修改响应消息头
问题描述 前后端分离的项目,前端使用Vue,后端使用Spring MVC. 显然,需要解决浏览器跨域访问数据限制的问题,在此使用CROS协议解决. 由于该项目我在中期加入的,主要负责集成shiro框架 ...
- Spring 拦截器——HandlerInterceptor
采用Spring拦截器的方式进行业务处理.HandlerInterceptor拦截器常见的用途有: 1.日志记录:记录请求信息的日志,以便进行信息监控.信息统计.计算PV(Page View)等. 2 ...
- spring 拦截器简介
spring 拦截器简介 常见应用场景 1.日志记录:记录请求信息的日志,以便进行信息监控.信息统计.计算PV(Page View)等.2.权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直 ...
- spring拦截器和注解处理日志操作
整体思想:通过拦截器拦截所有的请求,处理含有自定义注解的方法,通过request得到需要的参数. 拦截器代码: package com.zktx.platform.log2; import java. ...
- Spring 拦截器实现+后台原理(HandlerInterceptor)
过滤器跟拦截器的区别 spring mvc的拦截器是只拦截controller而不拦截jsp,html 页面文件的.这就用到过滤器filter了,filter是在servlet前执行的,你也可以理解成 ...
- Spring拦截器和过滤器
什么是拦截器 拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在方法执行之前或之后加入某些操作,其实就是AOP的一种实现策略.它通过动态拦截Action调用的对象,允许开发者 ...
- Spring拦截器总结
本文是对慕课网上"搞定SSM开发"路径的系列课程的总结,详细的项目文档和课程总结放在github上了.点击查看 Spring过滤器WebFilter可以配置中文过滤 拦截器实现步骤 ...
- 过滤器 ;spring拦截器 切片 小结
1. springMVc的拦截器 实现HandlerInterceptor接口,如下: public class HandlerInterceptor1 implements HandlerInter ...
- 如何实现 Https拦截进行 非常规“抓包” 珍惜Any 看雪学院 今天 前段时间在自己做开发的时候发现一个很好用的工具,OKHttp的拦截器(何为拦截器?就是在每次发送网络请求的时候都会走的一个回调)大概效果如下:
如何实现 Https拦截进行 非常规“抓包” 珍惜Any 看雪学院 今天 前段时间在自己做开发的时候发现一个很好用的工具,OKHttp的拦截器(何为拦截器?就是在每次发送网络请求的时候都会走的一个回调 ...
随机推荐
- NHibernate变的简单
前言 这篇文章出自于我尝试学习使用Nhiberbnate的挫败感.我发现好像Nhibernate全部的介绍材料不是很模糊就是太详细.我所需要的就是一个简单直接的教程,能让我尽快对NHibernate熟 ...
- POJ 1142 质因数分解
只要很朴素的分解就可以了,数据量不大 #include <stdio.h> #include <string.h> #include <stdlib.h> #inc ...
- ASP.NET MVC 5 学习教程:生成的代码详解
原文 ASP.NET MVC 5 学习教程:生成的代码详解 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 ...
- php函数参数
函数的参数 通过参数列表可以传递信息到函数,即以逗号作为分隔符的表达式列表.参数是从左向右求值的. PHP 支持按值传递参数(默认),通过引用传递参数以及默认参数.也支持可变长度参数列表,更多信息参见 ...
- Android 自动编译、打包生成apk文件 4 - 多渠道批量打包
相关文章列表: < Android 自动编译.打包生成apk文件 1 - 命令行方式> < Android 自动编译.打包生成apk文件 2 - 使用原生Ant方式 > < ...
- [转]CentOS_yum的详细使用方法
yum 是什么yum = Yellow dog Updater, Modified主要功能是更方便的添加/删除/更新RPM包.它能自动解决包的倚赖性问题.它能便于管理大量系统的更新问题 yum特点可以 ...
- 浅尝key-value数据库(一)——一览NoSQL
浅尝key-value数据库(一)——一览NoSQL 最近由于一个项目的关系,研究了一下key-value数据库这个最近很火的概念.本系列从项目需求的角度分析并测试了几个key-value数据库的性能 ...
- HDU4544 湫湫系列故事――消灭兔子
HDU 4544 Tags: 数据结构,贪心 Analysis: 将兔子的血量从大到小排序,将箭的杀伤力从大到小排序,对于每一个兔子血量, 将比他大的杀伤力大的剑压入优先队列,优先队列自己重写,让它每 ...
- UVA 1524 - Hot or Cold?(数学)
UVA 1524 - Hot or Cold? 题目链接 题意:给一个一元n次方程,带入x表示时间,f(x)表示温度,如今要求[s, e]的平均温度 思路:平均温度就是 总温度/ (e - s),画出 ...
- SSH框架之Hibernate(1)——映射关系
ORM的实现思想就是将关系数据库中表的数据映射成对象.以对象的形式展现,这样开发者就能够把对数据库的操作转化为对这些对象的操作.Hibernate正是实现了这样的思想,达到了方便开发者以面向对象的思想 ...