SpringMVC之RestFul(总体第三篇)

一、REST

1、什么是REST

(1)概念

  • 即 Representational State Transfer。(资源)表现层状态转化。是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
    • 资源: 网络上的一个实体,或者说是网络上的一个具体信息。
      它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个 URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。获取这个资源,访问它的 URI 就可以,因此 URI 即为每一个资源的独一无二的识别符
    • 表现出(Representation):吧资源具体呈现出来的形式,叫做它的表现层。比如,文本可以用text格式表现,也可以用html格式,可以xml,JSON,等格式。
    • 状态转化(state Transfer):每发出一个请求,就代表客户端和服务器的异常交换过程,http协议,是一个无状态的协议,即所有的状态都保存在服务器,因此,如果客户端向要操作服务器,必须通过某种手段,让服务器端发生状态转化,而这种转是建立在表现层之上的,所以称为表现层状态层转化。
    • 具体说,就是HTTP协议里面,四个表示操作方式的动词,get,post,put,delete。他们分别是对应的四种基本操作,get用来或者资源,post新建资源,put用来跟心资源,delete用来删除资源

(2)URL风格

  • /order/1 HTTP GET :得到 id = 1 的 order
  • /order/1 HTTP DELETE:删除 id = 1 的 order
  • /order HTTP PUT:更新 order
  • /order HTTP POST:新增 order

2、RestFul实现

(1)具体概念

在这里插入图片描述

  • 原始的
    在这里插入图片描述
  • restful风格
    在这里插入图片描述

(2)RestFul操作用户资源

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

(3)HiddenHTTPMethodFilter过滤器处理put和delete

  • 首先不配置的情况下,我们采用put方式提交是报错:405错误,但是我们启动了后端项目是不会报错的,原因在于我们的SpringMVC会自动处理,默认按着get方式请求。
    在这里插入图片描述
  • 浏览器 form 表单只支持 GET 与 POST 请求,而 DELETE、PUT 等 method 并不支持,Spring3.0 添加了一个过滤器,可以将这些请求转换为标准的 http 方法,使得支持 GET、POST、PUT

在这里插入图片描述

  • 配置PUT方式步骤【同样要采用post方式提交】
    在这里插入图片描述
    在这里插入图片描述

  • 配置delete步骤【但是它不能是post,这个后续补充】

(4)两过滤器

在这里插入图片描述
如果按着这样的顺序,你启动项目访问是会报编码错误的,所以你这里不能能这样写的。在我们编码之前不可以有任何的配置访问。

  • 所以要把两个过滤器的位置调换一下。
    在这里插入图片描述

3、RestFul代码实现

  • 这个后续补充

二、HttpMessageConverter

  • HttpMessageConverter报文信息转换器,将请求报文转换为Java对象,或将Java对象转换为报文。
  • HttpMessageConverter提供了两个注解和两个类型:@RequestBody,@ResponseBody,RequestEntity,ResponseEntity

1、@RequestBody

  • @RequestBody可以获取请求体,需要再控制器方法设置一个型参,使用@RequestBody进行识别,当前请求的请求头就会为当前注解所表示的型参赋值。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

2、RequestEntity

  • RequestEntity封装请求报文的一种类型,需要控制器方法的形参设置该类型的形参,当前请求的请求报文就会赋值给该形参,可以通过getHeaders()获取请求头信息,通过getBody()获取请求信息。
    在这里插入图片描述
    差不多也回到了我们的request里面了。
    在这里插入图片描述

3、@ResponseBody

  • @ResponseBody是:用来给浏览器响应数据的,【和Response是一样的概念】
    在这里插入图片描述
  • 当加上ResponseBody注解后,就不会返回的时候跳转到success路径了,而是返回的响应体了。【返回的是给页面的数据了,而不是返回的时候一个路径了】

