Java:68-SpringMVC进阶

SpringMVC进阶

ajax异步交互:
当我们操作json数据时
Springmvc默认用MappingJackson2HttpMessageConverter对json数据进行转换,但对应操作并没有,只是提供了平台
所以要进行json的操作,需要加入jackson的包,同时使用 <mvc:annotation-driven />,进行激活使用
  	<!--对应操作json需要的包-->
		<dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
             <version>2.9.8</version>
      <!--这个必须要,后面的可以不写,但最好写上,防止其他情况-->
        </dependency>
        <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-core</artifactId>
             <version>2.9.8</version>
        </dependency>
        <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-annotations</artifactId>
             <version>2.9.0</version>           
		</dependency>
这样我们就可以实现进行json操作了
@RequestBody:
该注解用于Controller的方法的形参声明,当使用ajax提交并指定contentType为json形式时
通过HttpMessageConverter接口转换为对应的POJO对象
<%--
  Created by IntelliJ IDEA.
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<script src="${pageContext.request.contextPath}/js/jquery-3.4.1.min.js"></script>
    <%--
    注意:不要自关闭,这是html的约束,因为script在html里中是设置了不能写成自关闭的约束
    否则后面的内容基本都不会显示,即不会读取了(因为全部当成了script的内容,src失效,即可以当作)
    也要注意:当src属性和script标签内容一起时,内容忽略,即相当于没有写
    --%>
<button id="btn">ajax提交</button>
<script>
    $("#btn").click(function(){


    let url = '${pageContext.request.contextPath}/user/ajax';
    let data = '[{"id":1,"username":"张三"},{"id":2,"username":"李四"}]'

    $.ajax({
        type:'POST',//大小写可以忽略
        url:url,
        data:data,
        contentType:'application/json;charset=utf-8',
        //设置发送的数据类型,这样data必须是字符串,因为不是字符串的话,一般会认为是键值对,而不是json
        //那么后台可能就会解析出错(单纯String应该不会),使得报错,当然了
        //发送默认的数据类型的话,那么就不能够是字符串了,而必须是键值对
        //这主要是对应的发送数据类型使得后台的不同解析
        success:function (data) {
            console.log(data);
        }
    })
    })
</script>
</body>
</html>

 /*
    ajax异步交互
     */
    @RequestMapping("ajax")
    //一般的,我们需要使用对应名称来进行对list的复制,但实际上是使用对应类来操作的
    //而直接的list复制,我们并没有对应操作,但是却可以用来封装json数据,但这需要解析json
    //就需要对应json包,且进行自定义配置,当有这些条件时,在调用方法前,先使用json方式依次取出数据
    //使用User的set方法进行设置(判断对应的set后面名称与key是否一致,大小写忽略),没有set则直接赋值
    //在没有特殊说明必须要set时,一般都是可以直接赋值的,每一个json都进行一次这样的操作
    //然后依次放入新创建的list,这个新创建的list就当作参数使用,所以结果会出现两个User
    //即[User{id='1', username='张三'}, User{id='2', username='李四'}]
    public void ajax(@RequestBody List<User> list){ //User可以自行编写
        System.out.println(list);
    }

@ResponseBody (通常这个注解不能使用两次,否则一般会报错,具体看情况,可以测试一下,可能这是规定,以后或者其他spring版本并不确定,所以是通常,而不是一定):
该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据
如:json,xml等,通过Response响应给客户端
部分jsp的修改:
success:function (data) {
            console.log(data);
            alert(JSON.stringify(data));
        }
部分java的修改:
  @ResponseBody
    public List<User> ajax(@RequestBody List<User> list) throws IOException {  //在参数里面的,那么基本只能操作post操作body了,若没有操作类似的body,那么通常会报错,类似于如get请求
        System.out.println(list);
        return list;
        //注意:若在springmvc中的调用方法里(这里是ajax方法)
        //让输出流中getWriter()方法被调用,那么会产生一个全局的编码格式(springmvc的操作)
        //一般这个编码不会识别中文
        //也就是说,你转发的jsp就算设置了对应中文编码(因为是请求的编码,不能操作到响应编码),且操作后
        //再次进行操作,即编码和解码,所以最后的结果还是使用这个全局编码进行输出结果
        //因为转发传递请求对象和响应对象
        //而响应对象基本不能改变(在前端来说,所以说还是使用这个全局,或者对于前端来说的全局)
        //当然,若提前设置编码,那么就可以
        //如HttpServletResponse的setContentType("text/html;charset=utf-8")方法来进行设置,虽然基本操作不到了
        //而由于@ResponseBody注解的存在,为了防止这样的操作,当你调用getWriter()方法时
        //那么即报错,出现500状态码,程序这里并没有对应的异常出现(没有设置异常)
        //前端也有报错,没有进行输出

    }
