4.SpringMVC之拦截器


概述

在这里插入图片描述

SpringMVC底层原理

在这里插入图片描述

  • DispatcherServlet:协调各组件,从而完成请求处理
  • 视图解析器:根据客户端要求的数据类型,比如页面/XML/JSON来返回数据给客户端
  • 拦截器:影响4,5步骤(请求处理前和处理后)
  • web.xml文件:用于注册组件

项目搭建

在这里插入图片描述

  • maven工具:可用于打包编译和运行
  • groupId:填写公司或组织名称
  • artifactId:填写项目名称或模块名称
  • 然后选择自己的maven仓库(本地仓库)
  • 模板会自动创建项目骨架,自己需要创建java文件夹(make source directory)

在这里插入图片描述

  • 版本设置为一参数

Tomcat配置

在这里插入图片描述- 关注

  1. 名称
  2. 端口号
  3. 热部署选项
  4. 启动后打开的网址
  • Tomcat使用与创建:配置——》local——》选择Tomcat本地的存放目录——》命名服务器——》进行deployment,即部署war包(可实时热部署)

web.xml配置

  • 使用模板时,maven构建的web容器配置项过低

  • 为了增加更多的Servlet支持和更好渲染——》提高容器版本(>3.0)——》修改默认头声明
    在这里插入图片描述

  • 讨巧的方法:创建一个新模块,具体选项如上图(JavaEE7),然后复制该模块web.xml的头声明,放置在自己工程中,再删除该模块

<?xml version="1.0" encoding="UTF-8"?>
<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_3_1.xsd"
         version="3.1">
   
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>namespace</param-name>
            <param-value>imoocmvc</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>


</web-app>
  • 三种配置核心配置文件的方式
    在这里插入图片描述
第一种:[servlet-name]-servlet.xml ,比如:springmvc-servlet.xml(指定了servlet-name,则核心XML配置文件名被固定死)
第二种是:改变命名空间 namespace,可自由指定核心XML配置文件名
前两种方式必须将配置文件放在web-inf目录下。
 第三种可通过:contextConfigLocation配置,如上图

核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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-4.3.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">


    <!-- 配置自定义扫描包 -->
    <context:component-scan base-package="com.imooc.web"></context:component-scan>
//表示扫描com.imooc.web下的类


    <!-- 拦截器的注册 -->
    <mvc:interceptors>

//拦截器1,先配置,优先处理
        <mvc:interceptor>   
            <mvc:mapping path="/user/**"/>        //表示拦截/user/下的所有请求方法,包括子集,如/user/1/2或者/user/3等等
            <bean class="com.imooc.core.LogInterceptor"></bean>  //配置拦截器方法
        </mvc:interceptor>
//拦截器2,后配置
        <mvc:interceptor>
            <!--<mvc:mapping path="/user/search"/>       //具体说明URL的拦截方式
            <mvc:mapping path="/user/updatepwd"/>   
            <mvc:mapping path="/user/updateheaderPic"/>-->
            <!--<mvc:mapping path="/user/*"></mvc:mapping>-->  //一个*只有一层目录,不包括子集
            <mvc:mapping path="/user/**"></mvc:mapping>       //两个*包括子集
            <!--exclude-mapping在所有拦截中进行排除,一般在通配符会有意义。-->
            <mvc:exclude-mapping path="/user/updatepwd"></mvc:exclude-mapping>   //在上述/user/**的范围内排除,取差集
            <mvc:exclude-mapping path="/user/updatebackground/*"></mvc:exclude-mapping>
            <bean class="com.imooc.core.LoginInterceptor"></bean>   //配置拦截器方法
        </mvc:interceptor>
    </mvc:interceptors>



    <!-- 映射物理路径 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
//定义视图解析器,其为JSP渲染的一种视图
//采用JSP视图解析器(拦截的是JSP)

        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>   
        //用于controller类方法返回逻辑视图时的拼接
        //如返回show,则指明页面为/WEB-INF/pages/show.jsp路径
    </bean>

</beans>

  • RequestMapping注解作用:URL匹配的规则,通过路由RequestMapping配置来完成

加载controller类到内存中,即把mapping生成一个requestmapping类

  • Controller类注册了路由和对应的请求处理方法
  • 客户端的请求地址——》根据对应的路由,找到方法
  • 视图——》页面(基于不同模板引擎,如JSP,选择不同的视图解析器类型)

拦截器和过滤器

在这里插入图片描述

  • 过滤器(web.xml中配置):过滤请求,即request对象

  • 拦截器(核心配置文件中配置):抽离逻辑代码到公共位置,然后进行请求对象延续的过程

  • 拦截器:动态代理,AOP编程,无侵入性,在对象执行特定方法时拦截

  • 拦截器机制:客户端发起请求,根据路由,找到方法(对象调用特定方法的拦截机制)

登录的拦截器

  • 应用场景:CSDN博客若直接输入其他页面URL,且没登录,则要求跳转到登录界面——》AOP织入登录界面

拦截器方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • render表示返回响应给客户端

拦截器实例


