SpringMVC学习笔记

去年暑假学的时候做的笔记,现在放出来

SpringMVC

三层架构

  1. 咱们开发服务器端程序,一般都基于两种形式,一种C/S架构程序,一种B/S架构程序
  2. 使用Java语言基本上都是开发B/S架构的程序,B/S架构又分成了三层架构
  3. 三层架构
    1. 表现层:WEB层,用来和客户端进行数据交互的。表现层一般会采用MVC的设计模型(SpringMVC)
    2. 业务层:处理公司具体的业务逻辑的(Spring)
    3. 持久层:用来操作数据库的 (Mybatis)

在这里插入图片描述

MVC模型

  1. MVC全名是Model View Controller 模型视图控制器,每个部分各司其职。
  2. Model:数据模型,JavaBean的类,用来进行数据封装。
  3. View:指JSP、HTML用来展示数据给用户
  4. Controller:用来接收用户的请求,整个流程的控制器。用来进行数据校验等。

SpringMVC的优势

  1. 清晰的角色划分:
    前端控制器(DispatcherServlet)
    请求到处理器映射(HandlerMapping)
    处理器适配器(HandlerAdapter)
    视图解析器(ViewResolver)
    处理器或页面控制器(Controller)
    验证器( Validator)
    命令对象(Command 请求参数绑定到的对象就叫命令对象)
    表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)。
  2. 分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要。
  3. 由于命令对象就是一个 POJO,无需继承框架特定 API,可以使用命令对象直接作为业务对象。
  4. 和 Spring 其他框架无缝集成,是其它 Web 框架所不具备的。
  5. 可适配,通过 HandlerAdapter 可以支持任意的类作为处理器。
  6. 可定制性, HandlerMapping、 ViewResolver 等能够非常简单的定制。
  7. 功能强大的数据验证、格式化、绑定机制。
  8. 利用 Spring 提供的 Mock 对象能够非常简单的进行 Web 层单元测试。
  9. 本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。
  10. 强大的 JSP 标签库,使 JSP 编写更容易。
  11. 还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配
    置支持等等。

SpringMVC 和 Struts2 的优略分析

共同点:

  1. 它们都是表现层框架,都是基于 MVC 模型编写的。
  2. 它们的底层都离不开原始 ServletAPI。
  3. 它们处理请求的机制都是一个核心控制器。

区别:

  1. Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
  2. Spring MVC 是基于方法设计的,而 Struts2 是基于类, Struts2 每次执行都会创建一个动作类。所以 Spring MVC 会稍微比 Struts2 快些。
  3. Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便
    (JSR303 是一套 JavaBean 参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们 JavaBean 的属性上面,就可以在需要校验的时候进行校验了。 )
  4. Struts2 的 OGNL 表达式使页面的开发效率相比 Spring MVC 更高些,但执行效率并没有比 JSTL 提升,尤其是 struts2 的表单标签,远没有 html 执行效率高

环境搭建

  1. 新建一个maven项目,创建时下面选择webapp

  2. pom.xml中导入坐标

    <!-- 版本锁定 -->
    <properties>
    	<spring.version>5.0.2.RELEASE</spring.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    
    1. 配置核心控制器(在webapp/WEB-INF/web.xml里面)
      <!-- SpringMVC的核心控制器 -->
      <servlet>
          
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 -->
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:springmvc.xml</param-value>
            <!-- 自动加载xml文件,只有这里配置了才会加载下面的xml文件 -->
        </init-param>
        
        <load-on-startup>1</load-on-startup><!-- 配置servlet启动时加载对象 -->
          
      </servlet>
      <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
    
     <!--还可以配置中文乱码过滤器(在下面)-->
    
    1. springmvc.xml(在resources文件夹下)
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           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">
        
        <!-- 配置spring创建容器时要扫描的包 -->
        <context:component-scan base-package="com.itheima"></context:component-scan>
        <!-- 配置视图解析器 -->
        <!--视图类的方法,返回值是String的时候,会自动跳转到某个页面,看下面怎么配置-->
        <bean id="viewResolver"
              class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/pages/"></property>
            <!-- 跳转到的文件的所在目录 -->
            <property name="suffix" value=".jsp"></property>
            <!-- 文件后缀名 -->
        </bean>
     <!-- 配置spring开启注解mvc的支持-->
        <mvc:annotation-driven></mvc:annotation-driven>
     
        <!--还可配置静态资源拦截问题(见下面)-->
    </beans>
    
    1. 写解析器类
    package com.itheima;
    
    import org.springframework.web.bind.annotation.PatchMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @org.springframework.stereotype.Controller
    public class Controller {
        @RequestMapping("/hello")//访问路径
     public String sayHello(){
            System.out.println("Hello World");
         return "success";   //会自动跳转到 “返回值.jsp”,主要看xml里怎么配置
        }
    }
    
    1. index.jsp
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>Title</title>
        </head>
     <body>
            <h1>入门</h1>
         <a href="hello">跳转</a>
        </body>
    </html>
    
    1. WEB-INF\pages\success.jsp(跳转到的页面,这个jsp放到哪个路径,主要看springmvc.xml怎么配置)
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>Title</title>
        </head>
        <body>
         <h1>成功</h1>
        </body>
    </html>
    
    1. 在上面的Edit Configuration里添加tomcat,然后运行。