//注意:使用了@ResponseBody注解,那么就是相当于使用HttpServletResponse类型进行数据输出(所以不输出也可以)
//那么基本上就看toString()方法了(实际上是看属性名称,是什么名称,那么结果就是什么,且分先后)
//若是对应集合(其实是所有对象),则变成json输出,中文可以识别,若是字符串(或者字符串数组)
//则就是字符串(或者字符串数组)输出,中文基本不识别,基本是这样
//即只会输出对应值了,而不是转发(不经过视图解析器)
//但是字符串的输出,这样的一般来说识别不了中文,若要使得响应的字符串数据变成可以识别中文,那么可以使用如下
//@RequestMapping(value = "ajax",produces = "application/json; charset=utf-8")
//设置了这个数据接收和输出的编码,一般输出是没有问题的(utf8),因为最后jsp都有设置,getWriter()一般不是一体的
RESTful:
什么是RESTful :
Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件
主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等
Restful风格的请求是使用"url+请求方式"表示一次请求目的的
HTTP 协议里面四个表示操作方式的动词如下:
GET:读取(Read)
POST:新建(Create)
PUT:更新(Update)
DELETE:删除(Delete)
注意:他们的作用实际上是一样的,除了post不是操作在url里面,我们可以看成是语义化
什么是语义化:指的是,同一个事务,用不同的单词来操作,只是该单词的意思可以让开发者知道,只是用来干什么的
也就是说,当我们操作DELETE时,虽然与get请求一样,但是我们一看就知道,这个请求是操作删除
下图基本是mvc需要处理的风格,具体看后面代码的处理(其他语言或者框架的实现可能有所不同)

在这里插入图片描述

代码实现:
@PathVariable
用来接收RESTful风格请求地址中占位符的值
@RestController
RESTful风格多用于前后端分离项目开发,前端通过ajax与服务器进行异步交互
我们处理器通常返回的是json数据,所以使用@RestController来替代@Controller和@ResponseBody两个注解
package com.lagou.controller;

import org.springframework.web.bind.annotation.*;

/**
 *
 */
@RestController //相当与在类上加上@Controller,在所有方法上加上@ResponseBody
@RequestMapping("/restful")
//这里说明一下,当注解中有value属性时,那么直接的单独内容就是默认这个属性的值,这是注解的默认操作方式
public class RestfulController {
    /*
根据id进行查询
localhost:8080/项目名/restful/user/2/1 + get请求方式
     */

    //{id}是占位符,就是说,这个地方可以随便匹配路径中的任意字符串
    //当路径来时,发现是{id},那么找参数是否有被@PathVariable注解修饰的id(名称必须一致,否则报错)
    //有则将占位符对应的值直接赋值给这个id,否则报错
    //但是若没有@PathVariable则不会进行操作,那么就不会出现报错了
    //也可以多写,如{id}/{q},那么就要依次匹配,若是一起的,如{id}{q},那么只会匹配第一个,也就是{id}
    //@RequestMapping(value = "/user/{id}/{q}",method = RequestMethod.GET)
    @GetMapping("/user/{id}/{q}") //单个参数,省略了value
    //相当于上面的操作,即默认加上了get请求方式
    public String restful(@PathVariable Integer id,@PathVariable Integer q) {

        System.out.println(q); //1

        return "findById:"+id; //findById:2

        //这样的操作,使得参数在路径上获取,而不是在url后面的参数上获取
    }
     /*
    新增方法
     */
    @PostMapping("/user")
    //注意:@RequestMapping里面的路径值最好写,否则是找不到的,给你个错误页面
    //相当于@RequestMapping(value = "/user",method = RequestMethod.POST)
    public String post(){
        return "post";
    }

