本文来自于https://www.boraji.com/spring-mvc-4-how-to-intercept-request-with-a-handlerinterceptor, 翻译此文如下.
技术栈: Java SE 1.8 、Spring 4.3.10.RELEASE、 Maven 3.3.9 、 Eclipse Neon.3 、 Apache Tomcat 7.0.47
本文将会介绍如何通过使用 HandlerInterceptor 接口 、HandlerInterceptorAdapter 类在 Spring MVC 应用程序中拦截WEB 请求。
HandlerInterceptor 接口提供了三个抽象方法如下:
preHandle() - 这个方法会在一个控制器类的处理方法被调用之前执行此方法。
afterCompletion() - 这个方法会在一个请求完成之后被调用 。如渲染视图之后。
postHandle() - 这个方法会在controller类的处理方法调用之后, 但是在渲染视力之前运行。
类 HandlerInterceptorAdapter 是接口 HandlerInterceptor 的一个实现类。如果你想使用这些方法, 可以继承这个类, 然后覆盖它。
我们需要创建一个自定义的处理拦截器,可以通过实现 HandlerInterceptor 接口或者继承 HandlerInterceptorAdapter类。接下来看一下完整的demo例子。
下面的项目结构由Gradle构建:
关于如何创建一个Web项目,参考https://www.boraji.com/how-to-create-a-web-project-using-maven-in-eclipse
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'eclipse-wtp'
apply plugin: 'jetty'
// JDK 8
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile 'ch.qos.logback:logback-classic:1.1.3'
compile 'javax.servlet:jstl:1.2'
//compile group: 'javax.servlet.jsp.jstl', name: 'jstl', version: '1.2'
compile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'
//Spring boot
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '1.5.9.RELEASE'
compile group: 'org.aspectj', name: 'aspectjrt', version: '1.8.13'
compile group: 'org.aspectj', name: 'aspectjweaver', version: '1.8.13'
compile "commons-io:commons-io:2.5"
compile group: 'javax.annotation', name: 'jsr250-api', version: '1.0'
compile group: 'javax', name: 'javaee-web-api', version: '8.0'
compile group: 'javax.servlet.jsp', name: 'jsp-api', version: '2.2'
compile group: 'org.springframework', name: 'spring-tx', version: '5.0.2.RELEASE'
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
compile group: 'log4j', name: 'log4j', version: '1.2.17'
compile group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.25'
compile group: 'ch.qos.logback', name: 'logback-core', version: '1.2.3'
compile group: 'ch.qos.logback', name: 'logback-access', version: '1.2.3'
compile group: 'org.springframework', name: 'spring-core', version: '5.0.2.RELEASE'
compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: '2.9.3'
compile group: 'atg.taglib.json', name: 'json-taglib', version: '0.4.1'
compile group: 'org.ops4j.pax.runner.profiles', name: 'felix.webconsole', version: '3.0.0'
// https://mvnrepository.com/artifact/org.springframework/spring-test
testCompile group: 'org.springframework', name: 'spring-test', version: '5.0.2.RELEASE'
testCompile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
jettyRun{
contextPath = "SpringMVCInterceptor2"
httpPort = 8080
}
jettyRunWar{
contextPath = "SpringMVCInterceptor2"
httpPort = 8080
}
eclipse {
wtp {
component {
//define context path, default to project folder name
contextPath = 'SpringMVCInterceptor2'
}
}
}
创建一个拦截控制器类, 命名为:GuestInterceptor,实现接口HandlerInterceptor
,代码如下:
GuestInterceptor.java
package com.boraji.tutorial.spring.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class GuestInterceptor implements HandlerInterceptor {
// Called before handler method invocation
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res,
Object handler) throws Exception {
System.out.println("Called before handler method");
req.setAttribute("fname", "Elizabeth");
return true;
}
// Called after handler method request completion, before rendering the view
@Override
public void postHandle(HttpServletRequest req, HttpServletResponse res,
Object handler, ModelAndView model) throws Exception {
System.out.println("Called after handler method request completion,"
+ " before rendering the view");
model.addObject("lname", "Brown");
}
// Called after rendering the view
@Override
public void afterCompletion(HttpServletRequest req, HttpServletResponse res,
Object handler, Exception ex) throws Exception {
System.out.println("Called after rendering the view");
}
}
- 创建另外一个拦截类,命名为AdminInterceptor
, 通过继承HandlerInterceptorAdapter
类和重写postHandle()
方法,具体如下:
AdminInterceptor.java
package com.boraji.tutorial.spring.interceptor;
import java.time.LocalTime;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class AdminInterceptor extends HandlerInterceptorAdapter {
@Override
public void postHandle(HttpServletRequest req, HttpServletResponse res,
Object handler, ModelAndView model) throws Exception {
System.out.println("Called after handler method request completion,"
+ " before rendering the view");
LocalTime time = LocalTime.now();
int hrs = time.getHour();
if (hrs >= 0 && hrs <= 12) {
model.addObject("greeting", "Good morning!");
} else if (hrs > 12 && hrs <= 17) {
model.addObject("greeting", "Good afternoon!");
} else {
model.addObject("greeting", "Good evening!");
}
}
}
WebConfig.java
package com.boraji.tutorial.spring.interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.boraji.tutorial.spring.interceptor" })
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// Register guest interceptor with single path pattern
registry.addInterceptor(new GuestInterceptor()).addPathPatterns("/guest");
// Register admin interceptor with multiple path patterns
registry.addInterceptor(new AdminInterceptor())
.addPathPatterns(new String[] { "/admin", "/admin/*" });
}
@Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
创建一个简单的拦截器类UserController
, 用于处理访客和admin用户的请求.
UserController.java
package com.boraji.tutorial.spring.interceptor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {
@RequestMapping("/")
public String index() {
return "index";
}
@RequestMapping("/guest")
public String guestHandler(@RequestAttribute("fname")String fname,Model model) {
model.addAttribute("mname", "Smith");
return "guest";
}
@RequestMapping("/admin")
public String adminHandler(Model model) {
model.addAttribute("name", "Mike");
return "admin";
}
}
在\src\main\webapp\WEB-INF\目录下, 创建views文件夹. 同时在\src\main\webapp\WEB-INF\views\下创建index.jsp,guest.jsp,admin.jsp三个文件.
index.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
BORAJI.COM
Spring MVC 4 - HandlerInterceptor example
guest.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
BORAJI.COM
Spring MVC 4 - HandlerInterceptor example
Guest user name is : ${fname} ${mname} ${lname}
admin.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
BORAJI.COM
Spring MVC 4 - HandlerInterceptor example
${greeting} ${name}
最后, 创建一个继承AbstractAnnotationConfigDispatcherServletInitializer
类的容器初始化类,用于引导Spring MVC的应用程序:
MyWebAppInitializer.java
package com.boraji.tutorial.spring.interceptor;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class>[] getRootConfigClasses() {
return new Class[] {};
}
@Override
protected Class>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
AbstractAnnotationConfigDispatcherServletInitializer
类, 它实现了WebApplicationInitializer
, 它的实现是为了使ServletContext
通过编程的方式在Servlet 3.0环境里配置.
如果你使用的是Maven,可以使用以下命令去编译运行.
- mvn clean install(它用于打war包)
-mvn tomcat7:run(它用于绑定tomcat7并且自动发布运行)
此例, 我使用的eclipse IDE直接启动运行:
项目名称鼠标右键->Run as ->Run on server.
通过访问http://localhost:8080/ 查看以下结果:
当你点击'Guest;链接时, 打开guest页面: