springmvc学习笔记

springmvc

1 springmvc初识

1.1 第一个基于注解的 SpringMVC程序

所谓 SpringMVC 的注解式开发是指,在代码中通过对类与方法的注解,便可完成处理器在 springmvc 容器的注册。注解式开发是重点

完成功能:用户提交一个请求,服务端处理器在接收到这个请求后,给出一条欢迎信息,在响应页面中显示该信息

1.1.1 新建maven项目导入web骨架支持

1.1.2 pom.xml
servlet依赖
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
springmvc依赖
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>

插件
<build>
    <plugins>
        <!-- 编码和编译和JDK版本 -->
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
            <source>1.8</source>
            <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>
1.1.3 注册中央调度器

在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_4_0.xsd"
         version="4.0">

     <!--
       1、声明和注册springmvc的核心对象DispatcherServlet
       2、需要在tomcat服务器启动后,创建DispatcherServlet对象的实例。
       3、为什么要创建DispatcherServlet对象的实例呢?
       4、因为DispatcherServlet在他的创建过程中, 会同时创建springmvc容器对象,
       读取springmvc的配置文件,把这个配置文件中的对象都创建好, 当用户发起
       请求时就可以直接使用对象了。

        servlet的初始化会执行init()方法。
        DispatcherServlet在init()中{
          //创建容器,读取配置文件
          WebApplicationContext ctx = new ClassPathXmlApplicationContext("springmvc.xml");
          //把容器对象放入到ServletContext中
          getServletContext().setAttribute(key, ctx);
       }

       启动tomcat报错,读取这个文件 /WEB-INF/springmvc-servlet.xml(/WEB-INF/myweb-servlet.xml)
       springmvc创建容器对象时,读取的配置文件默认是/WEB-INF/<servlet-name>-servlet.xml
       -->
    <servlet>
        <servlet-name>myweb</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--自定义springmvc读取的配置文件的位置-->
        <init-param>
            <!--springmvc的配置文件的位置的属性-->
            <param-name>contextConfigLocation</param-name>
            <!--指定自定义文件的位置-->
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        
        <!--
            在tomcat启动后,创建Servlet对象
            load-on-startup:表示tomcat启动后创建对象的顺序。它的值是整数,数值越小,
            tomcat创建对象的时间越早。 大于等于0的整数。
        -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>myweb</servlet-name>
        <!--
            使用框架的时候, url-pattern可以使用两种值
            1. 使用扩展名方式, 语法 *.xxxx , xxxx是自定义的扩展名。 常用的方式 *.do, *.action, *.mvc等等
               不能使用 *.jsp
               http://localhost:8080/myweb/some.do
               http://localhost:8080/myweb/other.do

            2.使用斜杠 "/"
         -->
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>
1.1.3.1 全限定性类名

该中央调度器为一个 Servlet,名称为 DispatcherServlet。中央调度器的全限定性类名在导入的 Jar 文件 spring-webmvc-5.2.5.RELEASE.jar 的第一个包

org.springframework.web.servlet下可找到

1.1.3.2 <load-on-startup/>

<servlet/>中添加<load-on-startup/>的作用是,标记是否在Web服务器(这里是Tomcat)启动时会创建这个 Servlet 实例,即是否在 Web 服务器启动时

调用执行该 Servlet 的 init()方法,而不是在真正访问时才创建。它的值必须是一个整数。

1、当值大于等于 0 时,表示容器在启动时就加载并初始化这个 servlet,数值越小,该 Servlet的优先级就越高,其被创建的也就越早;

2、当值小于 0 或者没有指定时,则表示该 Servlet 在真正被使用时才会去创建。

3、当值相同时,容器会自己选择创建顺序

1.1.3.3 <url-pattern/>

对于<url-pattern/>,可以写为 / ,建议写为*.do 的形式

1.1.4 创建 SpringMVC 配置文件

在工程的类路径即 src/main/resources 目录下创建 SpringMVC 的配置文件 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">

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


    <!--声明 springmvc框架中的视图解析器, 帮助开发人员设置视图文件的路径-->
    <bean  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前缀:视图文件的路径-->
        <property name="prefix" value="/WEB-INF/view/" />
        <!--后缀:视图文件的扩展名-->
        <property name="suffix" value=".jsp" />
    </bean>
</beans>
1.1.5 创建处理器
//@Controller:创建处理器对象,对象放在springmvc容器中。
@Controller
public class MyController {
    /**
     * 准备使用doSome方法处理some.do请求。
     *
     * @RequestMapping: 请求映射,作用是把一个请求地址和一个方法绑定在一起,一个请求指定一个方法处理。
     * 属性: 1. value 是一个String,表示请求的uri地址的(some.do)。
     * value的值必须是唯一的, 不能重复。 在使用时,推荐地址以“/”
     * 位置:1.在方法的上面,常用的。 2.在类的上面
     * <p>
     * 说明: 使用RequestMapping修饰的方法叫做处理器方法或者控制器方法。
     * 使用@RequestMapping修饰的方法可以处理请求的,类似Servlet中的doGet, doPost
     * <p>
     * 返回值:ModelAndView 表示本次请求的处理结果
     * Model: 数据,请求处理完成后,要显示给用户的数据
     * View: 视图, 比如jsp等等。
     */
    @RequestMapping(value = "/hello.do")
    public ModelAndView doSome() {
        System.out.println("处理hello请求中");
        // 调用service处理请求,把处理结果放入到返回值ModelAndView
        ModelAndView mv = new ModelAndView();
        //  addObject()方法用于向其 Model 中添加数据。Model 的底层为一个 HashMap。
        mv.addObject("msg", "使用注解的springMVC应用");
        mv.setViewName("hello");
        // Model 中的数据存储在 request 作用域中,SringMVC 默认采用转发的方式跳转到视图,本次请求结束,模型中的数据被销毁
        return mv;
    }
}
1.1.6 声明组件扫描器
    <!--声明组件扫描器-->
    <context:component-scan base-package="com.zwh.controller"/>
1.1.7 自定义目标页面

这里我们将目标jsp页面都放在web-inf下的view包中,目的是让用户不能直接访问

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h1>msg数据:${msg}</h1>
    </body>
</html>

测试结果:msg数据:使用注解的springMVC应用

1.2 SpringMVC 执行 执行 流程 ( 理解)

流程图:

执行流程简单分析:

  1. 浏览器提交请求到中央调度器
  2. 中央调度器直接将请求转给处理器映射器。
  3. 处理器映射器会根据请求,找到处理该请求的处理器,并将其封装为处理器执行链后返回给中央调度器。
  4. 中央调度器根据处理器执行链中的处理器,找到能够执行该处理器的处理器适配器
  5. 处理器适配器调用执行处理器。
  6. 处理器将处理结果及要跳转的视图封装到一个对象 ModelAndView 中,并将其返回给处理器适配器
  7. 处理器适配器直接将结果返回给中央调度器。
  8. 中央调度器调用视图解析器,将 ModelAndView 中的视图名称封装为视图对象
  9. 视图解析器将封装了的视图对象返回给中央调度器
  10. 中央调度器调用视图对象,让其自己进行渲染,即进行数据填充,形成响应对象。
  11. 中央调度器响应浏览器。

2 SpringMVC注解式开发

2.1 @RequestMapping 定义请求规则

@RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上。

用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

通俗讲就好比商品的增删改:都会有前缀,goods/add goods/delete goods/update

这时候就可以在类上添加@RequestMapping(value = “/goods”)

那么方法上就可以直接@RequestMapping(value = “/add”)@RequestMapping(value = “/update”),但是他们都同时具有了父路径/goods

对请求提交方式的定义:

对于@RequestMapping,其有一个属性 method,就是限制请求是采用post还是get方式

当然,若不指定 method 属性,则无论是 GET 还是 POST 提交方式,均可匹配。即对于请求的提交方式无要求。

2.2 接收前端参数及post乱码问题

1、若表单的name属性值与方法参数一致直接取即可

2、若表单的name属性值与方法参数不一致,则在参数前添加@RequestParam(value = “aname”),进行指定name的属性值即可

post请求乱码问题(web.xml):

    <!--注册声明过滤器,解决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>

2.3 处理器方法的返回值

  • 1、 ModelAndView

若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据,此时处理器方法返回 ModelAndView 比较好

  • 2、String

返回内部资源逻辑视图名,这个字符串与视图解析器中的 prefix、suffix 相结合,即可形成要访问的 URI

  • 3、 object

演示:返回学生对象到浏览器

    • 导入 jackson 依赖
           <!--Jackson应该是目前比较好的json解析工具了-->
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.10.0</version>
            </dependency>
    
    • 引入 jQuery 库
    <script src="js/jquery-3.4.1.js"></script>
    
    • 定义 index 页面
    <html>
    <head>
        <title>$Title$</title>
    </head>
    <script src="js/jquery-3.4.1.js"></script>
    <script type="text/javascript">
        $(function () {
            $("button").click(function () {
                $.ajax({
                    url: "/json1.do",
                    success: function (data) {
                        // JSON.stringify将json数据转换成json字符串
                       document.write(JSON.stringify(data));
                    }
                })
            })
        })
    </script>
    <body>
    <button>提交ajax请求</button>
    </body>
    </html>
    
    • 定义对象 Student
    @Data
    public class Student {
        private String name;
        private Integer age;
    }
    
    • 修改处理器类 MyController
    //在类上直接使用 @RestController ,这样子,里面所有的方法都只会返回 json 字符串了,不用再每一个都添加@ResponseBody
    @RestController
    public class MyController {
        //produces:指定响应体返回类型和编码
        @RequestMapping(value = "/json1.do")
        public String json1() throws JsonProcessingException {
            //创建一个jackson的对象映射器,用来解析数据
            ObjectMapper mapper = new ObjectMapper();
            //创建一个对象
            Student student = new Student("张三", 10);
            //将我们的对象解析成为json格式
            String str = mapper.writeValueAsString(student);
            //由于@ResponseBody注解,这里会将str转成json格式返回;十分方便
            return str;
        }
    }
    
    • springmvc配置文件
    <?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/context
           https://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd
           ">
    
        <!--注册mvc注解驱动以及处理JSON乱码问题配置-->
        <mvc:annotation-driven>
            <mvc:message-converters register-defaults="true">
                <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                    <constructor-arg value="UTF-8"/>
                </bean>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                    <property name="objectMapper">
                        <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                            <property name="failOnEmptyBeans" value="false"/>
                        </bean>
                    </property>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven>
    
        <!--声明组件扫描器-->
        <context:component-scan base-package="com.zwh.controller"/>
    
    
        <!--声明 springmvc框架中的视图解析器, 帮助开发人员设置视图文件的路径-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--前缀:视图文件的路径-->
            <property name="prefix" value="/WEB-INF/view/"/>
            <!--后缀:视图文件的扩展名-->
            <property name="suffix" value=".jsp"/>
        </bean>
    
    </beans>
    
    • 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_4_0.xsd"
             version="4.0">
    
    
        <servlet>
            <servlet-name>myweb</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>myweb</servlet-name>
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>
    
    
        <!--注册声明过滤器,解决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>
    
  • 4、 void

对于处理器方法返回 void 的应用场景,AJAX 响应

jQuery.ajax:

jQuery.ajax(...)
       部分参数:
              url:请求地址
             type:请求方式,GET、POST(1.9.0之后用method)
          headers:请求头
             data:要发送的数据
      contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")
            async:是否异步
          timeout:设置请求超时时间(毫秒)
       beforeSend:发送请求前执行的函数(全局)
         complete:完成之后执行的回调函数(全局)
          success:成功之后执行的回调函数(全局)
            error:失败之后执行的回调函数(全局)
          accepts:通过请求头发送给服务器,告诉服务器当前客户端课接受的数据类型
         dataType:将服务器端返回的数据转换成指定类型
            "xml": 将服务器端返回的内容转换成xml格式
           "text": 将服务器端返回的内容转换成普通文本格式
           "html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。
         "script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式
           "json": 将服务器端返回的内容转换成相应的JavaScript对象
          "jsonp": JSONP 格式使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数

这里就不做演示,和返回对象类型差不多,只是处理器方法返回值为void,不能表示数据,也没有视图。

所以可以通过httpServletResponse的输出对象,把数据输出到浏览器

  • 5、json输出时间对象

  • 默认日期格式会变成一个数字,是1970年1月1日到当前日期的毫秒数!

  • Jackson 默认是会把时间转成timestamps形式

解决方法:封装工具类

public class JsonUtils {
    public static String getJson(Object object) {
        return getJson(object, "yyyy-MM-dd HH:mm:ss");
    }

    public static String getJson(Object object, String dateFormat) {
        ObjectMapper mapper = new ObjectMapper();
        //不使用时间差的方式
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        //自定义日期格式对象
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        //指定日期格式
        mapper.setDateFormat(sdf);
        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

2.4 FastJson

fastjson.jar是阿里开发的一款专门用于Java开发的包,可以方便的实现json对象与JavaBean对象的转换,实现JavaBean对象与json字符串的转换,实现json对象与json字符串的转换。实现json的转换方法很多,最后的实现结果都是一样的。

fastjson 的 pom依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.60</version>
</dependency>

fastjson 三个主要的类:

  • JSONObject 代表 json 对象
  • JSONArray 代表 json 对象数组
  • JSON 代表 JSONObject和JSONArray的转化

代码测试,我们新建一个MyTest类

public class MyTest {
    public static void main(String[] args) {
        //创建一个对象
        Student Student1 = new Student("1号", 3);
        Student Student2 = new Student("2号", 3);
        Student Student3 = new Student("3号", 3);
        Student Student4 = new Student("4号", 3);
        List<Student> list = new ArrayList<Student>();
        list.add(Student1);
        list.add(Student2);
        list.add(Student3);
        list.add(Student4);

        System.out.println("*******Java对象 转 JSON字符串*******");
        String str1 = JSON.toJSONString(list);
        System.out.println("JSON.toJSONString(list)==>" + str1);
        String str2 = JSON.toJSONString(Student1);
        System.out.println("JSON.toJSONString(Student1)==>" + str2);

        System.out.println("\n****** JSON字符串 转 Java对象*******");
        Student jp_Student1 = JSON.parseObject(str2, Student.class);
        System.out.println("JSON.parseObject(str2,Student.class)==>" + jp_Student1);

        System.out.println("\n****** Java对象 转 JSON对象 ******");
        JSONObject jsonObject1 = (JSONObject) JSON.toJSON(Student2);
        System.out.println("(JSONObject) JSON.toJSON(Student2)==>" + jsonObject1.getString("name"));

        System.out.println("\n****** JSON对象 转 Java对象 ******");
        Student to_java_Student = JSON.toJavaObject(jsonObject1, Student.class);
        System.out.println("JSON.toJavaObject(jsonObject1, Student.class)==>" + to_java_Student);
    }
}

2.5 解读<url-pattern/>

1、配置详解

  • *.do

    在没有特殊要求的情况下,SpringMVC 的中央调度器 DispatcherServlet 的常使用后辍匹配方式,如写为*.do 或者 *.action, *.mvc 等

  • /

    可以写为/,因为 DispatcherServlet 会将向静态资源的获取请求,例如.css、.js、.jpg、.png等资源的获取请求,当作是一个普通的 Controller 请求。中央调度器会调用处理器映射器为其查找相应的处理器。当然也是找不到的,所以在这种情况下,所有的静态资源获取请求也均会报 404 错误.

*保持<url-pattern/>的值为 .do,扩展名方式,图片会正常显示,将<url-pattern/>的值修改为 / ,则图片将无法显示。

2、静态资源访问

<url-pattern/>的值并不是说写为/后,静态资源就无法访问了。经过一些配置后,该问题也是可以解决的。

方法一:

在web.xml中配置:

 <!--处理静态资源访问-->
<mvc:default-servlet-handler/>

方法二:

在web.xml中配置:

<mvc:resources mapping="/img/**" location="/img/"/>

location	表示静态资源所在目录。当然,目录不要使用/WEB-INF/及其子目录
mapping		表示对该资源的请求

3 springmvc核心技术

3.1 请求重定向和转发

注意:

对于请求转发的页面,可以是WEB-INF中页面;

而重定向的页面,是不能为WEB-INF中页的。

因为重定向相当于用户再次发出一次请求,而用户是不能直接访问 WEB-INF 中资源的。

1、请求转发

处理器方法返回 ModelAndView 时,需在 setViewName()指定的视图前添加 forward:,

且此时的视图不再与视图解析器一同工作,这样可以在配置了解析器时指定不同位置的视图。

视图页面必须写出相对于项目根的路径。forward 操作不需要视图解析器。

处理器方法返回 String,在视图路径前面加入 forward: 视图完整路径。

   语法:setViewName("forward:视图完整路径")
   特点:不和视图解析器一同工作,就当项目中没有视图解析器
   
   @RequestMapping(value = "/form.do")
    // 当表单的name属性值与参数名不一致使用@RequestParam,若一致,直接取即可
    public ModelAndView form(@RequestParam(value = "aname") String name, Integer age) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("myname", name);
        mv.addObject("myage", age);
        mv.setViewName("forward:/show.jsp");
        return mv;
    }

2、 请求重定向