RequestMapping注解

作用:用于简历请求URL和处理请求方法之间的对应关系。

出现位置:类上(指定一级目录)、方法上(指定二级目录)

@org.springframework.stereotype.Controller
@RequestMapping("/user")
public class Controller {
    @RequestMapping("/hello")//访问路径
    public String sayHello(){
        System.out.println("Hello World");
        return "success";   //会自动跳转到 “返回值.jsp”,主要看xml里怎么配置
    }
}

如要访问这个方法,那请求URL是/user/hello

属性:

  1. value、path属性:请求URL
  2. method:指定请求方式。(传入RequestMethod枚举类型,如:RequestMethod.POST)
  3. params:用于指定限制请求参数的条件。(传入字符串类型) 它支持简单的表达式。 要求请求参数的 key 和 value 必须和配置的一模一样。
    如:
    params = {“accountName”},表示请求参数必须有 accountName
    params = {“moeny!100”},表示请求参数中 money 不能是 100。
    params = {“moeny=100”},表示请求参数中 money 必须是 100。
  4. headers:用于指定限制请求消息头的条件。
    headers={“Accept”},表示请求头中必须要有Accept
@org.springframework.stereotype.Controller
@RequestMapping(path = "/user")
public class Controller {
    @RequestMapping(path = "/hello",method = {RequestMethod.GET,RequestMethod.POST},params = "username",headers = "Accept")//访问路径
    public String sayHello(){
        System.out.println("Hello World");
        return "success";   //会自动跳转到 “返回值.jsp”,主要看xml里怎么配置
    }
}

*请求参数的绑定

绑定的机制

我们都知道,表单中请求参数都是基于 key=value 的。
SpringMVC 绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的。

例如:

/**
* 查询账户
* @return
*/
@RequestMapping("/findAccount")
public String findAccount(Integer accountId) {
System.out.println("查询了账户。。。。 "+accountId);
return "success";
}
<a href="account/findAccount?accountId=10">查询账户</a>

支持的数据类型

  1. 基本类型参数:包括基本类型和 String 类型

  2. POJO 类型参数:包括实体类,以及关联的实体类

  3. 数组和集合类型参数:包括 List 结构和 Map 结构的集合(包括数组)

SpringMVC 绑定请求参数是自动实现的,但是要想使用,必须遵循使用要求。

使用要求

  1. 如果是基本类型或者 String 类型:
    要求我们的参数名称必须和控制器中方法的形参名称保持一致。 (严格区分大小写)
  2. 如果是 POJO 类型,或者它的关联对象:
    要求表单中参数名称和 POJO 类的属性名称保持一致。并且控制器方法的参数类型是 POJO 类型。
  3. 如果是集合类型,有两种方式:
    1. 第一种:要求集合类型的请求参数必须在 POJO 中。在表单中 请求参数名称要和 POJO 中集合属性名称相同。
      给 List 集合中的元素赋值, 使用下标。
      给 Map 集合中的元素赋值, 使用键值对。
    2. 第二种:接收的请求参数是 json 格式数据。需要借助一个注解实现。
注意:
它还可以实现一些数据类型自动转换。 内置转换器全都在:
org.springframework.core.convert.support 包下。 有:
java.lang.Boolean -> java.lang.String : ObjectToStringConverter
java.lang.Character -> java.lang.Number : CharacterToNumberFactory
java.lang.Character -> java.lang.String : ObjectToStringConverter
java.lang.Enum -> java.lang.String : EnumToStringConverter
java.lang.Number -> java.lang.Character : NumberToCharacterConverter
java.lang.Number -> java.lang.Number : NumberToNumberConverterFactory
java.lang.Number -> java.lang.String : ObjectToStringConverter
java.lang.String -> java.lang.Boolean : StringToBooleanConverter
java.lang.String -> java.lang.Character : StringToCharacterConverter
java.lang.String -> java.lang.Enum : StringToEnumConverterFactory
java.lang.String -> java.lang.Number : StringToNumberConverterFactory
java.lang.String -> java.util.Locale : StringToLocaleConverter
java.lang.String -> java.util.Properties : StringToPropertiesConverter
java.lang.String -> java.util.UUID : StringToUUIDConverter
java.util.Locale -> java.lang.String : ObjectToStringConverter
java.util.Properties -> java.lang.String : PropertiesToStringConverter
java.util.UUID -> java.lang.String : ObjectToStringConverter
......
如遇特殊类型转换要求,需要我们自己编写自定义类型转换器。

post请求的中文乱码解决

以前是要这样子配置:

request.setCharacterEncoding("utf-8");

现在加一个过滤器:WEB-INF/web.xml里的filter标签里面的开头:

  <!-- 配置 springMVC 编码过滤器 -->
  <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>
    <!-- 启动过滤器 -->
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <!-- 过滤所有请求 -->
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  

测试

  1. String类型:(参数名和key值一样)
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/param")
public class ParamController {

