`

Spring拦截器中通过request获取到该请求对应Controller中的method对象

 
阅读更多

来源:http://chenzhou123520.iteye.com/blog/1702563

 

 

背景:项目使用Spring 3.1.0.RELEASE,从dao到Controller层全部是基于注解配置。我的需求是想在自定义的Spring拦截器中通过request获取到该请求对应于Controller中的目标method方法对象。Controller和拦截器代码如下:

 

AdminController

 

Java代码 复制代码 收藏代码
  1. @Controller  
  2. @RequestMapping("/admin")   
  3. public class AdminController {   
  4.   
  5.     /**  
  6.      * init:初始页面. <br/>  
  7.      *  
  8.      * @author chenzhou  
  9.      * @param request 请求  
  10.      * @param response 响应  
  11.      * @return 登陆页  
  12.      * @since JDK 1.6  
  13.      */  
  14.     @RequestMapping("/init")   
  15.     public ModelAndView init(HttpServletRequest request,   
  16.             HttpServletResponse response){   
  17.         Map<String, Object> model = new HashMap<String, Object>();   
  18.         List<Role> roleList = this.adminService.getRoleList();   
  19.         model.put("roleList", roleList);   
  20.         return new ModelAndView(this.getLoginPage(), model);   
  21.     }   
  22.   
  23.     //……   
  24. }  
@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

 

Java代码 复制代码 收藏代码
  1. public class LoginInterceptor extends HandlerInterceptorAdapter {   
  2.     /**  
  3.      * This implementation always returns <code>true</code>.  
  4.      */  
  5.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)   
  6.         throws Exception {   
  7.         return true;   
  8.     }   
  9.   
  10.     /**  
  11.      * This implementation is empty.  
  12.      */  
  13.     public void postHandle(   
  14.             HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)   
  15.             throws Exception {   
  16.     }   
  17.   
  18.     /**  
  19.      * This implementation is empty.  
  20.      */  
  21.     public void afterCompletion(   
  22.             HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)   
  23.             throws Exception {   
  24.     }   
  25. }  
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配置文件定义:

Xml代码 复制代码 收藏代码
  1. <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />    
  2. <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>  
  3. <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">  
  4.     <property name="interceptors">  
  5.         <list>  
  6.             <bean class="com.chenzhou.examples.erm.util.interceptor.LoginInterceptor"/>  
  7.         </list>  
  8.     </property>  
  9. </bean>    
<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,代码如下:

 

Java代码 复制代码 收藏代码
  1. /**  
  2.  * This implementation always returns <code>true</code>.  
  3.  */  
  4. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)   
  5.     throws Exception {   
  6.     System.out.println("*********************preHandle********************");   
  7.     System.out.println(handler.getClass());   
  8.     HandlerMethod handlerMethod = (HandlerMethod) handler;   
  9.     System.out.println(handlerMethod.getMethod());   
  10.     return true;   
  11. }  
/**
 * 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版本,里面是找不到这个类的

 

根据龙年兄提供的方法,测试之后报错,报错信息如下:

 

Shell代码 复制代码 收藏代码
  1. *********************preHandle********************   
  2. class com.chenzhou.examples.erm.web.AdminController   
  3. 2012-10-21 16:28:25 org.apache.catalina.core.StandardWrapperValve invoke   
  4. 严重: Servlet.service() for servlet erm threw exception   
  5. java.lang.ClassCastException: com.chenzhou.examples.erm.web.AdminController cannot be cast to org.springframework.web.method.HandlerMethod   
  6.     at com.chenzhou.examples.erm.util.interceptor.LoginInterceptor.preHandle(LoginInterceptor.java:37)   
  7.     at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:891)   
  8.     at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)   
  9.     at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)   
  10.     at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)   
  11.     at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)   
  12.     at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)   
  13. ……  
*********************preHandle********************
class com.chenzhou.examples.erm.web.AdminController
2012-10-21 16:28:25 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:37)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:891)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
……

 

    根据错误提示可以看出是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配置如下:

 

Xml代码 复制代码 收藏代码
  1. <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />    
  2. <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>  
  3. <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">    
  4.     <property name="interceptors">  
  5.         <list>  
  6.             <bean class="com.chenzhou.examples.erm.util.interceptor.LoginInterceptor"/>  
  7.         </list>  
  8.     </property>  
  9. </bean>  
<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测试之后发现再次报错,报了另外一个错误,具体信息如下:

 

Shell代码 复制代码 收藏代码
  1. 2012-10-21 16:39:39 org.apache.catalina.core.StandardWrapperValve invoke   
  2. 严重: Servlet.service() for servlet erm threw exception   
  3. 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?   
  4. ……  
2012-10-21 16:39:39 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中进行了配置:

 

Xml代码 复制代码 收藏代码
  1. <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />    
  2. <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>  
  3. <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">    
  4.     <property name="interceptors">  
  5.         <list>  
  6.             <bean class="com.chenzhou.examples.erm.util.interceptor.LoginInterceptor"/>  
  7.         </list>  
  8.     </property>  
  9. </bean>  
  10. <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>  
<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代码 复制代码 收藏代码
  1. *********************preHandle********************   
  2. class org.springframework.web.method.HandlerMethod   
  3. public org.springframework.web.servlet.ModelAndView com.chenzhou.examples.erm.web.AdminController.init(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)  
*********************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

分享到:
评论

相关推荐

    spring配置JSON拦截器VIEW

    标题中的“spring配置JSON拦截器VIEW”指的是在Spring框架中设置JSON数据的处理方式,特别是通过拦截器(Interceptor)来优化视图层(View)的响应。在Web开发中,拦截器是一种常用的机制,用于在请求被实际处理之前...

    详解利用SpringMVC拦截器控制Controller返回值

    总结起来,这个示例展示了如何通过Spring MVC的拦截器和自定义注解来控制Controller方法的返回值。在开发过程中,你可以利用这个机制快速地构建和测试接口,而不需要每次都编写完整的方法实现。这种灵活性有助于提高...

    spring第11章--ajax,上传下载,拦截器.rar_spring mvc_spring 下载_spring 使用ajax

    本章将探讨如何在Spring MVC中集成和使用Ajax,以及涉及的上传和下载功能,同时还会介绍Spring MVC中的拦截器。 1. **Spring MVC与Ajax交互**: - **jQuery Ajax**:Spring MVC常与jQuery库结合使用,通过$.ajax()...

    spring控制器代码

    拦截器允许在请求处理前后执行自定义逻辑,如登录检查、日志记录等。创建一个实现`HandlerInterceptor`接口的类并注册到Spring配置中。 7. **转换器与格式化器** 自定义转换器和格式化器可以帮助Spring MVC将请求...

    企业级开发-SpringMVC使用拦截器实现用户登录权限验证实验报告.docx

    配置 SpringMVC 拦截器,我们需要在 `springmvc-config.xml` 文件中添加以下内容: ```xml &lt;beans xmlns="http://www.springframework.org/schema/beans" ...&gt; ... ... ``` 此外,还需要在 `web.xml` ...

    spring MVC测试实例

    在`spring-servlet.xml`配置文件中,你需要配置Spring MVC的组件,如视图解析器(ViewResolver)、模型-视图对象(ModelAndView)以及其他bean。视图解析器(如InternalResourceViewResolver)用于将模型数据与视图...

    详解java中spring里的三大拦截器

    在Java Spring框架中,拦截器(Interceptor)是用于增强应用程序功能和实现通用逻辑的重要组件。它们可以看作是在控制器(Controller)处理请求之前和之后执行的一系列预定义操作。Spring 提供了三种主要类型的拦截...

    实现java自定义注解拦截器.docx

    以上步骤展示了如何使用Spring Boot中的自定义拦截器和自定义注解来实现对特定方法的选择性拦截。这种机制可以非常灵活地控制哪些请求需要经过额外的验证或处理,对于构建安全可控的应用程序来说非常重要。

    Spring4 In Action-5.2.2-Spring Web应用程序-简单的控制器实现跳转

    `@RequestParam`用于获取请求参数,而`@ModelAttribute`则常用于模型绑定,可以从请求中读取数据并映射到Java对象。 在实际项目中,你可能还需要配置视图解析器,比如`InternalResourceViewResolver`,它告诉Spring...

    spring mvc过程详解

    Spring MVC 中的拦截器通过实现 `HandlerInterceptor` 接口或者标注 `@ControllerAdvice` 来实现。拦截器可以在请求处理前后执行自定义逻辑,例如日志记录、权限验证等。 #### 十、Spring MVC 的单元测试实践 对于...

    Spring系列面试题129道(附答案解析)

    在该容器中,对象定义(通过配置文件或注解)被创建,并通过依赖注入的方式自动装配依赖项。 IOC容器通过管理对象的创建和它们之间的依赖关系,使得对象之间的耦合度降低。 72、IOC的优点是什么? IOC(控制反转)...

    spring mvc 自學筆記

    Spring MVC 中的拦截器需要实现 `HandlerInterceptor` 接口,该接口提供了三个方法: - `preHandle()`:在控制器方法前调用。 - `postHandle()`:控制器方法调用之后,视图渲染之前调用。 - `afterCompletion()`:...

    spring 整合spring mvc

    在实际项目中,我们还会涉及到拦截器、异常处理、数据绑定、验证、国际化等功能,这些都是Spring MVC提供的强大支持。Spring的IoC容器使得我们可以方便地管理Bean,而AOP则可以实现切面编程,增强代码的可维护性和可...

    spring mvc 3_demo

    虽然这个示例是注解驱动的,但通常还需要一个配置类来启用Spring MVC,如`WebMvcConfigurerAdapter`的子类,配置拦截器、视图解析器等。然而,Spring Boot项目通常不再需要显式配置。 8. **依赖注入**: Spring ...

    java ee期末复习题.docx

    13. Spring MVC 中的默认参数类型:HttpServletRequest 通过 request 对象获取请求信息,HttpServletResponse 通过 response 处理响应信息,HttpSession 通过 session 对象得到 session 中存放的对象,Model/...

    java解决405 - HTTP method GET is not supported by this URL

    4. **MVC框架配置**:如果你使用了Spring MVC、Struts2等框架,检查控制器(Controller)配置,确保有处理GET请求的方法。 针对给定的压缩包文件名"删除servlet中doGet()中的super.doGet(req, resp);即可.txt",这...

    spring mvc系列教程源码

    Spring MVC中的拦截器通过实现`HandlerInterceptor`接口或继承`HandlerInterceptorAdapter`来创建。拦截器可以用来进行权限检查、日志记录、性能监控等操作。例如: ```java @Component public class ...

    spring boot 登陆拦截

    本教程将详细讲解如何在Spring Boot项目中设置一个简单的登录拦截器。 首先,我们需要理解Spring Security是Spring Boot推荐用于安全控制的框架。它提供了丰富的功能,包括认证、授权、CSRF防护、会话管理等。我们...

    spring boot如何使用spring AOP实现拦截器

    在Spring Boot中,使用Spring AOP实现拦截器主要涉及到以下几个核心概念: 1. **AOP(面向切面编程)**:AOP是Spring框架的一个重要特性,它允许程序员定义“切面”,这些切面可以包含业务逻辑的“侧面”——例如...

Global site tag (gtag.js) - Google Analytics