    /*
    更新方法
     */
    @PutMapping("/user") //对应的RequestMethod.PUT
    public String put(){
        return "put";
    }

    /*
    删除方法
     */
    @DeleteMapping("/user") //对应的RequestMethod.DELETE
    public String delete(){
        return "delete";
    }
    
}
文件上传:
文件上传三要素
表单项 type=“file”
表单的提交方式 method=“POST”,get后面的不可以操作文件
表单的enctype属性是多部分表单形式 enctype=“multipart/form-data"
使得多种类型一起操作,如可以加上二进制(如图片的上传,只是编码一定会显示,使得他通过对应特殊流来获取数据)
因为需要字节流,而多多部分表单形式就是字节的读取
普通的,即默认的是字符读取,所以使用文件时,一般使用多部分表单形式
若你强行不用,而使用默认的,那么浏览器并不会将对应文件的数据给出
而是直接给出名称,是为了数据的完整性,这是浏览器的设置

在这里插入图片描述

文件上传原理 :
当form表单修改为多部分表单时,request.getParameter()将失效
主要是通过字符流获得的,在字符流中的对应操作中,可以看成一个字符流操作的对象中
多部分表单中,不可以用request.getParameter(),就算使用时也是获取不到的
主要是通过字节流获得的,在字节流中的对应操作中,可以看成一个字节流操作的对象中
当form表单的enctype取值为 application/x-www-form-urlencoded 时,这是默认的,
则form表单的正文内容格式是: name=value&name=value(这就相当于字符流的的操作)
当form表单的enctype取值为 mutilpart/form-data 时(这就相当于字节流的的操作)
请求正文内容就变成多部分形式:

在这里插入图片描述

单文件上传 :
步骤分析:
/*
1. 导入fileupload和io坐标
2. 配置文件上传解析器
3. 编写文件上传代码
*/
导入fileupload和io坐标:
<!--  
文件上传 没有指定的那么就需要一起,即这里一般必须一起
因为他们需要结合,实际上只需要第一个即可,即commons-fileupload,但通常都是结合的
 -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <!--初始化操作-->
    <version>1.3.3</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <!--io对应操作-->
    <version>2.6</version>
</dependency>
<!--
上面两个虽然我们并没有操作,但上传解析器需要上面这其中的commons-fileupload,否则报错
在需要上面两个时我们一般要导入,这里就需要导入(第二个一般也要导入,当然若不是必须,可以不导入)
-->
配置文件上传解析器 :
   <!--配置文件上传解析器-->
    <bean id="multipartResolver" 
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设定文件上传的最大值为5MB,5*1024*1024 -->
           <!--这里一般不配置,默认没有上限,那这时就看对方服务器的空间了,若他没有这么多,自然可能会使得连接断开,或者终止传输(通常服务器在只有固定的空间后,就会使得终止,这是对于连接来说的),在满之前,通常只能手动补充满,但实际上连接也会(可能不会)-->
         <property name="maxUploadSize" value="5242880"></property>
         <!--
         设定文件上传时写入内存的最大值,因为有临时文件存放,而不是读取就写入
          如果小于maxInMemorySize这个参数值,则不会生成临时文件,而是保留在内存里
		否则就会在硬盘上创建临时文件,下面的配置大小不设置的话,默认为1024
         当全部读取完后,才会进行写入操作,这是为了数据完整性,防止中途中断,而读取中断,则会全部删除
         -->
         <property name="maxInMemorySize" value="40960"></property>

    </bean>
jsp页面:
<%--
  Created by IntelliJ IDEA.
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--
满足文件上传三要素的表单:
表单的提交方式要是post
表单的enctype要是multipart/form-data
表单的编码要是multipart/form-data

--%>

<form action="${pageContext.request.contextPath}/fileUpload" method="post"
      enctype="multipart/form-data">
    名称:<input type="text" name="username"> <br>
    文件:<input type="file" name="filePic"> <br>
    <input type="submit" value="单文件上传">
</form>

</body>
</html>

编写文件上传代码:
package com.lagou.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

@Controller
public class FileUploadController {


