SpringMVC知识

一、SpringMVC简述

Spring

Spring核心技术分IOC、AOP
Spring创建对象的容器:ApplicationContext

  String config="applicationContext.xml";
  ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  GoodsService goodsService = (GoodsService) ac.getBean("goodsService");
  goodsService.buy(1001,20);

使用web的监听器后,容器创建使用WebApplicationContextUtils
获取ServletContext中的容器对象(因为监听器会扫描spring的配置文件,创建spring容器ApplicationContext对象)

WebApplicationContext ac=null;
  String key = WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;
  Object act= getServletContext().getAttribute(key);
  if(act!=null){
    ac= (WebApplicationContext) act;
  }
  WebApplicationContext ac=null;
// 使用框架中的工具类WebApplicationContextUtils,获取容器对象
  ServletContext sc = getServletContext();
   ac = WebApplicationContextUtils.getWebApplicationContext(sc);
  StudentService service = (StudentService) ac.getBean("studentService");

DI实现了IOC功能,Spring底层通过反射创建对象
DI注入分xml配置文件、注解

  • XMl配置文件:
    简单类型:使用配置文件的bean标签,属性value
    引用类型:使用set注入、构造注入。
    引用类型的自动注入:byName、byType(同类、父子类、接口与实现类)
  • 注解:
    @Component、@Repository、@Service、@Controller
    属性的简单类型@value
    属性的引用类型:@Autowired、@Resource
    @Autowire默认byType,与@Qualifier配合使用byName
    @Resource默认byName,失败用byType

AOP
AOP面向切面编程,通过动态代理实现。
AOP实现方式:Spring、AspectJ(常用)

切面类;把增强的功能加入到目标方法前后
通知:在哪儿添加增强
@Before、@After、@Around、@AfterThrowing、@AfterReturning

Spring事务:
传播行为、隔离级别、是否只读、回滚异常

Spring整合MyBatis

Spring整合Web

SpringMVC

Spring容器,通过监听器扫描配置文件创建对象。容器为ApplicationContext。
SpringMVC容器,通过@Controller注解,把对象放入容器。容器为WebApplicationContext。
用DIspatcherServlet创建容器WebApplicationContext。
@Controller注解创建的对象不是Servlet,DIspatcherServlet才是Servlet

forward转发,redirect是重定向

SpringMVC用过滤器filter解决post请求乱码的问题。

过滤器(post提交中文乱码)、拦截器(拦截请求)

二、SpringMVC的使用

1、SpringMVC的概念

  • SpringMVC:
    基于Spring框架,是Spring的一个模块,专门做web开发,可以理解为Servlet的一个升级。(但是不是Servlet)
  • web:
    web底层是Servlet,SpringMVC框架在Servlet上加入新的功能,让做web更方便
  • SpringMVC是一个Spring、可以创建对象
    Spring是容器,IOC可以管理对象,使用bean标签、注解(如@Component、@Repository、@Service、@Controller)。
    SpringMVC创建对象,把对象放入SpringMVC容器中,容器 放控制器对象。
  • 做什么
    使用@Controller创建控制器对象,放入SpringMVC容器中,把创建的对象当做控制器使用。
    控制器对象可以接收用户请求、显示处理结果,可当做Servlet使用
  • @Controller创建的对象是普通类对象,不是Servlet。怎么成为Servlet?
  • SpringMVC给控制器对象一些额外功能,让它称为Servlet。用DispatcherServlet,即中央调度器
    Web底层是Servlet,SpringMVC有一个对象是Servlet,即DispatcherServlet(中央调度器)
  • DispatcherServlet,负责接收用户请求:
    用户把请求给DispatcherServlet,DispatcherServlet把请求转发给Controller对象(控制器的对象),最后controller对象处理请求。

在这里插入图片描述

  • 总结:
    spring是Spring容器,SpringMVC是SpringMVC容器
    SpringMVC基于Spring,,可以使用Spring的IOC、AOP
    @Controller创建的对象是普通类的对象,不是Servlet,SpringMVC的中央调度器是Servlet,即DispatcherServlet

过滤器(post提交中文乱码)、拦截器(拦截请求)

2.创建SpringMVC项目

new module --webapp

  • pom.xml
    servlet依赖、SpringMVC依赖
    <!--Servlet依赖-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <!-- provided:表明该包只在编dao译和测试的时候属用,-->
    <!--springmvc依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
  • web.xml
    为4.0版、配置中央调度器、配置tomcat启动后创建Servlet对象、配置扫描SpringMVC的配置文件、配置mappering、创建springMVC.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_4_0.xsd"
         version="4.0">

    <!--1.声明、注册SpringMVC的核心对象中央调度器DispatcherServlet。-->
    <!-- 需要在Tomcat服务器启动后,创建DispatcherServlet对象的实例(why?)
         因为DispatcherServlet在它的创建过程中,会同时创建容器SpringMVC容器对象,
         读取SpringMVC的配置文件,把这个配置文件中的对象都创建好,当用户发起请求时就可以直接使用对象了-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--2.配置SpringMVC配置文件的路径(相对路径)-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!--3.tomcat启动后,创建Servlet对象-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--4.配mappering-->
    <servlet-mapping>
        <!--1:*.do2/   -->
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>
  • springMVC.xml
    声明组件扫描器、视图解析器
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<!-- 1.声明组件扫描器-->
    <context:component-scan base-package="com.spring.controller"/>