   语法:setViewName("redirect:视图完整路径")
   特点:不和视图解析器一同工作,就当项目中没有视图解析器
   
   @RequestMapping(value = "/form.do")
    // 当表单的name属性值与参数名不一致使用@RequestParam,若一致,直接取即可
    public ModelAndView form(@RequestParam(value = "aname") String name, Integer age) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("myname", name);
        mv.addObject("myage", age);
        mv.setViewName("forward:/show.jsp");
        return mv;
    }

3.2 拦截器

概述:

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

过滤器:

  • servlet规范中的一部分,任何java web工程都可以使用
  • 在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截

拦截器:

  • 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
  • 拦截器只会拦截访问的控制器方法, 如果访问的是jsp/html/css/image/js是不会进行拦截的
3.2.1 自定义拦截器
  • 自定义拦截器类:
public class MyInterceptor implements HandlerInterceptor {

    //在请求处理的方法之前执行
    //如果返回true执行下一个拦截器
    //如果返回false就不执行下一个拦截器
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("------------处理前------------");
        return true;
    }

    //在请求处理方法执行之后执行
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("------------处理后------------");
    }

    //在dispatcherServlet处理后执行,做清理工作.
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("------------清理------------");
    }
}
  • springmvc的配置文件中配置拦截器:
<?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/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       ">

    <context:component-scan base-package="com.zwh.*"/>

    <!--关于拦截器的配置-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--/** 包括路径及其子路径-->
            <!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
            <!--/admin/** 拦截的是/admin/下的所有-->
            <mvc:mapping path="/**"/>
            <!--bean配置的就是拦截器-->
            <bean class="com.zwh.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>


    <mvc:annotation-driven/>


    <!--声明 springmvc框架中的视图解析器, 帮助开发人员设置视图文件的路径-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前缀:视图文件的路径-->
        <property name="prefix" value="/WEB-INF/view/"/>
        <!--后缀:视图文件的扩展名-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--处理静态资源访问-->
    <mvc:default-servlet-handler/>
    <!--    <mvc:resources mapping="/img/**" location="/img/"/>-->

</beans>
  • 编写一个Controller,接收请求:
 
//测试拦截器的控制器
@Controller
public class InterceptorController {
 
    @RequestMapping("/interceptor.do")
    @ResponseBody
    public String testFunction() {
        System.out.println("控制器中的方法执行了");
        return "hello";
    }
}

  • 前端 index.jsp:
<a href="${pageContext.request.contextPath}/interceptor.do">拦截器测试</a>

测试结果:
        ------------处理前------------
        控制器中的方法执行了
        ------------处理后------------
        ------------清理------------

3.3 文件上传和下载

3.3.1 文件的上传
  • 1、导入文件上传的jar包,commons-fileupload , Maven会自动帮我们导入他的依赖包 commons-io包;
<!--文件上传-->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
</dependency>
<!--servlet-api导入高版本的-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>

  • 2、配置bean:multipartResolver,id必须为"multipartResolver",否则报错
<!--文件上传配置-->
<bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
    <property name="defaultEncoding" value="utf-8"/>
    <!-- 上传文件大小上限,单位为字节(10485760=10M) -->
    <property name="maxUploadSize" value="10485760"/>
    <property name="maxInMemorySize" value="40960"/>
</bean>

CommonsMultipartFile 的 常用方法:
String getOriginalFilename():获取上传文件的原名
InputStream getInputStream():获取文件流
void transferTo(File dest):将上传文件保存到一个目录文件中
  • 3、编写前端页面
<form action="/upload" enctype="multipart/form-data" method="post">
  <input type="file" name="file"/>
  <input type="submit" value="upload">
</form>

  • 4、Controller
@Controller
public class FileController {
	方式一:

    //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
    //批量上传CommonsMultipartFile则为数组即可
    @RequestMapping("/upload")
    public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {
 
        //获取文件名 : file.getOriginalFilename();
        String uploadFileName = file.getOriginalFilename();
 
        //如果文件名为空,直接回到首页!
        if ("".equals(uploadFileName)){
            return "redirect:/index.jsp";
        }
        System.out.println("上传文件名 : "+uploadFileName);
 
        //上传路径保存设置
        String path = request.getServletContext().getRealPath("/upload");
        //如果路径不存在,创建一个
        File realPath = new File(path);
        if (!realPath.exists()){
            realPath.mkdir();
        }
        System.out.println("上传文件保存地址:"+realPath);
 
        InputStream is = file.getInputStream(); //文件输入流
        OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流
 
        //读取写出
        int len=0;
        byte[] buffer = new byte[1024];
        while ((len=is.read(buffer))!=-1){
            os.write(buffer,0,len);
            os.flush();
        }
        os.close();
        is.close();
        return "redirect:/index.jsp";
    }
    
    方式二:
    /*
     * 采用file.Transto 来保存上传的文件
     */
    @RequestMapping("/upload2")
    public String  fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {

        //上传路径保存设置
        String path = request.getServletContext().getRealPath("/upload");
        File realPath = new File(path);
        if (!realPath.exists()){
            realPath.mkdir();
        }
        //上传文件地址
        System.out.println("上传文件保存地址:"+realPath);

        //通过CommonsMultipartFile的方法直接写文件(注意这个时候)
        file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));

        return "redirect:/index.jsp";
    }

}

  • 5、测试上传文件