4、@ResponseBody响应JSON

  • 响应一个对象试一试【你浏览器根本就不知User是什么语言写的,这样肯定是不行的】
    在这里插入图片描述
    在这里插入图片描述
  • 所以要封装为一个JSON格式【JSON是一种数据交换格式,在AJAX里面什么的都是可以使用的】,所以要引入依赖
    在这里插入图片描述
    此时再去点击就会直接返回给你浏览器JSON一个格式了。内容执行了四个步骤
    在这里插入图片描述
  • 回顾一下JSON
    JSON是JavaScript里面一种数据格式,是我们数据交互格式,它应用很广泛,原因在于它使用{}和方括号[]扩起来的,数据量比较少,之前也有使用xml,但是它是我们自定义的数据格式,应用比较少,数据量是比较多的。
<person>
	<username> xxx</username>
	.
	.
	.
	.
	.
</person>
{ "username": xxx,"password":xxxx}
方括号[]放对象,{}方对象

5、SpringMVC处理AJAX

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

6、@RestController

@RestController注解是SpringMVC提供的复合注解,表示在控制器的类上,就相当于为类添加了@Controller注解,并且为其中的每个方法添加了@ResponseBody注解

7、ResponseEntity

ResponseEntity是用于控制器方法的返回值类型,该控制器返回值就是响应到浏览器的响应报文上。【就是些在方法上,自定义的响应报文】

(1)ResponseEntity实现文件下载

@Controller
public class JPGController {

    @RequestMapping("/testDown")
    public ResponseEntity<byte[]> testJPG(HttpSession session) throws IOException {
        //获取ServletContext对象
        ServletContext servletContext = session.getServletContext();
        //获取服务器中文件的真实路径【部署路径】
        String path = servletContext.getRealPath("/static/1.jpg");
        //创建输入流
        InputStream is = new FilterInputStream(path);
        //创建字节数组【is.available()获取所有的输入字节流】
        byte[] bytes = new byte[is.available()];
        //将流读到字节数组中
        is.read(bytes);
        //创建httpHeaders对象设置响应头
        MultiValueMap<String,String> headers = new HttpHeaders();
        //设置要下载方式和下载文件的名字
        headers.add("content-Disposition","attachment;filename=1.jpg");
        //设置响应状态码
        HttpStatus status = HttpStatus.OK;
        //创建ResponseEntity对象
        ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes,headers,status);
        is.close();
        return responseEntity;
    }
}

  • ResponseEntity自定义响应报文格式。

(2)SpringMVC配置文件上传解析器

首先上传的要求,不可以是get请求,一定是post,而且要修改如下的一个属性
在这里插入图片描述
在这里插入图片描述
正式的来练习

  • 添加依赖
		<dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
  • MultipartFile就是文件上传的信息,操作也是封装在里面的,但是我们上传的文件不能直接转换为multipartFile对象,所以要去添加文件上传解析器【配置在我们的配置文件里面】

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

  • 文件服务器地址配置
 @RequestMapping("/up")

    public String testUP(MultipartFile multipartFile,HttpSession session) throws IOException {
        //MultipartFile就是文件上传的信息,操作也是封装在里面的,但是我们上传的文件不能直接转换为multipartFile对象,所以要去添加文件上传解析器
        String fileName = multipartFile.getOriginalFilename();//获取文件名字

        ServletContext servletContext = session.getServletContext();
        String photoPath = servletContext.getRealPath("photo");
        //动态的创建目录
        File file = new File(photoPath);
        if (!file.exists()) { //判断路径是否存再
           //若不存则创建
           file.mkdir();
        }
        //最终上传的路径
        String finalPaht = photoPath + File.separator + fileName;
        //指定上传到哪个位置
        multipartFile.transferTo(new File(finalPaht));

        //返回值
        return "success";
    }

(3)文件上传的特殊情况