<!-- 2.声明SpringMVC框架中的视图解析器,帮助开发人员设置视图文件的路径-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前缀:视图文件的路径-->
        <property name="prefix" value="/WEB-INF/view/"/>
        <!--后缀:表示视图文件的扩展名-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>
  • 写index.jsp
    启动tomcat,发起请求xxx.do
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>index.jsp</title>
</head>
<body>
<p><a href="some.do">发起some.do请求</a></p>
<p><a href="other.do">发起other.do请求</a></p>

</body>
</html>
  • controller类
    处理用户提交的请求,SpringMVC中是使用方法来处理的。
    方法定义:自定义,多种返回值,多种参数,方法名称自定义
    发送请求:
    把数据放入ModelAndView,即request作用域,并且转发请求到jsp页面,在jsp页面从ModelAndView作用域的request获得数据
@Controller
public class myController {
// @RequestMapping(value = "/some.do")
 @RequestMapping(value = {"/some.do","/first.do"})
 public ModelAndView doSome(){// doGet()--service请求处理
//  处理some.do。相当于service调用处理完成了
  ModelAndView mv = new ModelAndView();
//  添加数据,框架在请求的最后,把数据放到request作用域
  //request.setAttribute("msg", "欢迎使用SpringMVC做web开发");
  mv.addObject("msg", "欢迎使用SpringMVC做web开发");
  mv.addObject("fun","执行的是doSome方法");
//  指定视图,指定视图的完整路径
//  框架对试图执行的是forward的操作,request.getRequestDispatcher("/show.jsp").forward(..)

//  配置视图解析器后,可以直接用逻辑名称(文件名),指定师徒。
  mv.setViewName("show");
  return  mv;
 }

 @RequestMapping(value = {"/other.do","/second.do"})
 public ModelAndView doOther(){
  ModelAndView mv = new ModelAndView();
// 把数据放到request作用域
  mv.addObject("msg", "欢迎使用SpringMVC做web开发");
  mv.addObject("fun","执行的是doOther方法");
//转发页面
  mv.setViewName("other");
  return  mv;
 }
}

  • jsp页面使用ModelAndView的数据
<h3>msg数据: ${msg}</h3>
  • pom文件
    把src/main/java映射、添加指定jdk版本
    <!--    把src/main/java目录的xml文件包含到输出结果中。输出到classes文件中-->
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
    <!-- 指定jdk版本-->
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>

3.SpringMVC的执行流程

  • tomcat启动后,根据中央调度器创建Servlet对象,也创建容器。中央调度器需要配置文件,从配置文件中找到controller类,从controller类中的@Controller注解,创建控制器对象,放入SpringMVC容器,根据请求xxx.do找到对应的方法。
    在这里插入图片描述
  • 请求处理工程
    执行Servlet的Service方法
    执行dosrvice方法
    执行中央调度器的doDispatch()方法中的控制类的方法,即controller的dosome方法
  • webapp 的xxx.jsp直接可以访问
    不用经过Servlet,不过会不带数据。
    把jsp页面放入WEB-INF下,可以直接访问,因为EB-INF目录下的文件是可保护的
  • 通过视图解析器,把jsp页面指定到EB-INF下
    WEB-INF下的文件可受保护
    用视图解析器可以简化jsp页面的写法

配置视图解析器

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前缀:视图文件的路径-->
        <property name="prefix" value="/WEB-INF/view/"/>
        <!--后缀:表示视图文件的扩展名-->
        <property name="suffix" value=".jsp"/>
    </bean>

controller的方法中使用逻辑名(文件名)指定视图(jsp文件)。达到转发视图的功能
下面代码,就是转发到other.jsp页面,并且通过ModelAndView携带数据

 ModelAndView mv = new ModelAndView();
 mv.addObject("fun","执行的是doOther方法");
 mv.setViewName("other");
  • controller类的@Controller与@RequestMapping
    @Controller表示创建控制器对象,使用在类上
    @RequestMapping使用在方法上,表示请求。
    @RequestMapping(value="/some.do"),或者多个请求@RequestMapping( “/some.do”,"/other.do")
    @RequestMapping使用在类上、方法上

三、SpringMVC的注解式开发

1、@RequestMapping的使用

ch01项目

  • @RequestMapping的使用;
    控制器方法上,表示方法的请求
    控制器类上, 表示方法请求的公共部分

如@RequestMapping("/test/some.do"),
把@RequestMapping("/test)放在类上,把@RequestMapping("/some.do)放在方法上,

  • RequestMapping请求映射
    在方法上使用
    属性:method,表示请求的方式(枚举值)

如get请求方式,

@RequestMapping(value = "/some.do",method = RequestMethod.GET) 

post请求方式,

@RequestMapping(value = "/other.do",method = RequestMethod.POST)

没有请求方式,无限制(get、POST都行,没有也行)

2、处理方法的参数、post提交乱码

ch02项目
controller的方法

  • 形参:
    HttpServletRequest request 请求
    HttpServletResponse response 回话
    HttpSession session session

使用request作用域的数据

ModelAndView mv = new ModelAndView();
// 把数据放到request作用域
  mv.addObject("msg", "name= "+request.getParameter("name"));

注意form表单:method设置get或者post

  • post请求中文乱码
    过滤器自定义,或者使用框架的过滤器CharacterEncodingFilter
    web.xml配置过滤器

web.xml配置过滤器