3.3.2 文件的下载
  • 1、设置response响应头

  • 2、读取文件–inputstream

  • 3、写出文件–outputstream

  • 4、执行操作

  • 5、关闭流(先开后关)

@RequestMapping(value="/download")
public String downloads(HttpServletResponse response ,HttpServletRequest request) throws Exception{
    //要下载的图片地址
    String  path = request.getServletContext().getRealPath("/upload");
    String  fileName = "基础语法.jpg";
 
    //1、设置response 响应头
    response.reset(); //设置页面不缓存,清空buffer
    response.setCharacterEncoding("UTF-8"); //字符编码
    response.setContentType("multipart/form-data"); //二进制传输数据
    //设置响应头
    response.setHeader("Content-Disposition",
            "attachment;fileName="+URLEncoder.encode(fileName, "UTF-8"));
 
    File file = new File(path,fileName);
    //2、 读取文件--输入流
    InputStream input=new FileInputStream(file);
    //3、 写出文件--输出流
    OutputStream out = response.getOutputStream();
 
    byte[] buff =new byte[1024];
    int index=0;
    //4、执行 写出操作
    while((index= input.read(buff))!= -1){
        out.write(buff, 0, index);
        out.flush();
    }
    out.close();
    input.close();
    return null;
}


  • 前端:
<a href="/download">点击下载</a>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值