活动地址:CSDN21天学习挑战赛
目录
如果在项目中只定义了一个拦截器,那么该拦截器在程序中的执行流程如图所示。
1.在eclipse中创建动态web项目,将Spring MVC依赖的包复制到lib目录下,如下图:
2.在web.xml中配置Spring MVC的前端过滤器和初始化加载配置文件等信息
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
- http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- id="WebApp_ID" version="4.0">
-
- <servlet>
-
- <servlet-name>springmvcservlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
-
- <init-param>
- <param-name>contextConfigLocationparam-name>
- <param-value>classpath:springmvc-config.xmlparam-value>
- init-param>
-
- <load-on-startup>1load-on-startup>
- servlet>
- <servlet-mapping>
- <servlet-name>springmvcservlet-name>
- <url-pattern>/url-pattern>
- servlet-mapping>
- web-app>
3.在src目录下创建一个controller包,并在包中创建控制器类HelloController类
- package controller;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- @Controller
- public class HelloController {
- @RequestMapping("/hello")
- public String hello(){
- System.out.println("Hello");
- return "success";
- }
- }
4.在src目录下创建interceptor包,在包内创建拦截器类UserInterceptor类。该类要实现HandlerInterceptor接口,并且在实现方法中需要编写输出语句来输出信息。
- package 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 UserInterceptor implements HandlerInterceptor{
- @Override
- public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
- System.out.println("UserInterceptor...preHandle");
- //对拦截的请求放行处理
- return true;
- }
- @Override
- public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
- throws Exception {
- System.out.println("UserInterceptor...postHandle");
- }
- @Override
- public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
- throws Exception {
- System.out.println("UserInterceptor...afterCompletion");
- }
- }
5.在src目录下创建并配置springmvc-config.xml
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:mvc="http://www.springframework.org/schema/mvc"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/mvc
- http://www.springframework.org/schema/mvc/spring-mvc.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd">
-
- <context:component-scan base-package="controller" />
-
- <bean id="viewResoler"
- class="org.springframework.web.servlet.view.InternalResourceViewResolver">
-
- <property name="prefix" value="/" />
-
- <property name="suffix" value=".jsp" />
- bean>
-
- <mvc:interceptors>
-
- <bean class="interceptor.UserInterceptor" />
- mvc:interceptors>
- beans>
6.在webapp目录下创建success.jsp用于显示信息。
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>拦截器title>
- head>
- <body>
- ok,执行成功!
- body>
- html>
7.运行结果:
访问:localhost:8848/chapter14/hello
控制台消息:
由此可以看出,程序先执行了preHandle()方法,然后执行了控制器中的hello()方法,最后执行了拦截器类中的postHandle()方法和afterCompletion()方法,和前文描述一致。
在大型项目中,通常会定义很多拦截器来实现不同的功能。多个拦截器的执行顺序如图所示。
1.在interceptor包中创建两个拦截器类Interceptor1和Interceptor2类,在这两个类中均实现了HandlerInterceptor接口。
- package 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 Interceptor1 implements HandlerInterceptor{
- @Override
- public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
- System.out.println("UserInterceptor1...preHandle");
- return true;
- }
- @Override
- public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
- throws Exception {
- System.out.println("UserInterceptor1...postHandle");
- }
- @Override
- public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
- throws Exception {
- System.out.println("UserInterceptor1...afterCompletion");
- }
- }
- package 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 Interceptor2 implements HandlerInterceptor{
- @Override
- public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
- System.out.println("UserInterceptor2...preHandle");
- return true;
- }
- @Override
- public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
- throws Exception {
- System.out.println("UserInterceptor2...postHandle");
- }
- @Override
- public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
- throws Exception {
- System.out.println("UserInterceptor2...afterCompletion");
- }
- }
2.在配置文件springmvc-config.xml文件中配置上面定义的两个拦截器
-
-
- <mvc:interceptor>
- <mvc:mapping path="/**" />
- <bean class="interceptor.Interceptor1" />
- mvc:interceptor>
-
- <mvc:interceptor>
- <mvc:mapping path="/hello" />
- <bean class="interceptor.Interceptor2" />
- mvc:interceptor>
3.运行结果:
访问:localhost:8848/chapter14/hello
控制台消息:
可以看出,程序先执行了两个拦截器的preHandle()方法,这两个方法的执行顺序与配置文件中定义的顺序相同;然后执行了控制器的hello()方法,然后执行了拦截器的postHandle()和afterCompletion()方法,且这两个方法的执行顺序与配置文件中所定义的拦截器顺序相反。
通过拦截器来完成一个用户登录权限验证的案例。该案例的整个执行流程如图所示。
从流程图看出,只有登录后的用户才能访问管理主页,如果没有登录而直接访问主页,则拦截器会将请求拦截,并转发到登录页面,同时在登录页面中给出提示信息。如果用户名或密码错误,也会在登录页面给出相应的提示信息。当已登录的用户在管理主页中单击“退出”链接时,同样会回到登录页面。
1.在src目录下创建po包,在包内创建User类
- package po;
- public class User {
- private Integer id;
- private String username;
- private String password;
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- }
2.在controller包中创建控制器类UserController,并在该类中定义向主页跳转,向登陆页面跳转。执行用户登录等操作的方法
- package controller;
- import javax.servlet.http.HttpSession;
-
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.Model;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import po.User;
- @Controller
- public class UserController {
- /*
- * 向用户登陆页面跳转
- */
- @RequestMapping(value="/toLogin",method=RequestMethod.GET)
- public String toLogin(){
- return "login";
- }
- /*
- * 用户登录
- */
- @RequestMapping(value="/login",method=RequestMethod.POST)
- public String login(User user,Model model,HttpSession session){
- String username=user.getUsername();
- String password=user.getPassword();
- //模拟从数据库获取用户名和密码进行判断
- if(username!=null && username.equals("zyy")){
- if(password!=null && password.equals("123456")){
- //用户存在,将用户信息保存到session中,并复位向到主页
- session.setAttribute("user_session", user);
- return "redirect:main";
- }
- }
- //用户不存在将错误信息到model中,并跳转到登陆页面
- model.addAttribute("msg","用户或密码输入错误,请重新登录");
- return "login";
- }
- /*
- * 向管理主页跳转
- */
- @RequestMapping(value="/main")
- public String toMain(){
- return "main";
- }
- /*
- * 退出
- */
- @RequestMapping(value="/logout")
- public String logout(HttpSession session){
- session.invalidate();
- return "redirect:toLogin";
- }
- }
3.在interceptor包中创建拦截器类LoginInterceptor
- package interceptor;
- import javax.servlet.http.HttpServletRequest;
-
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
- import po.User;
- public class LoginInterceptor implements HandlerInterceptor{
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- //获取请求的URL
- String url=request.getRequestURI();
- //允许公开访问"/toLogin"
- if(url.indexOf("/toLogin")>=0){
- return true;
- }
- //允许公开访问"/Login"
- if(url.indexOf("/login")>=0){
- return true;
- }
- //获取session
- HttpSession session=request.getSession();
- User user=(User)session.getAttribute("user_session");
- //如果user不为空,表示已经登录
- if(user!=null){
- return true;
- }
- request.setAttribute("msg","请先登录");
- request.getRequestDispatcher("/login.jsp").forward(request, response);
- return false;
- }
- @Override
- public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
- throws Exception {
- }
-
- @Override
- public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
- throws Exception {
- }
- }
4.在配置文件中配置自定义的登录拦截器信息
- <mvc:interceptor>
-
- <mvc:mapping path="/**" />
-
- <bean class="interceptor.LoginInterceptor" />
- mvc:interceptor>
5.在webapp目录下创建管理主页面main.jsp
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>管理主页title>
- head>
- <body>
- 当前用户信息:${user_session.username}
- <a href="${pageContext.request.contextPath}/logout">退出a>
- body>
- html>
6.在webapp目录下创建登陆页面login.jsp
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>用户登录title>
- head>
- <body>
- <font style="color:Red;">${msg }font>
- <form action="${pageContext.request.contextPath}/login" method="post">
- 登录名:<input type="text" name="username" id="username" /> <br />
- 密 码:<input type="password" name="password" id="password" /> <br />
- <input type="submit" value="登录" />
- form>
- body>
- html>
7.运行结果
运行localhost:8848/chapter14/main
输入正确的账号密码(zyy,123456)后会跳转到管理主页面
如果输入错误,会提醒用户或密码输入错误
项目源码:
链接:https://pan.baidu.com/s/1-J6eiunkWVG7NxqSxRgO4A?pwd=r5za
提取码:r5za