<!-- 2.注册声明 过滤器,解决post请求乱码的问题-->
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!--设置项目中使用的字符编码-->
    <init-param>
     <param-name>encoding</param-name>
     <param-value>utf-8</param-value>
    </init-param>
    <!--强制请求对象(HTTPServletRequest)使用encoding编码的值-->
    <init-param>
      <param-name>forceRequestEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
    <!--强制应答对象(HTTPServletResponse)使用encoding编码的值-->
    <init-param>
      <param-name>forceResponseEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
      <!-- /* 表示强制所有的请求先通过过滤器处理-->
    <url-pattern>*.do</url-pattern>
  </filter-mapping>

3、收参

ch03项目

  • 控制器方法的参数:
    HttpServletRequest request 请求
    HttpServletResponse response 回话
    HttpSession session session

3.1、 逐个收参-零散数据

如零散数据的收参,String name,Integer age

@Controller
@RequestMapping(value = "/user0")
public class myController {
//零散数据的收参
 @RequestMapping(value = "/some.do")
 public ModelAndView doFirst(String name,Integer age){

  ModelAndView mv = new ModelAndView();
// 把数据放到request作用域
  mv.addObject("myName", name);
  mv.addObject("myAge",age);
//转发页面
  mv.setViewName("show");
  return  mv;
}
}

jsp页面

 %@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>对象数据的收参</title>
</head>
<body>

<h2>对象数据的收参</h2>
<form action="user/some.do" method="post">
    姓名:<input type="text" name="name"><br/>
    年龄:<input type="text" name="age"><br/>
    <input type="submit" value="提交参数">
</form>
</body>
</html>

jsp文件的参数与表单输入框的name一致。int为Intege更好
post提交中文乱码,使用过滤器CharacterEncodingFilter

3.2、@RequestParam-零散数据

@RequestParam 当请求的参数与处理方法的参数不一致
属性:value ,添加请求的参数名
required,表示请求必须有参数,默认true。

@Controller
@RequestMapping(value = "/user1")
public class myController1 {
//零散数据的收参
 @RequestMapping(value = "/some.do")
 public ModelAndView doFirst(@RequestParam(value = "rname",required = true) String name, @RequestParam("rage")Integer age{
  ModelAndView mv = new ModelAndView();
// 把数据放到request作用域
  mv.addObject("myName", name);
  mv.addObject("myAge",age);
//转发页面
  mv.setViewName("show");
  return  mv;
 }
 <form action="user2/some.do" method="post">
    姓名:<input type="text" name="rname"><br/>
    年龄:<input type="text" name="rage"><br/>
    <input type="submit" value="提交参数">
</form>

3.3、对象收参

controller参数为对象,如Student

@Controller
@RequestMapping(value = "/user2")
public class myController2 {
//对象数据的收参

 @RequestMapping(value = "/some.do")
 public ModelAndView doFirst(Student s){
  ModelAndView mv = new ModelAndView();
// 把数据放到request作用域
  mv.addObject("myName", s.getName());
  mv.addObject("myAge",s.getAge());
//转发页面
  mv.setViewName("show");
  return  mv;
 }
}

jsp页面

<form action="user/some.do" method="post">
    姓名:<input type="text" name="name"><br/>
    年龄:<input type="text" name="age"><br/>
    <input type="submit" value="提交参数">
</form>

4、返回值

ch04-return

4.1、返回值是ModelAndView:

ModelAndView:分model、view
model:把数据放入request作用域
view:转发到视图(jsp页面)

public class MyController {
// 返回值是ModelAndView,不仅可以传参(request作用域),也可以转发视图(forward)
 @RequestMapping("/some.do")
 public ModelAndView doSome(String name, Integer age) {
  ModelAndView mv = new ModelAndView();
  mv.addObject("myName", name);
  mv.addObject("myAge", age);
  mv.setViewName("show");

  return mv;
 }

4.2、返回值是String

返回值是string,配合request手动传参(request作用域),可以转发视图(forward)

string是视图逻辑名,需要视图解析器

 @RequestMapping("/some.do")
 public String doSome(String name, Integer age, HttpServletRequest request)   {

  request.setAttribute("myName", name);
  request.setAttribute("myAge", age);
  return "show";
 }

返回值是string,不传参,仅仅转发视图(forward)
string是视图完整路径,不需要视图解析器

 @RequestMapping("/other.do")
 public String doOther(String name, Integer age)   {
  return "/WEB-INF/view/show.jsp";
 }
}

jsp文件,视图

<form action="user/some.do">
    用户名:<input type="text" name="name"/><br/>
    年龄:<input type="text" name="age"/><br/>
    <input type="submit" value="提交"/>
</form>

4.3、返回值是void(了解)

返回值是void,不可传参,不能转发视图
返回值是void,配合ajax请求。配合response,可以输出内容

 // 返回值是void,配合ajax请求
 @RequestMapping("/some.do")
 public void doSome(String name, Integer age, HttpServletResponse response) throws IOException {

//处理ajax,使用json作为数据格式
  // service调用完成,使用Student表示处理结果
  Student student = new Student();
  student.setAge(age);
  student.setName(name);

//把对象转为json
  String json = null;
  if (student != null) {
   ObjectMapper om = new ObjectMapper();
   json = om.writeValueAsString(student);
  }

//  输出数据,响应ajax请求
  response.setContentType("application/json;charSet=utf-8");
  PrintWriter pw = response.getWriter();
  pw.println(json);
  pw.flush();
  pw.close();
 }

jsp文件,即视图
ajax请求

<head>
    <title>返回值是void</title>
    <script type="application/javascript" src="js/jquery-1.8.3.js"></script>
    <script type="application/javascript">
        $(function () {
            $("#btn").click(function () {
                $.ajax({
                    url: "user2/some.do",
                    data: {
                        name: "zairian",
                        age: 25
                    },
                    type: "post",
                    dataType: "json",
                    success: function (data) {
                        console.log(data)
                        // console.log("name= "+data.name+", age= "+data.age)
                    }
                })
            })
        })

    </script>
</head>
<body>
<button id="btn">发起ajax请求</button>

</body>

4.4、返回值是object

Object为Integer、String、自定义对象、map、list等
返回值不以视图出现,而是以数据出现在视图中

返回对象:需要使用@ResponseBody注解,景数据转化为JSON数据,放到响应中
添加Jackson依赖、注解驱动、@ResponseBody

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.6</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.6</version>
    </dependency>
<!--3.注解驱动-->
    <mvc:annotation-driven/>
@Controller
@RequestMapping("/user")
public class MyController3 {
 /*
 * 使用spring配置文件的<mvc:annotation-driven>,实现java数据转换json数据
 * 使用@ResponseBody,响应页面(数据、响应类型等)
 * */
 // 返回值是Object的Student对象,配合ajax请求
 @ResponseBody
 @RequestMapping("/some-student.do")
 public Student doSome(String name, Integer age, HttpServletResponse response) throws IOException {

//处理ajax,使用json作为数据格式
  // service调用完成,使用Student表示处理结果
  Student student = new Student();
  student.setAge(25);
  student.setName("黎小何");
  return  student; //会把框架转换为json数据
 }

 // 返回值是Object的List<Student>集合,配合ajax请求
 @RequestMapping("/some-list.do")
 @ResponseBody
 public List<Student> doSomeList(String name, Integer age, HttpServletResponse response) throws IOException {
  List<Student> list = new ArrayList<>();
//处理ajax,使用json作为数据格式
  // service调用完成,使用Student表示处理结果
  Student student = new Student();
  student.setAge(25);
  student.setName("李四");
  list.add(student);

  student = new Student();
  student.setAge(26);
  student.setName("张三");
  list.add(student);
  return  list;
 }

 // 返回值是Object的List<Student>集合,配合ajax请求
 @RequestMapping(value = "/some-string.do",produces = "text/plain;charset=utf-8")
 @ResponseBody