    @RequestMapping("controller")
    public String param(String username,String password){
        System.out.println(username);
        System.out.println(password);
        return "success";
    }
}
<a href="param/controller?username=zhangsan&password=123">String参数绑定</a>
  1. Java Bean对象:(bean对象的属性名和key值一样)

    Account类:

/**
 * @AUTHOR Prince
 * @TIME 2020/7/17 16:25
 */

package com.itheima.Account;

public class Account {
    private String username;
    private String password;
    private int age;

    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;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Account{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }
}

​ 解析器:

    @RequestMapping("account")
    public String param2(Account account){
        System.out.println(account);
        return "success";
    }

​ JSP:

<%--
  Created by IntelliJ IDEA.
  User: Prince
  Date: 2020/7/17
  Time: 16:24
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户</title>
</head>
<body>
    <h1>用户登录</h1>
    <form action="param/account" method="post">
        <label>用户名</label>  <input type="text" name="username"><br>
        <label>密码</label>  <input type="password" name="password"><br>
        <label>年龄</label>  <input type="number" name="age"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

▲如果希望在这个JavaBean对象里面封装另一个javabean对象,并且希望赋值。

如:在上面Account里还有一个名为user的User对象,User里又有username和password,首先在Account里加上User的getter和setter,User类里也加上getter setter,那么请求参数的key值必须是user.username , user.password

<label>用户名</label>  <input type="text" name="user.username"><br>
  1. List、Map等集合类型
<!--对于List类型,参数的key值直接是list[索引]-->
<label>用户名</label>  <input type="text" name="list[0]"><br>
<label>用户名</label>  <input type="text" name="list[1]"><br>
<!--对于Map类型,参数的key值直接是map[键值]-->
<label>用户名</label>  <input type="text" name="map["username"]"><br>
<!--对于List<User>类型,参数的key值直接是list[索引].User对象的属性-->
<label>用户名</label>  <input type="text" name="list[0].username"><br>

自定义类型转换器

比如参数类型是Date,而在前端输入的文本框的格式可能是yyyy/MM/dd,也可能是yyyy-MM-dd,格式不一,需要自己写一个自定义类型转换器!(yyyy/MM/dd格式是可以正常封装的,不需要自定义!但是yyyy-MM-dd格式是不会被识别的)

e.g.(下面是默认情况,主要是演示一下yyyy/MM/dd格式是能够被识别)

解析器代码:

@RequestMapping("p3")
public String param3(Date date){
    System.out.println(date);
    return "success";
}

JSP页面:

<%--
  Created by IntelliJ IDEA.
  User: Prince
  Date: 2020/8/15
  Time: 20:06
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>自定义类型转换器测试</title>
</head>
<body>
<h1>用户登录</h1>
<form action="param/p3" method="post">
    <label>日期</label>  <input type="text" name="date"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

运行结果:提交2020/08/15:成功;提交2020-08-15:400错误

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

★解决办法:自定义一个类型转换器(Converter)

下面是Spring对这个接口的定义:

/*
 * Copyright 2002-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.core.convert.converter;

import org.springframework.lang.Nullable;

/**
 * A converter converts a source object of type {@code S} to a target of type {@code T}.
 *
 * <p>Implementations of this interface are thread-safe and can be shared.
 *
 * <p>Implementations may additionally implement {@link ConditionalConverter}.
 *
 * @author Keith Donald
 * @since 3.0
 * @param <S> the source type
 * @param <T> the target type
 */
@FunctionalInterface
public interface Converter<S, T> {

	/**
	 * Convert the source object of type {@code S} to target type {@code T}.
	 * @param source the source object to convert, which must be an instance of {@code S} (never {@code null})
	 * @return the converted object, which must be an instance of {@code T} (potentially {@code null})
	 * @throws IllegalArgumentException if the source cannot be converted to the desired target type
	 */
	@Nullable
	T convert(S source);

}

在这里插入图片描述
(Spring也提供了许多内置的转换器)