上面的文件上传中,如果用户1上传了1.jpg,然后接着第二个用户上传1.jpg后,之前的就会被覆盖调,这种情况很严重。【不是文件覆盖,而是文件中的内容覆盖】

  • 此时就可以用UUID来进行文件名的配置了
    在这里插入图片描述
    @RequestMapping("/up")

    public String testUP(MultipartFile multipartFile,HttpSession session) throws IOException {
        //MultipartFile就是文件上传的信息,操作也是封装在里面的,但是我们上传的文件不能直接转换为multipartFile对象,所以要去添加文件上传解析器
        String fileName = multipartFile.getOriginalFilename();//获取文件名字

        //获取上传文件的文件名,通过servlet获取服务器中photoPath目录的路径
            //获取后缀名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));//suffixName = .xxxx
            //通过UUID设置文件名
        String uuid = UUID.randomUUID().toString();
            //将uuid进行拼接作为最后的文件名
        fileName = uuid + suffixName;
        ServletContext servletContext = session.getServletContext();
        String photoPath = servletContext.getRealPath("photo");
        //动态的创建目录
        File file = new File(photoPath);
        if (!file.exists()) { //判断路径是否存再
           //若不存则创建
           file.mkdir();
        }
        //最终上传的路径
        String finalPaht = photoPath + File.separator + fileName;
        //指定上传到哪个位置
        multipartFile.transferTo(new File(finalPaht));

        //返回值
        return "success";
    }
}

三、拦截器

1、介绍

  • SpringMVC中的拦截器用于拦截控制器方法的执行【它和过滤器的区别是:过滤器那个/*拦截浏览器和服务器的的所有的请求过滤的,而拦截器是作用于控制器】
    在这里插入图片描述
    拦截器拦截时候有三个方法调用控制器方法执行之前,另外一个拦截执行之后,另外一个在渲染视图完成之后。

2、创建拦截器

  • implements HandlerInterceptor
  • extends HandlerInterceptorAdapter

本次选择上一个
在这里插入图片描述

  • 快捷键Ctrl + O即可查看可以继承的方法
    在这里插入图片描述
    在这里插入图片描述

3、配置拦截器

(1)bean方式

在这里插入图片描述
不管你现在是访问哪个链路都是不可行的。【preHandler就是我们的拦截的方法,返回true是拦截,返回false为放行】

  • 此时采用bean的方式配置拦截,它会拦截所有的请求

(2)ref方式

在这里插入图片描述
也是对所有的请求进行拦截

(3)path类型(指定页面拦截)

在这里插入图片描述
这里的“/*" 表示上下文的一层目录,如果是拦截所有的用“/**”

4、prehandler方法,各个方法的执行顺序

(1)返回true多个拦截器的执行顺序

在这里插入图片描述
当有两个拦截器的时候,拦截的顺序是什么样子的呢?
在这里插入图片描述

  • 原因是呢?【其实就是我们的配置文件里面的书写顺序】
    • 首先你访问就会进入到这一点
      在这里插入图片描述
    • 然后会进入到这,遍历你的拦截器,第0个它自己创建的,第二第三就是我们创建的顺序了
      在这里插入图片描述
      此时执行后,我们的两句话就要输出了
      在这里插入图片描述
    • 接下来就要返回了
      在这里插入图片描述
    • 其他的为什么反着来输出
      在这里插入图片描述这里就要输出如下了
      在这里插入图片描述
    • 同样的渲染之后执行也是这样执行的
      在这里插入图片描述

(2)返回false多个拦截器的执行顺序

  • 首先修改这里
    在这里插入图片描述
  • 同样的也是执行处理前方法()
    在这里插入图片描述
    在这里插入图片描述
    又会返过去执行之前的方法。
    比如我现在有1,2,3,4,5拦截器:如果3拦截器返回false的话,那就会只有1和2和2会执行,后面的两就不会执行了,postHandler是任何一个都不会执行的,还有后面的after都不会执行了

(3)总结

在这里插入图片描述

四、SpringMVC之异常处理

1、异常处理器

在这里插入图片描述
在这里插入图片描述
自动的异常处理的话,我们就可以指定异常跳转到指定页面的配置。

  • 当你自己写的有问题的时候,它就会给你返回一个新的modelAndview
    在这里插入图片描述
    如果你的请求出了如下的一些错误就会到这里进行处理
    在这里插入图片描述
  • 自定义异常处理时候【我们可以通过配置文件和注解处理方式】
    在这里插入图片描述

2、基于配置的异常处理

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

  • 配置异常信息
    在这里插入图片描述
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
错误页面

<p th:text="@{ex}">

</p>
</body>
</html>

3、通过注解方式

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值