// 默认使用响应类型 text/plain;charset=ISO-8859-1,导致中文有乱码,给@RequestMapping增加produces,指定响应类型
 public String doSomeString(String name, Integer age, HttpServletResponse response) throws IOException {
//处理ajax,使用json作为数据格式
  // service调用完成,使用Student表示处理结果
  return  "返回String:helloWorld";
 }
}

jsp页面,即视图

<%@ page contentType="text/html;charset=UTF-8" pageEncoding="utf-8" language="java" %>
<html>
<head>
    <title>返回值是Object的List集合</title>
    <script type="application/javascript" src="js/jquery-1.8.3.js"></script>
    <script type="application/javascript">
        // json数据为对象
        $(function () {
            $("#btn").click(function () {
                $.ajax({
                    url:"user/some-student.do",
                    data:{
                        name:"zairian",
                        age:25
                    },
                    type:"post",
                    dataType:"json",
                    success:function (data) {
                        console.log(data)
                        // console.log("name= "+data.name+", age= "+data.age)
                    }
                })
            })
        })

        // json数据为list
        $(function () {
            $("#btn1").click(function () {
               $.ajax({
                   url:"user/some-list.do",
                   data:{
                       name:"zairian",
                       age:25
                   },
                   type:"post",
                   dataType:"json",
                   success:function (data) {
                      // data中服务器返回的是json的字符串{"name":"张欢欢","age":"25"}
                      // jquery会把字符串转为json对象,赋值给data形参
                      $.each(data,function (i,n) {
                          // i表示第几个json,n表示第几个json字符串
                          console.log(n.name+", "+n.age)
                      })
                   }
               })
            })
        })

        // json数据为字符串
        $(function () {
            $("#btn2").click(function () {
                $.ajax({
                    url:"user/some-string.do",
                    data:{
                        name:"zairian",
                        age:25
                    },
                    type:"post",
                    // dataType:"json",
                    success:function (data) {
                        // data中服务器返回的是json的字符串{"name":"张欢欢","age":"25"}
                        // jquery会把字符串转为json对象,赋值给data形参
                            alert(data)
                    }
                })
            })
        })
    </script>

</head>
<br>
    <button id="btn">发起ajax请求,数据是自定义对象</button></br>
    <button id="btn1">发起ajax请求,数据是(泛型为对象的)list</button></br>
    <button id="btn2">发起ajax请求,数据是string字符串</button>

</body>
</html>

5、静态资源

ch05-url_pattern

  • SpringMVC发送请求,资源处理用什么服务器?
    jsp、图片、js、html都用tomcat处理
    xxx.do等请求用SpringMVC的Servlet,即中央调度器DispatcherServlet处理
    所以,tomcat会处理静态资源。

  • web.xml配置
    tomcat的web.xml有一个default Servlet,在服务器启动是创建。
    默认Servlet作用:处理静态资源、处理未映射到其他Servlet的请求
    前提:中央调度器Servlet的url-pattern不能用/

  • 当中央调度器的url-pattern使用 / 后:
    tomcat默认的Servlet会被代替,结果静态资源找不到,即404
    原因:
    DispatcherServlet没有处理静态资源的能力,这样动态资源可以访问,静态资源就访问不到。
    故,tomcat默认的Servlet无法无法使用,静态资源就访问不到
    解决:2种

5.1、如何处理静态资源

由于中央调度器的url-pattern使用 / 后,tomcat默认的Servlet无法使用,导致静态资源无法访问。
怎么操作,让tomcat默认的Servlet可以使用,即访问静态资源成功

法一:配置默认Servlet处理器