★下面开始解决:

  1. 自己自定义一个转换器(注意Converter不要导错包)

    package com.itheima.Converter;
    
    import org.springframework.core.convert.converter.Converter;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class StringToDateConverter implements Converter<String, Date> {
    
        @Override
        public Date convert(String source) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            try {
                return sdf.parse(source);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    
  2. 使用这个转换器

springmvc.xml里配置这个对象(其实就是往Spring的IOC容器里添加ConversionServiceFactoryBean,然后在ConversionServiceFactoryBean里配置转换器)

<!--配置自定义类型转换器-->
<bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.itheima.Converter.StringToDateConverter" />
        </set>
    </property>
</bean>

在这里插入图片描述

ConversionServiceFactoryBean类里面的内容是这样的,我们要把自己写的转换器类注入到里面的Set里!

配置完了之后还要使用这个(必须要告诉他使用的是哪个)(在springmvc.xml的<beans>标签里面的最后加上)

<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/>

测试(成功):

在这里插入图片描述

注意:经过测试发现,一旦自定义了类型转换器,原来的就被覆盖了,比如现在我输入2020-08-15是可以的,但是2020/08/15不行。我觉得这种情况可以直接在你写的转换器那里判断一下就好了。

HiddentHttpMethodFilter 过滤器

(这一部分搬自:https://blog.csdn.net/geloin/article/details/7444321?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param)

浏览器form表单只支持GET与POST请求,而DELETE、PUT等method并不支持,spring3.0添加了一个过滤器,可以将这些请求转换为标准的http方法,使得支持GET、POST、PUT与DELETE请求,该过滤器为HiddenHttpMethodFilter。

HiddenHttpMethodFilter的父类是OncePerRequestFilter,它继承了父类的doFilterInternal方法,工作原理是将jsp页面的form表单的method属性值在doFilterInternal方法中转化为标准的Http方法,即GET,、POST、 HEAD、OPTIONS、PUT、DELETE、TRACE,然后到Controller中找到对应的方法。例如,在使用注解时我们可能会在Controller中用于@RequestMapping(value = "list", method = RequestMethod.PUT),所以如果你的表单中使用的是<form method="put">,那么这个表单会被提交到标了Method="PUT"的方法中。

需要注意的是,由于doFilterInternal方法只对method为post的表单进行过滤,所以在页面中必须如下设置:

<form action="..." method="post">
        <input type="hidden" name="_method" value="put" />
        ......
</form>

而不是使用:

<form action="..." method="put">
        ......
</form>

在web.xml里要配置下面的过滤器

<filter>  
    <filter-name>HiddenHttpMethodFilter</filter-name>  
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>  
</filter>  
<filter-mapping>  
    <filter-name>HiddenHttpMethodFilter</filter-name>  
    <servlet-name>dispatcherServlet</servlet-name>  
</filter-mapping>

​ 同样的,作为Filter,可以在web.xml中配置HiddenHttpMethodFilter的参数,可配置的参数为methodParam,值必须为GET,、POST、 HEAD、OPTIONS、PUT、DELETE、TRACE中的一个。

(好像JSP只支持GET和POST请求,溜了溜了!)

在MVC框架中获取原生的Servlet的API

非常简单的,直接在参数里面输入即可

解析器:

//获取原生API的方式
    @RequestMapping("p4")
    public String param4(HttpServletRequest request, HttpServletResponse response){
        System.out.println(request);
        System.out.println(response);
        return "success";
    }

结果:

在这里插入图片描述

其他注解

RequestParam

上面“请求参数的绑定”那里有说过了,如果要获取请求参数,必须要让形参的名字和参数的key值一样。

使用RequestParam注解可以避免这个问题。

//RequestParam注解测试
@RequestMapping("p5")
public String param5(@RequestParam("username") String name){
    System.out.println(name);
    return "success";
}

这个注解加在形参的前面,值代表请求参数的key值

RequestBody

作用:用于获取请求体内容。 直接使用得到是 key=value&key=value…结构的字符串。
get 请求方式不适用。(get请求没有请求体,那些参数都在地址栏上了)

属性:required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值
为 false, get 请求得到是 null。

//RequestBody注解测试
    @RequestMapping("p6")
    public String param6(@RequestBody String body){
        System.out.println(body);
        return "success";
    }

如果不加@RequestBody,那么就代表获取key为body的数据,加了之后,获取的就是username=htf&password=gdf

(这个注解放在这里现在是没什么用,到以后的异步请求的时候用到json的时候会用到)

PathVariable

作用:用于绑定 url 中的占位符。 例如:请求 url 中 /delete/{id}, 这个{id}就是 url 占位符。
url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 风格 URL 的一个重要标志。

属性:
value: 用于指定 url 中占位符名称。
required:是否必须提供占位符。

在这里插入图片描述

​ (RestFul风格)

<a href="param/p7/100">PathVariable注解测试</a>
//PathVariable
@RequestMapping("p7/{id}")
public String param7( @PathVariable int id){
    System.out.println(id);
    return "success";
}

甚至可以传参:

//PathVariable
@RequestMapping("p7/{sid}")
public String param7( @PathVariable("sid") int id){
    System.out.println(id);
    return "success";
}

RequestHeader

作用:用于获取请求消息头。
属性:
value:提供消息头名称
required:是否必须有此消息头
注:
在实际开发中一般不怎么用。

//RequestHeader注解测试
@RequestMapping(value = "p9")
public String param9(@RequestHeader("Accept") String header){
    System.out.println(header);
    return "success";
}

CookieValue

作用:用于把指定 cookie 名称的值传入控制器方法参数。
属性:
value:指定 cookie 的名称。
required:是否必须有此 cookie。

//CookieValue注解测试
@RequestMapping(value = "p10")
public String param10(@CookieValue("JSESSIONID") String cookies){
    System.out.println(cookies);
    return "success";
}

ModelAttribute

作用:
该注解是 SpringMVC4.3 版本以后新加入的。它可以用于修饰方法和参数。
出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可
以修饰有具体返回值的方法。
出现在参数上,获取指定的数据给参数赋值。

属性:
value:用于获取数据的 key。 key 可以是 POJO 的属性名称,也可以是 map 结构的 key。

应用场景:
当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。

例如:
我们在编辑一个用户时,用户有一个创建信息字段,该字段的值是不允许被修改的。在提交表单数
据是肯定没有此字段的内容,一旦更新会把该字段内容置为 null,此时就可以使用此注解解决问题。

比如我们有一个User类,该类里有username , age,如果我们提交表单的时候只有username,那么age是不被注入的

使用了这个注解可以解决问题(比如给出username,然后再从数据库中查询,然后把age注入)

    //ModelAttribute  注解测试
    @RequestMapping(value = "p11")
    public String param11(User user){
        System.out.println(user);
        return "success";
    }

    @ModelAttribute  //表上这个注解的方法会先执行(然后取返回值)
    public User model(String username){
        User user = new User();
        user.setUname(username);
        user.setAge(50);
        return user;
    }

另外的一中写法(我也不知道怎么表达,自己体会吧~~~)

    //ModelAttribute  注解测试
    @RequestMapping(value = "p11")
    public String param11(@ModelAttribute("abc") User user){
        System.out.println(user);
        return "success";
    }

    @ModelAttribute
    public void model(String username, Map<String,User> map){
        User user = new User();
        user.setUname(username);
        user.setAge(50);
        map.put("abc",user);
    }

SessionAttribute

作用:用于多次执行控制器方法间的参数共享。

属性:
value:用于指定存入的属性名称
type:用于指定存入的数据类型。

这个东东我也不知道干嘛的,参见https://blog.csdn.net/abc997995674/article/details/80462450

Model

这个我不太了解,大概是在控制器里面如果

model.addAttribute("user",user);

那么在接下来在返回成功的页面

return "success";

在success.jsp中可以直接使用EL 表达式来取出对象

${user.username}

获得Model的方法:直接放在控制器的方法参数。

SpringMVC拦截静态资源的问题

默认的SpringMVC会拦截掉那些css,js,image这些资源(不知道他是不是有毛病),如果在一个页面引用这些静态资源是没有反应的,解决方法:

参考:https://blog.csdn.net/qq_40594137/article/details/79112700

问题产生:
因为我们在web.xml中写了 拦截所有请求,当然包括了静态资源,所以页面需要引用css或js的话,该请求也会被拦截,例如:

在style.css中写一个简单样式,加个背景颜色

body{
    background-color: antiquewhite;
}

然后在index.jsp页面引用该样式:<link rel="stylesheet" href="/css/style.css">

再一次运行项目,会看到并没有样式,F12可以看到在调用style.css的时候报了404错误,这是因为被DispatcherServlet拦截了

解决办法:

方案一:拦截器中增加针对静态资源不进行过滤(涉及spring-mvc.xml)

注意:需引入mvc命名空间

 <!-- 添加注解驱动 -->
<mvc:annotation-driven/>
<!--
    通过mvc:resources设置静态资源,这样servlet就会处理这些静态资源,而不通过控制器
    设置不过滤内容,比如:css,js,img 等资源文件
    location指的是本地的真实路径,mapping指的是映射到的虚拟路径。
	**表示这个文件夹下的所有资源
-->
    <mvc:resources mapping="/css/**" location="/css/"/>
    <mvc:resources mapping="/images/**" location="/images/"/>
    <mvc:resources mapping="/js/**" location="/js/"/>

(亲测:配置完直接用不起作用,重启idea后就行了,真奇怪)

方案二:使用默认的servlet处理静态资源(涉及spring-mvc.xml,web.xml)
在spring-mvc.xml中添加:

<!--启用默认Servlet-->
<mvc:default-servlet-handler/>

在web.xml中添加:

<!--增加对静态资源的处理,当前的设置必须在Spring的Dispatcher的前面-->
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.css</url-pattern>
    <url-pattern>/css/*</url-pattern>
  </servlet-mapping>

方案三:修改spring的全局拦截设置为

*.do的拦截(涉及web.xml)

 <!-- 拦截所有请求 -->
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <!--<url-pattern>/</url-pattern>-->
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

这时,我们浏览器的所有访问路径就要变成:http://localhost:8080/xxx/xxx.do

比较总结:
第一种方案配置比较臃肿,多个拦截器时增加文件行数,不推荐使用
第二种方案使用默认的Servlet进行资源文件的访问,Spring拦截所有请求,然后再将资源文件交由默认的Sevlet进行处理,性能上少有损耗
第三种方案Spring只是处理以’.do’结尾的访问,性能上更加高效,但是再访问路径上必须都以’.do’结尾,URL不太文雅

综上所述,推荐使用第二和第三种方案

相应数据和结果视图

返回值类型

String

上面的例子中一直都是返回字符串,跳过

void
@RequestMapping("/testVoid")
public void testVoid(){
    System.out.println("testVoid方法执行了");
}

结果:能够正常执行该方法,但是会出现404页面:

在这里插入图片描述

通过结果可以看到,他有一个默认行为,和return "testVoid";的功能是一样的。

避免上面的问题可以采取以下措施:

  1. 转发到其他页面

    @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("testVoid方法执行了");
        request.getRequestDispatcher("/index.jsp").forward(request,response);
    }
    

    细节:转发的时候的路径一定要写全,不可以是

    request.getRequestDispatcher("success").forward(request,response);
    
  2. 重定向到其他页面

    @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("testVoid方法执行了");
        response.sendRedirect("https://www.baidu.com");
    }
    
  3. 直接在该页面进行相应

    @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("testVoid方法执行了");
        //中文乱码问题
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text-html;charset=UTF-8");
    
        response.getWriter().println("123");
    }
    
*使用关键字进行重定向和转发

需要返回值类型是String,返回值里加上关键字,具体例子如下:

@RequestMapping("/testForward")
public String testForward(){
    System.out.println("testForward方法执行了");
    return "forward:/WEB-INF/pages/success.jsp";
}
@RequestMapping("/testRedirect")
public String testRedirect(HttpServletRequest request){
    System.out.println("testRedirect方法执行了");
    return "redirect:/index.jsp";
}
ModelAndView

ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值。

该对象中有两个方法:

在这里插入图片描述

个人理解就是Model和String的结合而已,下面2种用法的效果都是一样的

@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
    ModelAndView modelAndView = new ModelAndView();

    User user = new User();
    user.setUname("张三");
    user.setAge(20);

    modelAndView.addObject("user",user);
    modelAndView.setViewName("success");
    return modelAndView;
}

@RequestMapping("/testModelAndView_String")
public String testModelAndView_String(Model model){
    User user = new User();
    user.setUname("张三");
    user.setAge(20);
    model.addAttribute("user",user);
    return "success";
}

在success.jsp中

${user.uname}

可以读取到信息。(我也不知为啥识别不了EL表达式,还要手动开启的isELIgnored="false"

JSON

相应json就要发送异步请求,发送异步请求的最好方式还是要使用到jquery,【注:关于静态资源拦截的问题请翻阅上面】

(有关jquery实现ajax,具体查阅:https://www.w3school.com.cn/jquery/ajax_ajax.asp)

  1. json数据的发送

    前端jsp

    <%--
      Created by IntelliJ IDEA.
      User: Prince
      Date: 2020/8/18
      Time: 15:28
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>AJAX测试</title>
        <script src="js/jquery-3.3.1.min.js"></script>
    </head>
    
    
    <body>
        <h1>异步请求test</h1>
        <button id="btn">发送异步请求</button>
    </body>
    
    </html>
    
    <script>
        $(function (){
            $("#btn").click(function (){
                $.ajax({
                    dataType:"json", //发送过去的数据的类型是json
                    data:'{"username":"haha","age":"20"}', //要发送的数据
                    type:"post",   //发送请求的类型
                    contentType:"application/json;charset=UTF-8",   //contentType类型为json(返回来的数据类型是json)
                    url:"testAjax",    //请求url
                    success:function (data) {   //回调函数
                    }
                });
            });
        });
    </script>
    

    后端控制器:

    @RequestMapping("/testAjax")
    public void testAjax(@RequestBody String body /*想要获取客户端发送过来的json类型的数据,就要获取请求体信息*/){
        System.err.println("testAjax方法执行啦");
        System.out.println(body);
    }
    

    输出:

    {"username":"haha","age":"20"}
    testAjax方法执行啦
    

    踩坑:只能用post请求,不能用get请求。我也不知为啥,大概的原因是json的 {} 不在规定的字符之内然后报错

  2. json数据的响应

    响应的时候,spring 为我们可以自动将json转化为javaBean对象(要求这个javaBean对象的属性和json的key值一样),前提是要提前引入jackson的jar包:
    pom.xml

    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.0</version>
    </dependency>
    <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-annotations</artifactId>
    <version>2.9.0</version>
    </dependency>
    
    @RequestMapping("/testAjax")
    public void testAjax(@RequestBody User user){  //spring会自动帮我们将json转换为User
        System.err.println("testAjax方法执行啦");
        System.out.println(user);
    }
    

    同时,spring还可以自动将javaBean对象转化为json,返回值直接是javaBean对象即可,但是需要加上ReponseBody注解:

    @RequestMapping("/testAjax")
    public @ResponseBody User testAjax(@RequestBody User user /*想要获取客户端发送过来的json类型的数据,就要获取请求体信息*/){
        System.err.println("testAjax方法执行啦");
        System.out.println(user);
        User u = new User();
        u.setUsername("张三");
        u.setAge(18);
        return u;
    }
    

    前端jsp:

    ......
    <script>
        $(function (){
            $("#btn").click(function (){
                $.ajax({
                    dataType:"json", //发送过去的数据的类型是json
                    data:'{"username":"haha","age":"20"}', //要发送的数据
                    type:"post",   //发送请求的类型
                    contentType:"application/json;charset=UTF-8",   //contentType类型为json(返回来的数据类型是json)
                    url:"testAjax",    //请求url
                    success:function (data) {   //回调函数
                        //响应服务器端返回来的json
                        document.writeln(data);
                        document.writeln(data.username);
                        document.writeln(data.age);
                    }
                });
            });
        });
    </script>
    

SpringMVC实现文件上传

必要前提

  1. form 表单的 enctype 取值必须是: multipart/form-data
    (默认值是:application/x-www-form-urlencoded)
    enctype:是表单请求正文的类型
  2. method 属性取值必须是 Post(get请求的地址栏放不下)
  3. 提供一个文件选择域<input type="file" />

原理分析

当 form 表单的 enctype 取值不是默认值后,request.getParameter()将失效。
enctype="application/x-www-form-urlencoded"时, form 表单的正文内容是key=value&key=value&key=value
当 form 表单的 enctype 取值为Mutilpart/form-data 时,请求正文内容就变成每一部分都是 MIME 类型描述的正文

-----------------------------7de1a433602ac 					分界符
Content-Disposition: form-data; name="userName" 			协议头
aaa 													协议的正文
-----------------------------7de1a433602ac
Content-Disposition: form-data; name="file";
filename="C:\Users\zhy\Desktop\fileupload_demofile\b.txt"
Content-Type: text/plain 									协议的类型( MIME 类型)
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-----------------------------7de1a433602ac--

借助第三方组件实现文件上传

使用 Commons-fileupload 组件实现文件上传,需要导入该组件相应的支撑 jar 包: Commons-fileupload 和
commons-io。 commons-io 不属于文件上传组件的开发 jar 文件,但Commons-fileupload 组件从 1.1 版本开始,它
工作时需要 commons-io 包的支持。

导入jar包

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

传统方式上传

(我也不会,就是跟着视频敲的)

首先记得要在pom.xml中导入那个坐标依赖

前端jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上传学习——传统方式</title>
</head>
<body>
    <form action="fileUpload01" method="post" enctype="multipart/form-data">
        <input type="file" name="upload" /> <!--踩坑了,没有name就提交没有用的-->
        <input type="submit" value="上传">
    </form>
</body>
</html>

后端java:

@RequestMapping("/fileUpload01")
public String fileUpload01(HttpServletRequest request) throws Exception {
    System.err.println("开始文件上传");
    //获取上传的位置
    String path = request.getSession().getServletContext().getRealPath("/uploads/");

    File file = new File(path);
    //判断路径是否存在,如果不存在则创建
    if(!file.exists()){
        file.mkdirs();
    }

    //获取上传文件项
    DiskFileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload upload = new ServletFileUpload(factory);
    //解析request
    List<FileItem> items = upload.parseRequest(request);
    for (FileItem item : items) {
        //判断item是不是上传文件项
        if(!item.isFormField()){
            //不是普通表单项,则是上传文件项
            String filename = item.getName();
            //把文件名称设置成唯一值UUID
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            filename = uuid + "_" + filename;
            // 完成文件上传
            item.write(new File(path,filename));
            // 删除临时文件
            item.delete();
        }
    }
    return "success";
}

使用SpringMVC上传

在这里插入图片描述

  1. 配置解析器对象,在springmvc.xml中加入下面配置(记得也要先导入那2个jar包)

    <!-- 配置文件解析器对象,要求id名称必须是multipartResolver -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设定默认编码 -->
        <property name="defaultEncoding" value="UTF-8"></property>
        <!-- 设定文件上传的最大值为5MB,5*1024*1024 -->
        <property name="maxUploadSize" value="5242880"></property>
        <!-- 设定文件上传时写入内存的最大值,如果小于这个参数不会生成临时文件,默认为10240 -->
        <property name="maxInMemorySize" value="40960"></property>
        <!-- 上传文件的临时路径 -->
        <!--<property name="uploadTempDir" value="fileUpload/temp"></property>-->
        <!-- 延迟文件解析 -->
        <property name="resolveLazily" value="true"/>
    </bean>
    
  2. 后端的java代码(前端的jsp不变)

    @RequestMapping("/fileUpload02")
    public String fileUpload02(HttpServletRequest request, MultipartFile upload /*这个参数的名字一定要和前端的文件选择框的name一致*/) throws Exception {
        System.err.println("开始文件上传");
        //获取上传的位置
        String path = request.getSession().getServletContext().getRealPath("/uploads/");
        File file = new File(path);
        //判断路径是否存在,如果不存在则创建
        if(!file.exists()){
            file.mkdirs();
        }
        String filename = upload.getOriginalFilename(); //获取文件名称
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        filename = uuid + "_" + filename;  //使文件名唯一化
        upload.transferTo(new File(path,filename));
        return "success";
    }
    

    总结:SpringMVC的方式跟传统方式比起来省去了很多步骤,直接用transferTo方法就可以了。

跨服务器的文件上传

在实际开发中,我们会有很多处理不同功能的服务器。例如:
应用服务器:负责部署我们的应用
数据库服务器:运行我们的数据库
缓存和消息服务器:负责处理大并发访问的缓存和消息
文件服务器:负责存储用户上传文件的服务器。
(注意:此处说的不是服务器集群)

分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。

环境搭建

  1. 新增一个Tomcat服务器用于保存文件。
    (新建一个模块,然后什么都不用做,然后为这个模块添加一个Tomcat服务器(注意端口号要改一下,要不然重复))

  2. 导入新的坐标依赖:jersey【跨服务器上传需要用到这个jar包】

    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-core</artifactId>
        <version>1.18.1</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-client</artifactId>
        <version>1.18.1</version>
    </dependency>
    
  3. 后端代码:

    @RequestMapping("/fileUpload03")
    public String fileUpload03(MultipartFile upload) throws IOException {
        System.err.println("开始跨服务器上传");
        String path = "http://localhost:9090/uploadFileService_war_exploded/uploads/";   //服务器地址
        //注意要确保文件夹存在,否则500,而且定要是target那个目录里面存在着文件夹
        String filename = upload.getOriginalFilename(); //获取文件名称
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        filename = uuid + "_" + filename;  //使文件名唯一化
    
        //完成文件上传
    
        //1.创建客户端对象
        Client client = Client.create();
        //2.和服务器进行连接
        WebResource resource = client.resource(path + filename);
        //3.上传文件
        resource.put(upload.getBytes());
        return "success";
    }
    

500错误的解决方法

  1. 服务器端没有那个文件夹。在敲代码那里新建了,但是最终部署项目时是在target文件夹里的,然后target文件夹里没有自己新建的uploads文件夹,还需要手动创建

  2. tomcat默认不允许写入,需要修改conf/web.xml

    <!-- 使得服务器允许文件写入。-->
    <init-param>
        <param-name>readonly</param-name>
        <param-value>false</param-value>
    </init-param>
    

    参考:https://blog.csdn.net/shujuku____/article/details/105522286

  3. 这个问题很无语,我不知道是不是见鬼了,还是他脑子抽风了,他说我缺少springmvc.xml,可是明明在啊,结果我打开target文件夹一看,压根就没有,还得我自己手动复制过去!还有一个问题就是我明明在maven里导入坐标了,也刷新了,结果他不帮我把jar包放到/WEB-INF/lib里,然后就500错误说找不到类,还得我自己去复制,真是无语。

SpringMVC的异常处理

在这里插入图片描述

平时服务器出现错误都是直接显示错误信息,我们要实现的功能是一旦发生错误就跳转到指定页面。

  1. 后端java

    @RequestMapping("/testException")
    public String testException() throws Exception{
        System.out.println("testException执行了");
        //模拟异常
        int a = 10 / 0;
        return "success";
    }
    
  2. 编写异常处理器
    需要使用接口HandlerExceptionResolver
    返回值是ModelAndView,按照之前“返回值类型” 那里的方法来做,可以通过addObject()来保存异常信息然后到error页面来显示。

    public class ExceptionResolver implements HandlerExceptionResolver {
    
        /**
         * 处理异常业务逻辑
         * @param httpServletRequest
         * @param httpServletResponse
         * @param o
         * @param e  捕获到的异常对象
         * @return
         */
        @Override
        public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("errMsg",e.getMessage());
            modelAndView.setViewName("error");  //设置要跳转到的页面
            return modelAndView;
        }
    }
    
  3. 错误页面。
    上面配置的是跳转到error.jsp,所以我们要创建一个error.jsp,位置和之前的success.jsp一样(就看springmvc.xml里怎么配置了)

    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h1>发生错误:${errMsg}</h1>
    </body>
    </html>
    
  4. 配置异常解析器。
    上面已经编写好了异常解析器,我们还有一步,需要自己去配置这个解析器
    方法很简单,就跟配置一个bean即可

    <bean id="exceptionResolver" class="com.itheima.Other.ExceptionResolver"></bean>
    

运行结果:

在这里插入图片描述

拦截器

Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。
用户可以自己定义一些拦截器来实现特定的功能。

谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺
序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但
是也有区别,接下来我们就来说说他们的区别:

  1. 过滤器是 servlet 规范中的一部分, 任何 java web 工程都可以使用。

  2. 拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。

  3. 过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。

  4. 拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp, html,css,image 或者 js 是不会进行拦
    截的。
    它也是 AOP 思想的具体应用。

    我们要想自定义拦截器, 要求必须实现: HandlerInterceptor 接口。

自定义拦截器:

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor...放行了");
        return true;//true是放行,false不放行
    }
}

HandlerInterceptor接口里面的方法都是default标识的,不一定要重写

preHandle是预处理方法,也就是在Controller方法执行之前(必须要这一关过了才行)
当return false的时候,代表不放行,如果不放行需要跳转到某一个页面的话,可以使用request的请求转发。

postHandle是后处理方法,执行时间是Controller方法执行之后,跳转到success.jsp之前

afterCompletion:跳转到success.jsp后,该方法执行

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor...放行了");
        return true;//true是放行,false不放行
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

配置拦截器

springmvc.xml

<!--配置拦截器对-->
<mvc:interceptors>
    <mvc:interceptor>
        <!--要拦截的路径-->
        <mvc:mapping path="testInterceptor"/>
        <!--不要拦截的路径-->
        <!--<mvc:exclude-mapping path=""/>-->

        <!--拦截器对象-->
        <bean class="com.itheima.Other.MyInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

(如果要配置多个拦截器,就配置多个mvc:interceptor标签即可!)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值