    /*
        单文件上传
     */
    @RequestMapping("/fileUpload")
    //MultipartFile设置了对应读取文件的数据,当通过名称检查时,普通的直接进行获取赋值
    //而MultipartFile进行读取放入一个类型里,进行地址指向得到(不是先获得空的,在进行读取)
    //与类的中变量是引用操作不一样(字符串和数组不会)
    public String fileUpload(String username, MultipartFile filePic) throws IOException {
//使用MultipartFile需要对应的文件解析器进行注入(自动的),即基本要配置文件解析器,否则报错

        //获取表单的提交参数,完成文件上传
        System.out.println(username);
        // 获取原始的文件上传名 a.txt
        String originalFilename = filePic.getOriginalFilename();
        filePic.transferTo(new File("D:/upload/"+originalFilename));
        //相当于里面定义一个输出流,进行字节输出,输出MultipartFile里面对应文件信息对应参数文件
        //其中MultipartFile里面对应文件信息会受到配置文件的影响
        //从而决定是否超过使得报错,或者读取放在一个临时文件,然后进行输入输出操作
        //又或者就在内存被读取输入
        //但不管如何,都是一种信息存放的方式,且都由字节流操作
        //字节流实际上所有的操作都可以,而有些说明字节不可以操作中文,实际上是编码的问题
        //因为字符流也是从字节开始的,所以我们也说单纯的字节操作不了中文,因为没有设置编码(对应编码)
        //举个例子:就如一个字"好",编码时,变成0000 1111(可能有多个)
        //解码回去,变成好,如果解码的字符编码不同
        //那么0000 1111(可能有多个)对应的对照表不同,可能出现"有",而不是"好",或者其他乱码
        //实际上字节操作不了中文的一个原因,一般就是上面的多个
        //这个多个由各个字符编码进行,如有些一次读取两个字节
        //而不是读取单个字节,这也是单个字节解释不了中文的原因
        //在IO流中也是如此,虽然你使用字节流,但最后还是会将这个字节变成对应字符,但是他是通过单字节变成的
        //也就是说会出现乱码(让一个两个字节编码的去识别一个字节)
        //有些读取两个,那么使用相似的进行变成字符,文件变大的原因,或者读取某个停止,如-1,变小的原因
        return "success";
    }
}
多文件上传 :
jsp代码:
<%--实现多文件上传--%>
<form action="${pageContext.request.contextPath}/filesUpload" method="post"
      enctype="multipart/form-data">
   名称:<input type="text" name="username"> <br>
   文件1:<input type="file" name="filePic"> <br>
   文件2:<input type="file" name="filePic"> <br>
   <input type="submit" value="多文件上传">
</form>
java代码:
 /*
      多文件上传
   */
    @RequestMapping("/filesUpload")
    public String filesUpload(String username, MultipartFile[] filePic) throws IOException {

        //注意:数组的得值,单纯的变量也可,但由于名称不能一样,则需要注解@RequestParam
        //当多个时,单纯的变量取第一个,数组则是根据个数确定长度
        //获取表单的提交参数,完成文件上传
        System.out.println(username);

        // 获取原始的文件上传名 a.txt  abc
        for (MultipartFile multipartFile : filePic) {
            String originalFilename = multipartFile.getOriginalFilename();
            multipartFile.transferTo(new File("D:/upload/"+originalFilename));
//transferTo在31章新特性中也有说明,实际上该文件的操作,可以认为是内置的操作,具体在56章博客也有说明,即   DiskFileItemFactory factory = new DiskFileItemFactory();,而他是import org.apache.commons.fileupload.disk.DiskFileItemFactory;的

        }

        return "success";
    }
上面的操作springmvc帮我们封装好了对应读取文件的操作了,所以我们只要创建对应输出流来操作即可
异常处理:
异常处理的思路
在Java中,对于异常的处理一般有两种方式:
一种是当前方法捕获处理(try-catch),这种处理方式会造成业务代码和异常处理代码的耦合
另一种是自己不处理,而是抛给调用者处理(throws),调用者再抛给它的调用者,也就是一直向上抛
在这种方法的基础上,衍生出了SpringMVC的异常处理机制
系统的dao、service、controller出现都通过throws Exception向上抛出
最后由springmvc前端控制器交由异常处理器进行异常处理
如下图:

在这里插入图片描述

请求还是不会经过这个异常处理器,后面会有对应的操作,来实现请求的时候,指向异常页面
自定义异常处理器:
步骤分析:
/*
1. 创建异常处理器类实现HandlerExceptionResolver
2. 配置异常处理器
3. 编写异常页面
4. 测试异常跳转
*/
创建异常处理器类实现HandlerExceptionResolver:
package com.lagou.exception;

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

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

//@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {


    /*
        Exception e:实际抛出的异常对象
     */

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse 
                                         httpServletResponse, Object handler, Exception e) {
        //具体的异常处理 产生异常后,跳转到一个最终的异常页面
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("error",e.getMessage());
        modelAndView.setViewName("error");

        return modelAndView;
    }
}

配置异常处理器 :
<!--
配置自定义的异常处理器,前端控制器会查找IOC容器中实现了HandlerExceptionResolver接口的实例(即可以使用注解)
若找到了,则出现异常时,调用他对应的方法,否则使用默认的实现类的对应方法
出现异常未必需要打印对应信息(不要认为必须打印,实际上打印的也是框架或者java自己设置的信息)
-->
    <bean id="globalExceptionResolver" class="com.lagou.exception.GlobalExceptionResolver"></bean>

<!--当有多个时,根据顺序来操作主要的,操作后,其他不会操作了-->

编写异常页面 :
<%--
  Created by IntelliJ IDEA.
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
这是异常页面
${error}
</body>
</html>

测试异常跳转:
package com.lagou.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ExceptionController {


    @RequestMapping("/testException")
    public String testException(){

        int i = 1/0;

        return "success";
    }
}
web的处理异常机制:
 <!--
    由于我们设置的异常对请求来说并没有操作
    即他们的异常是由后面的Controller,Service,Dao来进行创建对应异常对象
    而请求到前端控制器中,并没有对应的异常对象,那么我们需要一个对应的异常处理
    使得扫描时,前端控制价创建对应的异常,当创建时,根据内容路径进行转发
    如下配置:
    -->
    <!--处理404异常-->
<error-page>
    <error-code>404</error-code>
    <!--当请求时,出现404错误,那么就到404.jsp当作错误页面,而不是默认的-->
    <location>/404.jsp</location> 
    <!--这个/有约束限制,不能省略,虽然有些没有,但运行时,也都基本报错-->
    <!--
    一般的,若是 <exception-type>java.lang.Throwable</exception-type>
    则需要特殊操作,使得页面是对应错误页面
    即如果要使用它,必须将对应页面page指令的isErrorPage属性设置成true,才会当作错误页面
    即可以设置<%@ page isErrorPage="true" %> 得到对应异常信息对象
    -->
</error-page>
    <!--处理500异常-->
    <error-page>
        <error-code>500</error-code>
        <!--当请求时,出现500错误,那么就到500.jsp当作错误页面,而不是默认的-->
        <location>/500.jsp</location>

    </error-page>
拦截器:
拦截器(interceptor)的作用
Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理
将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(InterceptorChain)
在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用
拦截器也是AOP思想的具体实现
拦截器和过滤器区别:
关于interceptor和filter的区别,如图所示:

在这里插入图片描述

主要的是过滤器是监听请求信息和响应信息,而进行后续操作(请求和响应进行过滤后,才到服务器和浏览器)
而拦截器是操作方法的增强,从而实现过滤,所以只能操作控制器方法,所以可以看到,响应数据一般不会被进行拦截
使得一次请求全部执行
快速入门:
步骤分析:
/*
1. 创建拦截器类实现HandlerInterceptor接口
2. 配置拦截器
3. 测试拦截器的拦截效果
*/
创建拦截器类实现HandlerInterceptor接口:
package com.lagou.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

public class MyInterceptor1 implements HandlerInterceptor {