SpringMVC配置文件springmvc.xml,添加tomcat默认Servlet的Hander

 <mvc:default-servlet-handler/>

加入它后,框架会创建控制器对象DefaultServletHttpRequestHandler,它会把接收到的请求转发给Tomcat的默认Servlet

  • tomcat可以处理静态资源,无法处理请求如xxx.do
    原因:@RequestMapping与tomcat的默认Servlet冲突
    解决:springmvc.xml添加注解驱动
<mvc:annotation-driven/>

中央调度器的url-pattern为/

  • 总结:
    中央调度器的url-pattern用/
    加入注解驱动
    加入tomcat默认Servlet的Hander
    优点:使用方便
    缺点:必须使用tomcat默认的Servlet
法二:配置静态资源到resources

加入<mvc:resources后,框架会创建ResourcesServletRequestHandler对象,它处理静态资源的访问,不依赖tomcat
mapping:访问静态资源的url,用通配符
location:静态资源在项目的目录位置

把静态资源放入resources的static下,后来可以把静态资源放入nginx的static下

springmvc.xml添加

<mvc:resources mapping="/static/**" location="/static/"/>
总结

由于中央调度器的url-pattern使用 / 后,tomcat默认的Servlet无法使用,导致静态资源无法访问。
解决:让tomcat默认的Servlet可以使用,即访问静态资源成功

  • 配置文件springmvc.xml添加
    tomcat默认Servlet的处理器、注解驱动
 <mvc:default-servlet-handler/>
 <mvc:annotation-driven/>
  • 配置文件springmvc.xml添加
    把 静态资源映射到resources的static下
<mvc:resources mapping="/static/**" location="/static/"/>

以后controller的请求不使用xxx.do,使用xxx。
如 @RequestMapping(value = “/some”)

四、SSM整合开发

ch07-SSM

SSM=SpringMVC+Spring+MyBatis
SpringMVC的Servlet功能,Spring的IOC与AOP功能,MyBatis数据库

1、流程

在这里插入图片描述
SpringMVC管理controller
Spring管理dao、service对象。
MyBatis的数据库

SpringMVC容器为Spring容器的子容器,像继承
故,SpringMVC可以访问Spring的dao、service

SpringMVC容器:WebApplicationContext
Spring容器:ApplicationContext

2、SSM项目

  • pom.xml
    jdk
    junit、Servlet、jsp、SpringMVC、Spring事务、Spring-jdbc
    json的Jackson、Spring整合MyBatis、MyBatis、mysql驱动
    阿里连接池
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.spring</groupId>
  <artifactId>ch07-SSM</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>


  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
<!--    servlet依赖-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>
<!--    jsp依赖-->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2.1-b03</version>
      <scope>provided</scope>
    </dependency>
<!--    springmvc依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
<!--    spring事务-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
<!--    json的依赖-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>
<!--    spring整合mybatis-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.1</version>
    </dependency>
<!--    mybatis依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.2</version>
    </dependency>
<!--mysql驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.9</version>
    </dependency>
<!--    阿里巴巴连接池-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.12</version>
    </dependency>
  </dependencies>

  <build>
    <!-- 把src/main/java目录的xml文件包含到输出结果中。输出到classes文件中-->
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
    <!-- 指定jdk版本-->
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
  • web.xml
    中央调度器、监听器(spring容器)、过滤器(解决post请求中文乱码)
<?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_4_0.xsd"
         version="4.0">
<!-- 1.中央调度器:创建springmvc容器,创建控制器对象-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:conf/dispatcherServlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <!--1:*.do。  法2/   -->
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
<!--2.监听器:创建spring容器-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:conf/applicationContext.xml</param-value>
    </context-param>
    <!--注册监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

