zoukankan      html  css  js  c++  java
  • Spring入门-Interceptor基本使用

    SpringMVC提供了拦截器Interceptor,可以用于验证用户登录,它跟过滤器是有区别的,拦截器是Spring提供的,而过滤器是Servlet提供的。

    使用拦截器的条件

    使用拦截器前面需要进行配置,包括导包、web.xml中配置DispatcherServlet,Spring启动读取文件中配置组件扫描、注解驱动、视图解析器和拦截器。其他就是需要写一个控制器用来进行请求分发处理,还有自定义拦截器。

    自定义拦截器

    自定义拦截器需要实现HandlerInterceptor接口,实现接口定义的方法。

     1 package Interceptors;
     2 
     3 import javax.servlet.http.HttpServletRequest;
     4 import javax.servlet.http.HttpServletResponse;
     5 
     6 import org.springframework.web.servlet.HandlerInterceptor;
     7 import org.springframework.web.servlet.ModelAndView;
     8 /**
     9  * 拦截器类需要实现HandlerInterceptor接口
    10  * @author yangchaolin
    11  *
    12  */
    13 public class SomeInterceptor implements HandlerInterceptor{
    14     /**
    15      * DispatcherServlet在收到请求后,会先调用preHandler方法,如果该方法的返回值为true,则继续向后调用Controller的方法
    16      * 如果返回值是false,则中断请求
    17      * 
    18      * DispatcherServlet,拦截器、Controller会共享同一个request,response
    19      * handler:Controller的方法对象,利用了java反射机制,后面了解学习
    20      */
    21     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
    22             throws Exception {
    23         System.out.println("拦截器的preHandle方法执行了");
    24         return true;
    25     }
    26     /**
    27      * 是Controller处理完后,在将ModelAndView返回给前端控制器DispatcherServlet之前,执行的方法
    28      * 可以在该方法里,修改ModelAndView的处理结果
    29      */
    30     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
    31             ModelAndView modelAndView) throws Exception {
    32         System.out.println("拦截器的postHandle方法执行了");        
    33     }
    34     /**
    35      * 最后执行
    36      * ex:是处理器Controller所抛出的异常
    37      * 可以写一个拦截器专门处理Controller抛出的异常
    38      */
    39     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    40             throws Exception {
    41         System.out.println("拦截器的afterCompletion方法执行了");        
    42     }
    43 }

    Controller

    写一个Controller来测试拦截器方法的执行顺序,里面为了测试多级目录写了两个方法。

     1 package Controller;
     2 
     3 import org.springframework.stereotype.Controller;
     4 import org.springframework.web.bind.annotation.RequestMapping;
     5 
     6 @Controller
     7 public class HelloController {
     8     @RequestMapping("/hello.do")
     9     public String hello() {
    10         System.out.println("控制器的hello()方法执行了");
    11         return "hello";
    12         
    13     }
    14     /**
    15      * 如果路径加一个demo,然而拦截器mapping还是/*的话,将不会拦截
    16      * 如果想实现各种路径的拦截,不论几层都能实现拦截效果的话,需要将mapping修改为/**
    17      * @return
    18      */
    19     @RequestMapping("/demo/hello.do")
    20     public String hello1() {
    21         System.out.println("hello1()");
    22         return "hello";        
    23     }
    24 }

    配置拦截器

    在Spring启动默认读取文件applicationContext.xml文件中添加拦截器配置,这里只设置了一个拦截器,可以配置多个拦截器,执行顺序从上往下拦截。

     1     <!-- 设置拦截器Interceptor -->
     2     <!-- 如果想要拦截所有的请求,path应该写成/** -->    
     3     <mvc:interceptors>
     4       <!-- 第一个拦截器 -->
     5       <mvc:interceptor>
     6         <mvc:mapping path="/**"/>       
     7         <bean class="Interceptors.SomeInterceptor"></bean>
     8       </mvc:interceptor>
     9       <!-- 后面可以配置多个拦截器,拦截顺序从上到下 -->
    10     </mvc:interceptors>

    运行结果,只展示hello.do请求,多级目录/demo/hello.do也可以拦截。

    控制台输出情况

    可以看出来拦截器方法的执行顺序

    (1)DispatcherServlet接受到请求后,首先会根据HandlerMapping配置请求的结果(这里使用注解@RequestMapping来完成),查看是否有对应请求Mapping

    (2)如果没有匹配路径不再往下执行,如果有请求匹配的话,会先执行拦截器方法preHandle,返回true则继续执行Controller的方法

    (3)Controller执行完逻辑准备将结果(String或者ModelAndView)返回给前端控制器前,先执行postHandle方法,如果有异常,接下来在afterCompletion方法中进行处理,最后将结果返回给前端控制器

    拦截器用于登录验证

    接下来使用拦截器,在前面登录案例的基础上,添加一个用户登录验证,即登录成功的才跳转到后面页面,否则返回到登录页面,前期配置参考博文。

    (1)JSP准备

    登录页面、主页,sub页,主页用于登录验证,主页直接登录,sub页直接登录。

     1 <%@page pageEncoding="utf-8"%>
     2 <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
     3 <!doctype html>
     4 <html>
     5     <head>
     6       <title>欢迎登录Color Filter-JavaScript登录验证</title>
     7       <meta charset="utf-8">
     8       <link rel="stylesheet" type="text/css" href="css/login.css" />
     9       <!-- <script type="text/javascript" src="script/login.js"></script> -->
    10     </head>
    11     <body>
    12        <!--logo区+段落区-->
    13        <div class="logo">
    14            <img src="image/LogoCF.jpg">
    15            <p id="logoDesc">Sign in to Color Filter</p>
    16        </div>
    17        <!--主体登录区-->
    18        <div class="main">
    19           <div id="login">
    20               <!--5行2列-->
    21               <!--表单用于输入登录信息,提交给服务器  -->
    22               <!-- 
    23                 onsubmit是表单提交事件,在点击提交按钮时触发。触发时先调用onsubmit内的方法,若该方法返回true则会自动提交表单
    24                 返回false则不提交,此处声明的方法可以起到拦截提交的作用,避免账号名和密码都不对时也能提交到服务器
    25                 onsubmit="return ((check_username()+check_pwd())==2)"
    26                -->
    27               <form action="logincheck.do" method="get">
    28               <table>
    29               <tr>
    30                 <td colspan="2" style="text-align: left;text-indent: 29px">Username or email address</td>
    31               </tr>
    32               <tr>
    33                 <!-- 增加切换光标确认用户名格式是否正确 -->
    34                 <td colspan="2"><input type="text" name="user"  id="username" onblur="check_username();" value="${username }"></td>
    35               </tr>
    36               <tr>
    37                 <td style="text-align: left;text-indent: 29px;15%">Password</td>
    38                 <td style="text-align: left;text-indent: 0px;85%"><a href="#">Forget password?</a></td>
    39               </tr>
    40               <tr>
    41                 <td colspan="2" style=" 345px"><input type="password" name="pwd" id="pwd" onblur="check_pwd();" value="${password }"></td>
    42               </tr>
    43               <tr>
    44                 <td colspan="2" style="text-align: left;text-indent: 29px">Security Code</td>
    45               </tr>
    46               <tr>
    47                 <td style="padding-left:32px;60%;text-align:left;"><input type="text" name="valicode" id="valicode"/></td>
    48                 <!-- <td style="padding-top:3px;40%;text-align:right;padding-right:32px"><img alt="验证码" src="createIMG.do" onclick="this.setAttribute('src','createIMG.do?x='+Math.random())"></td> -->
    49                 <!-- 添加登录失败提示 -->
    50                 <td>${login_fail}</td>
    51               </tr>     
    52               <tr>
    53                 <td colspan="2" id="buttontd"><input type="submit" name="btn" value="Sign in" id="button"></td>
    54               </tr>                     
    55               </table>
    56               </form>  
    57           </div>
    58           <div id="regist">
    59              <p style="text-align: center;">New to Color Filter? <a href="#">Create an account.</a></p>
    60           </div> 
    61        </div>
    62        <!--版权、隐私、法律相关-->
    63        <div class="foot">
    64           <p><a href="#">Terms</a>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#">Privacy</a>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#">Security</a>&nbsp;&nbsp;&nbsp;&nbsp;Contact Color Filter</p>
    65        </div>   
    66     </body>
    67 
    68 </html>
    View Code
     1 <%@page pageEncoding="utf-8" contentType="text/html; charset=utf-8"%>
     2 <h1>欢迎登陆</h1><br/>
     3 <!-- 得到服务器返回的user参数,采用el表达式获取 -->
     4 ${user }
     5 <!-- 拦截器测试 -->
     6 <div>
     7   <form action="toSubPage.do" method="post">
     8     <a href="javascript:document.forms[0].submit();">点我继续访问</a>
     9   </form>
    10 </div>
    View Code
    1 <%@page pageEncoding="utf-8" contentType="text/html; charset=utf-8"%>
    2 <h1>欢迎来到subPage</h1>
    View Code

    (2)自定义拦截器类及拦截器配置

    拦截器类

     1 package com.boe.interceptor;
     2 
     3 import javax.servlet.http.HttpServletRequest;
     4 import javax.servlet.http.HttpServletResponse;
     5 
     6 import org.springframework.web.servlet.HandlerInterceptor;
     7 import org.springframework.web.servlet.ModelAndView;
     8 
     9 /**
    10  * 配置自定义拦截器
    11  * @author yangchaolin
    12  */
    13 public class LoginInterceptor implements HandlerInterceptor{
    14     //在一次请求中,DispatcherServlet、拦截器和Controller共用一个request和response
    15     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
    16             throws Exception {
    17         //进行登录验证拦截,除了toLogin.do,logincheck.do都进行拦截
    18         Object obj=request.getSession().getAttribute("loginData");
    19         if(obj==null) {
    20             //返回登录页面
    21             System.out.println("没有登录,进行拦截");
    22             //重定向,使用不带"/",相对路径
    23             response.sendRedirect("toLogin.do");
    24             return false;
    25         }else {
    26             System.out.println("登录成功,继续访问");
    27             return true;
    28         }        
    29     }
    30 
    31     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
    32             ModelAndView modelAndView) throws Exception {
    33         // TODO Auto-generated method stub
    34         
    35     }
    36 
    37     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    38             throws Exception {
    39         // TODO Auto-generated method stub
    40         
    41     }
    42 }
    View Code

    applicationContext.xml文件中配置拦截器

    1 <!-- 添加拦截器,不拦截进入登录页面,登录验证 -->
    2     <mvc:interceptors>
    3       <mvc:interceptor>
    4         <mvc:mapping path="/**"/>
    5         <mvc:exclude-mapping path="/toLogin.do"/>
    6         <mvc:exclude-mapping path="/logincheck.do"/>
    7         <bean class="com.boe.interceptor.LoginInterceptor"></bean>
    8       </mvc:interceptor>
    9     </mvc:interceptors>

    (3)修改LoginController控制器方法,登录成功后将用户信息保存到session中。

     1 package com.boe.controller;
     2 
     3 import javax.annotation.Resource;
     4 import javax.servlet.http.HttpSession;
     5 
     6 import org.springframework.stereotype.Controller;
     7 import org.springframework.ui.ModelMap;
     8 import org.springframework.web.bind.annotation.RequestMapping;
     9 
    10 import com.boe.entity.Admin;
    11 import com.boe.entity.userInfo;
    12 import com.boe.exception.ApplicationException;
    13 import com.boe.service.LoginService;
    14 
    15 @Controller
    16 public class mainController {
    17     @Resource(name="loginServiceImpl")
    18     private LoginService service;
    19     
    20     //去到登录页面
    21     @RequestMapping("/toLogin.do")
    22     public String toLogin() {
    23         System.out.println("去到登录页面");
    24         return "login";
    25     }
    26     
    27     //验证登录
    28     @RequestMapping("/logincheck.do")
    29     public String login(userInfo data,ModelMap mm,HttpSession session) {
    30         System.out.println("登录验证");
    31         System.out.println("用户名为:"+data.getUser());
    32         System.out.println("密码为:"+data.getPwd());
    33         //处理业务层异常
    34         try {
    35             Admin admin=service.checkLogin(data.getUser(), data.getPwd());
    36             if(admin!=null) {
    37                 System.out.println("登录成功");
    38                 mm.addAttribute("user",data.getUser());
    39                 //登录成功后,将admin信息存入session
    40                 session.setAttribute("loginData", admin);
    41             }            
    42         }catch(Exception e) {
    43             //应用错误,即用户填写错误
    44             if(e instanceof ApplicationException) {
    45                 mm.addAttribute("login_fail", e.getMessage());
    46                 mm.addAttribute("username",data.getUser());
    47                 mm.addAttribute("password", data.getPwd());
    48                 return "login";
    49             }
    50             //系统错误
    51             return "loginNG";
    52         }
    53         return "loginOK";
    54     }
    55     
    56     //直接进入主页,拦截器测试
    57     @RequestMapping("/loginOK.do")
    58     public String toMainPage() {
    59         System.out.println("准备进入loginOK主页");
    60         return "loginOK";
    61     }
    62     //直接进入sub页,拦截器测试
    63     @RequestMapping("/toSubPage.do")
    64     public String toSubPage() {
    65         System.out.println("准备进入subPage副页");
    66         return "subPage";
    67     }    
    68 }
    View Code

    (4)测试不登录的情况下,进入loginOK页面,发现被拦截了,并提示没有登录。

    控制台情况,显示执行了自定义拦截器的preHandle方法,并返回false,不再执行controller里的方法,进行重定向到登录页面。

    (5)测试登录的情况下,访问loginOK.do和toSubPage.do 。

    控制台情况,可以看出验证登录是没有拦截的,登录成功后进入主页,然后点击链接时就会被拦截到,因为有登录所以拦截器的preHandle方法返回true并打印出了"登录成功,继续访问",后进入LoginController继续处理逻辑,打印出了"准备进入subPage副页",并返回String结果给前端控制器,让前端控制器分发视图解析器最后完成副页展示。

    总结

    拦截器可以用于登录验证,但是其属于Spring,如果前端更换框架则不再生效,而过滤器是servlet范畴,配置了过滤器无论怎么更换都会过滤,相比较来说过滤器范围更广。

    参考博文:

    (1)https://www.cnblogs.com/youngchaolin/p/11354307.html springMVC完成登录页面

    (2)https://www.cnblogs.com/youngchaolin/p/10549020.html 过滤器和拦截器

    (3)https://blog.csdn.net/koflance/article/details/79635240 URI、URL和URN

  • 相关阅读:
    css(上)
    前端基础
    并发编程,python的进程,与线程
    网络编程 套接字socket TCP UDP
    python 类的内置函数2
    python3大特征之多态
    python 类(object)的内置函数
    类 与 继承
    类 与 面向对象
    OOP >>> 封装
  • 原文地址:https://www.cnblogs.com/youngchaolin/p/11363118.html
Copyright © 2011-2022 走看看