public class LoginInterceptor implements HandlerInterceptor {  //实现拦截器接口


//处理请求前执行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        User user = (User)request.getSession().getAttribute("session_user");  //先确认是否有用户信息
        if(user==null) {  //没有,则还没登录
            System.out.println("1:keketip--login====preHandle===>");
            response.sendRedirect(request.getContextPath()+"/login");  //跳转到登录界面
            return false;   //false代表不执行controller类中URL对应的处理方法
        }
        return true;//不做处理,然后会执行controller类中URL对应的处理方法
        //会终止所有的请求
    }

//处理请求后,返回响应前执行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("3:-----keketip==--login==postHandle===>");
    }

//一切请求处理完毕执行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("4--->keketip=--login===afterCompletion===>");
    }
}
  • /为根,/user表示放置在根路由下

  • div标签为盒子

  • 数据绑定(获取参数)方式多样,参考如下教程
    在这里插入图片描述

Controller类

@Controller
public class LoginController {

    @RequestMapping("/login")
    public String login(){
        return "login";
    }


    @RequestMapping("/logined")
    public String logined(@RequestParam("account")String account,
                          @RequestParam("password")String password,
                          HttpSession session){
//@RequestParam,数据绑定注解,表示将前端name=account的表单内容绑定到形参account上
        if(account.equals("xuke") && password.equals("123456")) {
            User user = new User();
            user.setAccount(account);
            user.setPassword(password);
            //登录成功,将对象放置在session中
            session.setAttribute("session_user",user);  //引入jar包,才有session对象
            return "redirect:user/search";  //默认的跳转方式为转发
        }else{
            return "redirect:login";
        }
    }
}
------
对应地,可在request域中取出数据

<body>
    <h1>用户搜索模块</h1>
    <h2>你当前登录的用户是:${session_user.account}</h2>
</body>
  • 引入以下jar包,才有session对象
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>7.0</version>
      <scope>provided</scope>
    </dependency>
  • Tomcat已经提供了相关容器的配置,所以在部署时要忽略(上述provided配置),不去打包

  • JDK动态代理要有接口——》拦截器底层的实现接口为HandlerInterceptor

  • ALT+INSERT快捷键用于快速实现接口

拦截器配置详解

  1. 在核心配置文件中配置,配置命名空间(灰色的头声明)
    在这里插入图片描述
  2. 创建定义拦截器方法的类
  3. 注册拦截器,定义拦截规则,配置定义拦截器方法的bean节点,开启注解扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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-4.3.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">


    <!-- 配置自定义扫描包 -->
    <context:component-scan base-package="com.imooc.web"></context:component-scan>



    <!-- 拦截器的注册 -->
    <mvc:interceptors>

        <mvc:interceptor>
            <mvc:mapping path="/user/**"/>
            <bean class="com.imooc.core.LogInterceptor"></bean>
        </mvc:interceptor>

        <mvc:interceptor>
            <!--<mvc:mapping path="/user/search"/>
            <mvc:mapping path="/user/updatepwd"/>
            <mvc:mapping path="/user/updateheaderPic"/>-->
            <!--<mvc:mapping path="/user/*"></mvc:mapping>-->
            <mvc:mapping path="/user/**"></mvc:mapping>
            <!--exclude-mapping在所有拦截中进行排除,一般在通配符会有意义。-->
            <mvc:exclude-mapping path="/user/updatepwd"></mvc:exclude-mapping>
            <mvc:exclude-mapping path="/user/updatebackground/*"></mvc:exclude-mapping>
            //exclude仅仅针对上方存在通配符匹配才有效,与具体配置无关
            <bean class="com.imooc.core.LoginInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>



    <!-- 映射物理路径 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

</beans>

多个拦截器

日志拦截器

  • 新增日志拦截器
package com.imooc.core;

import com.imooc.bean.User;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LogInterceptor implements HandlerInterceptor {


    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("log------>1:-----keketip====preHandle===>");
        System.out.println("keketip====当前执行的类是:"+handler.getClass());  //handler对象可获得当前请求的方法名
        System.out.println("keketip===="+handler);
        return true;//会终止所有的请求
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("log------>3:-----keketip====postHandle===>");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("log------>4--->keketip====afterCompletion===>");
    }
}

执行顺序

在这里插入图片描述

  • 谁配置在前谁先执行preHandler方法
  • Z字型执行顺序,注意postHandler和afterCompletion是后配置的拦截器先执行

在这里插入图片描述

  • 若第二个拦截器的preHandler方法返回false(不进入controller类的方法),则直接跳转到第一个拦截器的afterCompletion去执行
    在这里插入图片描述

  • 拦截器1的preHandler——》return true——》controller类的方法还有拦截器——》拦截器2的preHandler——》return true——》执行controller类方法——》拦截器2的postHandler——》拦截器1的postHandler——》拦截器2的afterCompletion——》拦截器1的afterCompletion——》返回客户端响应

  • aftercompletion:所有请求和posthandler执行完毕才执行

  • 日志拦截器可获取当前执行的方法和处理对象
    在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值