<!--    3.过滤器:解决post请求中文乱码-->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!--设置项目中使用的字符编码-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <!--强制请求对象(HTTPServletRequest)使用encoding编码的值-->
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <!--强制应答对象(HTTPServletResponse)使用encoding编码的值-->
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <!-- /* 表示强制所有的请求先通过过滤器处理-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

  • SpringMVC配置文件—dispatcherServlet.xml
    不用springmvc.xml,使用dispatcherServlet.xml
    组件扫描器、视图解析器、注解驱动
<!--springmvc配置文件和web相关的对象。声明controller-->
    <!--1.组件扫描器-->
    <context:component-scan base-package="com.spring.controller"/>
    <!--2.视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
<!--3.注解驱动:响应ajax返回json,解决静态资源访问问题-->
    <mvc:annotation-driven/>
  • Spring 配置文件—applicationContext.xml
    小配置文件、数据源、SqlSessionFactoryBean、dao、service、事务(注解、aspect任选一)
<!--0.spring配置文件-->
    <!--读取小配置文件-->
    <context:property-placeholder location="classpath:conf/jdbc.properties"/>
<!--1.数据源-->
    <bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init" destroy-method="close">
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="maxActive" value="${jdbc.max}" />
    </bean>
<!--2.声明mybatis如果的SqlSessionFactoryBean类,其类内部创建SqlSessionFactory对象-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="myDataSource"/>
        <property name="configLocation" value="classpath:conf/mybatis-config.xml"/>
    </bean>
<!--3.创建dao对象-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="com.spring.dao"/>
    </bean>
<!--4.声明service-->
   <context:component-scan base-package="com.spring.service"/>
<!--5.事务,注解、aspectJ-->
</beans>
        <!--注意:修改时,只修改到的包路径,还有service的属性-->
  • MyBatis配置文件–mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--settings,控制mybatis的全局行为-->
<!--    <settings>-->
<!--        &lt;!&ndash;mybatis的输出日志&ndash;&gt;-->
<!--        <setting name="logImpl" va lue="STDOUT_LOGGING"/>-->
<!--    </settings>-->

    <!--设置别名-->
    <typeAliases>
        <!--实体类所在的包名-->
        <package name="com.spring.entity"/>
    </typeAliases>

    <!--sql的mapper(sql映射文件)的位置-->
    <mappers>
        <!--<mapper resource=""></mapper>-->
        <package name="com.spring.dao"/>
    </mappers>
</configuration>
  • 小配置文件—jdbc.properties
jdbc.url=jdbc:mysql://localhost:3306/Springdb
jdbc.driver=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=123456
jdbc.max=20

五、SpringMVC核心技术

ch08-forward-redirect项目

Spring的核心技术:IOC、AOP
SpringMVC核心技术:forward、redirect

forward:请求转发,request.getRequestDispatcher(“show.jsp”).forward(request,response);
redirect:重定向, request.sendRedirect(“xxx.jsp”) ;

SpringMVC对Servlet进行封装,即DispatcherServlet,用forward、redirect

请求转发:可以访问WEB-INF中的资源。
重定向: 不可用访问WEB-INF中的资。

1、forward

forward :jsp在WEB-INF下

jsp在WEB-INF下,因为WEB-INF下文件受保护,必须开启视图解析器

 @RequestMapping(value = "/doForward.do")
 public ModelAndView doSome(String name, Integer age) {
  ModelAndView mv = new ModelAndView();
  mv.addObject("myName",name);
  mv.addObject("myAge",age);

//  mv.setViewName("show");//使用视图解析器
//  mv.setViewName("/WEB-INF/view/show.jsp");//不用视图解析器
//  mv.setViewName("forward:/WEB-INF/view/show.jsp");//用forward处理WEB-INF下jsp
  mv.setViewName("forward:/hello.jsp");//用forward处理非WEB-INF下jsp,必须使用视图解析器
  return mv;
 }
  • 有视图解析器
 mv.setViewName("show");//使用视图解析器
  mv.setViewName("forward:/WEB-INF/view/show.jsp");//用forward处理WEB-INF下jsp
  • 无视图解析器
 mv.setViewName("/WEB-INF/view/show.jsp")

forward :jsp不在WEB-INF下

jsp不在WEB-INF下,把jsp文件放入webapp下

 mv.setViewName("forward:/hello.jsp");

2、redirect重定向

重定向不能与视图解析器连用,可以使用ModelAndView
redirect不能访问WEB-INF下资源

mv.setViewName("redirect:/hello.jsp");//用redirect处理非WEB-INF下jsp

原理:
重定向由于一个请求的控制器重定向到另一个页面, 会有2个作用域(控制器作用域、重定向页面的作用域)。

问题:由于2个作用域,造成重定向页面无法收到控制器作用域的数据
重定向后,会把控制器作用域数据作为重定向页面请求的参数,如何收参?

解决:${param.myName}
myName为控制器作用域数据的key

重定向的jsp页面 使用 控制器作用域数据

<h3>name数据:${param.myName}</h3>
<h3>age数据: ${param.myAge}</h3
<h3>age数据: <%=request.getParameter("myAge")%></h3

注意:简单类型这样用

3、异常处理

功能:异常后,抛出异常

  • jsp的form表单,提交请求、数据
  • controller:
    方法获取form表单数据,ModelAndView收参,判断是否有异常(throws 或new 异常)
  • 异常父类、多个异常子类
    父类继承Exception,子类继承父类
  • 异常处理的类
    类上添加@ControllerAdvice,异常方法为表单数据的异常、其他异常的处理。
    @ControllerAdvice:控制器增强,给控制器增加异常处理功能。
    方法加@ExceptionHandler,value指定异常类型
/**
 @ControllerAdvice:控制器增强,给控制器增加异常处理功能。
 类的上面
 特点:必须在配置文件配置组件扫描器
 */
@ControllerAdvice
public class GlobalExceptionHandler {
// 定义方法处理发生的异常
 /*
   处理异常方法与控制器方法定义一样,可ModelAndView、String、void、对象的返回值
   形参:Exception,表示Controller抛出的异常对象,中国形参可获取发生的异常信息
   @ExceptionHandler(异常的class):表示异常类型,当发生此类型异常时,由此方法处理

 * */
 @ExceptionHandler(value = NameException.class)
 public ModelAndView doNameException(Exception ex){
//  处理NameException的异常
  /*异常发生的处理逻辑
      1.需要把异常记录下来,记录到数据库、日志文件。
         记录一下发生的时间,哪个方法发生的,异常错误内容

      2.发送通知,把异常信息通过邮件、短信、微信发送的相关人员
      3.该用户友好的提示
  */
  ModelAndView mv = new ModelAndView();
  mv.addObject("msg","姓名必须是张欢欢,其他用户不能访问");
  mv.addObject("ex",ex);
  mv.setViewName("nameError");
  return mv;
 }

 @ExceptionHandler(value = AgeException.class)
 public ModelAndView doAgeException(Exception ex){
  ModelAndView mv = new ModelAndView();
  mv.addObject("msg","年龄格式不符合要求,否则会出错!");
  mv.addObject("ex",ex);
  mv.setViewName("ageError");
  return mv;
 }

// 处理其他异常
 @ExceptionHandler()
 public ModelAndView doOtherException(Exception ex){
  ModelAndView mv = new ModelAndView();
  mv.addObject("msg","出错了,请重新输入!");
  mv.addObject("ex",ex);
  mv.setViewName("defaultError");
  return mv;
 }
}

  • web.xml
    监听器、过滤器
  • SpringMVC配置文件
    组件扫描器、视图解析器、注解驱动、异常方法的扫描器