    /*
        preHandle: 在目标方法执行之前 进行拦截   return false:不放行 后面的方法增强就不操作了
        //即postHandle和afterCompletion不执行了
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object 
                             handler) throws Exception {
        System.out.println("preHandle1....");

        return true;
    }


    /*
        postHandle: 在目标方法执行之后,视图对象返回之前(相当于就是return前面)
        执行的方法 文件操作后,编译
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 
                           ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle1....");
    }

    /*
        afterCompletion:在流程都执行完成后,执行的方法
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object 
                                handler, Exception ex) throws Exception {

        System.out.println("afterCompletion1....");


    }
}
//相当于preHandle =》 方法 =》 postHandle =》 后面就是return(没有则postHandle直接是最后一个,具体还是需要看测试,一般还是存在后面的)
// =》 jsp的servlet的对应输出语句执行完 =》 afterCompletion =》 然后响应到浏览器 =》 页面渲染
//过滤器:请求 =》 过滤监听到(执行对应方法上面的代码) =》 服务器
// =》 响应 =》 过滤器监听到(执行对应方法后面的代码,实际上对应方法执行完了) =》 浏览器

配置拦截器 :
<!--配置拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/> 
        <!--项目路径下的对应路径,一个*代表一个路径下,但不代表路径下的路径下,两个基本就是所有-->
        <!--对所有的controller类里面的所有方法都进行拦截(因为是/**)-->
        <bean class="com.lagou.interceptor.MyInterceptor1"></bean>
    </mvc:interceptor>
</mvc:interceptors>
测试拦截器的拦截效果
编写Controller,发请求到controller,跳转页面
package com.lagou.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class TargetController {

    @RequestMapping("/target")
    public String targetMethod(){
        System.out.println("目标方法执行了....");
        return "success";
    }
}
修改对应jsp页面:
<%--
  Created by IntelliJ IDEA.
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h3>嘿嘿嘿</h3>
${name}
<%
    System.out.println(1);
%>
</body>
</html>

拦截器链 :
开发中拦截器可以单独使用,也可以同时使用多个拦截器形成一条拦截器链
开发步骤和单个拦截器是一样的,只不过注册的时候注册多个,注意这里注册的顺序就代表拦截器执行的顺序
同上,再编写一个MyHandlerInterceptor2操作,测试执行顺序:
<!--配置拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <!--对所有的controller类里面的所有方法都进行拦截-->
        <bean class="com.lagou.interceptor.MyInterceptor1"></bean>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <!--对所有的controller类里面的所有方法都进行拦截-->
        <bean class="com.lagou.interceptor.MyInterceptor2"></bean>
        <!--后面一点,则这个后进行增强(对于第一个方法来说)-->
    </mvc:interceptor>
</mvc:interceptors>

<!--一般来说,/**的/代表从端口开始,这里了解即可,所以初始访问也会进行拦截处理(但是也要知道,一个端口基本只有一个服务器占用,所以并不会影响其他服务器的,所以不需要考虑其他服务器的影响问题(除非是业务逻辑上的影响,比如文件的操作))-->

对应java代码:
package com.lagou.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

public class MyInterceptor2 implements HandlerInterceptor {


    /*
        preHandle: 在目标方法执行之前 进行拦截   return false:不放行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object 
                             handler) throws Exception {
        System.out.println("preHandle2....");

        return true;
    }


    /*
        postHandle: 在目标方法执行之后,视图对象返回之前,执行的方法
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 
                           ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle2....");
    }

    /*
        afterCompletion:在流程都执行完成后,执行的方法
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object 
                                handler, Exception ex) throws Exception {

        System.out.println("afterCompletion2....");


    }
}

执行结果:
/*
preHandle1....
preHandle2....
目标方法执行了....
postHandle2....
postHandle1....
1
afterCompletion2....
afterCompletion1....

发现后面两个方法中,后配置的在前面,主要是先配置的需要先靠近最后,所以使得他们放在后面了
而第一个方法,则需要靠近前面,即先配置的先靠前
导致上面的结果

也要注意:不放行的结果,是对于方法不执行(会认为跳过,但还是执行完的),那么若上面的第二个拦截器不放行,那么结果是
preHandle1....
preHandle2.... 
中间方法不执行,那么对于方法增强,就不会打印
afterCompletion1.... 
由于第二个不放行,那么对应的方法不执行,所以这里只有第一个方法的对应执行
*/
知识小结:
拦截器中的方法说明如下:

在这里插入图片描述

一般来说get请求,对请求参数格式并无关系,所以无论是json形式的字符串还是直接的字符串基本都可以操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值