<!--处理异常,需要2-->
    <context:component-scan base-package="com.spring.handler"/>
    <mvc:annotation-driven/>

注解驱动:响应ajax返回json、解决静态资源访问问题、异常处理

  • 异常类的jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>姓名异常处理页面</title>
</head>
<body>
<p>姓名异常处理页面</p></br>
提示信息: ${msg}</br>
异常信息: ${ex.message}
</body>
</html>

4、拦截器

监听器:通过spring配置文件,创建spring容器
过滤器:Springmvc中中文乱码,过滤请求参数
拦截器:拦截请求,对请求做判断、处理。实现HandlerInterceptor接口

4.1、拦截器介绍

  • 拦截器为全局的,可以对多个控制器拦截
    项目中可以有0-多个拦截器,一起拦截用户请求
  • 拦截器使用:
    用户登录拦截、权限拦截、记录日志…

4.2、拦截器的使用步骤

自定义拦截器,实现HandlerInterceptor接口
配置文件,声明拦截器

自定义拦截器

//拦截器方法,拦截用户请求
public class MyInterceptor implements HandlerInterceptor {
 /**preHandle:预处理方法
 参数:request,response,Object handler
      Object handler:被拦截的控制器对象
  返回值:Boolean:
          true:
          false:
  preHandle特点:1.控制器方法之前执行(用户先执行此方法)
                 2.在这个方法中可以获取请求的信息,验证请求是否符合要求,
                 验证用户是否登录,验证用户是否有权限访问某个连接地址(url)
  如果验证失败,可以截断请求,请求不能被处理;如果验证成功,可以放行请求,控制器方法才能执行。
  */
 private long btime=0;
 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  btime=System.currentTimeMillis();
  System.out.println("拦截器的预处理方法:preHandle");
//  request.getRequestDispatcher("/tips.jsp").forward(request,response);
//  return false;
  return true;
 }

//控执行时机:制器方法执行后
// 作用:修改处理器方法作用域、转发的视图
 @Override
 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mv) throws Exception {
  System.out.println("拦截器的后处理方法:postHandle");
//  修改处理器方法的返回值、视图
  if(mv!=null){
   mv.addObject("myDate",new Date());
   mv.setViewName("other");
  }
 }

// 执行时机:在请求完成的最后
// 作用:回收资源。善后工作
 @Override
 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  System.out.println("拦截器的最后执行方法:afterCompletion");
  long etime=System.currentTimeMillis();
  System.out.println("计算从预处理到最后执行方法之间的时间= "+ (etime-btime));

 }
}

SpringMVC配置文件 springmvc.xml

    <!--3.拦截器-->
    <mnv:interceptors>
        <mvc:interceptor>
         <!--指定拦截的url地址
            path:url地址,通配符**-->
            <mvc:mapping path="/**"/>
            <bean class="com.spring.handler.MyInterceptor"/>
        </mvc:interceptor>
    </mnv:interceptors>

4.3、拦截器执行时间

请求处理前,即控制器方法执行前被拦截
控制器方法执行后,进行拦截
在请求处理完成后

4.4、一个拦截器

ch10-interceptor项目

  • 控制器
自定义拦截器

3个方法,且实现HandlerInterceptor 接口

preHandle:预处理方法

作用:判断数据是否正常
拦截时期:在控制器方法执行前
参数:request、response、Object handler(被拦截的控制器对象)
返回值:true,表示继续执行控制器请求;false拦截请求,停止处理请求,跳转到失败页面

返回值:true

 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  System.out.println("拦截器的预处理方法:preHandle11");
  return true;
 }

返回值:false

 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  System.out.println("拦截器的预处理方法:preHandle11");
  request.getRequestDispatcher("/tips.jsp").forward(request,response);
  return false;
 }
postHandle:后处理方法

执行时间:制器方法执行后
作用: 修改处理器方法作用域、转发的视图
参数:request、response、Object handler、ModelAndView

afterCompletion:最后执行的方法

执行时机:在请求完成的最后
作用:回收资源。善后工作
参数:request、response、Object handler、 Exception

如,计算请求的执行时间
在预处理前加入
private long btime=0;
在预处理内添加开始时间
btime=System.currentTimeMillis();
在最后执行的方法添加结束时间
long ctime=System.currentTimeMillis();
两个时间差就是请求执行的时间
long dtime=ctime-btime

//拦截器方法,拦截用户请求
public class MyInterceptor implements HandlerInterceptor {
 /**preHandle:预处理方法
    作用:判断数据是否正常.
  */
 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  System.out.println("拦截器的预处理方法:preHandle11");
//  request.getRequestDispatcher("/tips.jsp").forward(request,response);
//  return false;
  return true;
 }

//执行时机:制器方法执行后
// 作用:修改处理器方法作用域、转发的视图
 @Override
 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mv) throws Exception {
  System.out.println("拦截器的后处理方法:postHandle11");
 }

// 执行时机:在请求完成的最后
// 作用:回收资源。善后工作
 @Override
 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  System.out.println("拦截器的最后执行方法:afterCompletion11");
 }
}

  • SpringMVC配置文件配置拦截器,一个拦截器
    <!--3.拦截器-->
    <mnv:interceptors>
        <mvc:interceptor>
         <!--指定拦截的url地址
            path:url地址,通配符**-->
            <mvc:mapping path="/**"/>
            <bean class="com.spring.handler.MyInterceptor"/>
        </mvc:interceptor>
    </mnv:interceptors>

4.5、多个拦截器

ch11-interceptor2项目

1个controller的一个方法
2个拦截器类
SpringMVC配置文件配置拦截器,多个拦截器

    <!--3.拦截器-->
        <!--拦截器有0-多个,在框架中是list-->
    <mnv:interceptors>
        <!--第一个拦截器-->
        <mvc:interceptor>
         <!--指定拦截的url地址
            path:url地址,通配符**-->
            <mvc:mapping path="/**"/>
            <bean class="com.spring.handler.MyInterceptor"/>
        </mvc:interceptor>
        <!--第二个拦截器-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.spring.handler.MyInterceptor1"/>
        </mvc:interceptor>
    </mnv:interceptors>
多个拦截器执行顺序
  • 若2个拦截器的preHandle方法都为true,顺序为
    preHandle:1,2
    postHandle:2,1
    afterCompletion:2,1
    在这里插入图片描述
  • 只要2个拦截器的preHandle任意一个为false,拦截的请求会停止执行
总结拦截器

controller的方法、类,@Controller、@RequestMapping
自定义拦截器实现HandlerInterceptor 接口,3个方法
springmvc配置文件:视图解析器、组件扫描器、多个拦截器扫描器
web.xml:中央调度器、过滤器(解决post请求中文乱码)

4.6、过滤器、拦截器区别

Filter为过滤器,Interceptor是拦截器,还有监听器(监听spring创建容器的)
Filter是Servlet中对象(范围大),Interceptor是框架中对象(范围小)。
Filter实现Filter接口,Interceptor实现HanderInterceptor接口
filter用来设置请求、响应的参数、属性。(侧重于数据过滤)。Interceptor用来验证请求、可以拦截请求(侧重请求)
filter在interceptor前执行
filter是tomcat创建的对象,interceptor是SpringMVC创建容器
filter一个执行点,interceptor3个执行点
filter处理静态资源。interceptor处理控制器对象,请求为中央调度器接收
filter过滤Servlet的请求响应,interceptor拦截普通类的方法执行

4.7、SpringMVC执行流程

在这里插入图片描述
1.用户发起请求
2.中央调度器接收请求,把请求转发给 处理器映射器
处理器映射器根据请求找到处理器对象,框架再把处理器对象+拦截器放入处理器执行链类中。
3.处理器映射器把处理器执行链发给中央调度器
4.中央调度器根据处理器找到处理器适配器
5.处理器适配器找到处理器,并执行方法返回ModelAndView
处理器适配器 把ModelAndView发给中央调度器
7.中央调度器执行ModelAndView的jsp文件,需要视图解析器。中央调度器把视图的逻辑名发给视图解析器组装。
8.再发给中央调度器
9.中央调度器调用jsp文件,把数据通过中央调度器响应到给用户

映射器根据请求找到执行链
中央调度器根据处理器对象,找到合适的处理器适配器
适配器执行处理器方法,返回ModelAndView
视图解析器把视图组装到视图对象中
视图对象自己进行渲染,形成响应对象
中央调度器响应浏览器

4.8、拦截器使用–登录检查

ch12-interceptor-login-peimission项目
启动tomcat后,进入index.jsp页面,post提交,访问some.do到控制器方法
拦截器拦截请求,判断用户名是否一致,一致就成功,跳转到show.jsp页面,否则跳转到失败页面,即tip.jsp

  • index.jsp
<form action="some.do" method="post">
    姓名:<input type="text" name="name"/></br>
    <input type="submit" value="提交"/>
</form>
  • 控制器controller
@Controller
public class MyController {
    @RequestMapping(value = "/some.do")
    public ModelAndView some(String name, HttpSession session) {

        ModelAndView mv = new ModelAndView();
        session.setAttribute("name", name);
        System.out.println("控制器的方法some方法");
        mv.addObject("myName", name);
        mv.setViewName("show");
        return mv;
    }
}
  • 拦截器
//拦截器方法,拦截用户请求
public class MyInterceptor implements HandlerInterceptor {
    /**
     * preHandle:预处理方法
     * 作用:判断数据是否正常.
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器的预处理方法:preHandle");
        String loginName = "";
        //从session获得name值
        Object name = request.getSession().getAttribute("name");
        System.out.println("Session的name= " + name);
        if (name != null) {
            loginName = (String) name;
        }
//        判断用户是否符合要求
        if (!"lisi".equals(loginName)) {
            request.getRequestDispatcher("/tips.jsp").forward(request, response);
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mv) throws Exception {
        System.out.println("拦截器的后处理方法:postHandle11");

    }
}
  • 成功页面。show.jsp
<head>
    <title>show.jsp</title>
    <script type="application/javascript" src="js/jquery-1.8.3.js"></script>
    <script>
        $(function () {
            $("#btn").click(function () {
                logout()
                window.location.href = "${pageContext.request.contextPath}/index.jsp"
            })

        })

        function logout() {
            <%
            session.removeAttribute("name");
            %>
        }
    </script>
</head>
<body>
<h3>/WEB-INF/view/show.jsp 获取request作用域的数据</h3>
<h3>name数据:${myName}</h3>
<button id="btn">退出</button>
</body>
  • 失败页面,tip.jsp
<body>
tips.jsp用户权限不够,不能执行
</body>
  • 退出页面,loginOut.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
退出登陆,从session中删除数据
<%
    session.removeAttribute("name");
%>
</body>
</html>
  • web.xml
    过滤器、拦截器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值