SpringMVC修炼之旅(3)REST风格与拦截器

一、概述

1.1简介

Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

1.2功能

资源:互联网所有的事物都可以被抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
分别对应 添加、 删除、修改、查询。

1.3优点

  • 隐藏资源的访问行为,无法通过地址得知对资源是何种操作
  • 书写简化 

1.4RESTful入门案例

 //设置当前请求方法为DELETE,表示REST风格中的删除操作//@PathVariable注解用于设置路径变量(路径参数),要求路径上设置对应的占位符,并且占位符名称与方法形参名称相同@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)@ResponseBodypublic String delete(@PathVariable Integer id){System.out.println("user delete..." + id);return "{'module':'user delete'}";}
DELETE http://localhost:8080/users/1

类型:形参注解

位置:SpringMVC控制器方法形参定义前面

作用:用于将URL中的路径变量绑定到方法参数上。这样,当用户访问一个包含路径变量的URL时,这些路径变量的值将被自动传递给相应的方法参数

@RequestBody  @RequestParam  @PathVariable的区别 

区别

  • @RequestParam用于接收url地址传参或表单传参
  • @RequestBody用于接收json数据
  • @PathVariable用于接收路径参数,使用{参数名称}描述路径参数

应用

  • 后期开发中,发送请求参数超过1个时,以json格式为主,@RequestBody应用较广
  • 如果发送非json格式数据,选用@RequestParam接收请求参数
  • 采用RESTful进行开发,当参数数量较少时,例如1个,可以采用@PathVariable接收请求路径变量,通常用于传递id值

1.5RESTful快速开发

 改进

package com.yanyu.controller;import com.yanyu.pojo.Book;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;//@Controller
//@ResponseBody配置在类上可以简化配置,表示设置当前每个方法的返回值都作为响应体
//@ResponseBody
@RestController     //使用@RestController注解替换@Controller与@ResponseBody注解,简化书写
@RequestMapping("/books")
public class BookController {//    @RequestMapping( method = RequestMethod.POST)@PostMapping        //使用@PostMapping简化Post请求方法对应的映射配置public String save(@RequestBody Book book){System.out.println("book save..." + book);return "{'module':'book save'}";}//    @RequestMapping(value = "/{id}" ,method = RequestMethod.DELETE)@DeleteMapping("/{id}")     //使用@DeleteMapping简化DELETE请求方法对应的映射配置public String delete(@PathVariable Integer id){System.out.println("book delete..." + id);return "{'module':'book delete'}";}//    @RequestMapping(method = RequestMethod.PUT)@PutMapping         //使用@PutMapping简化Put请求方法对应的映射配置public String update(@RequestBody Book book){System.out.println("book update..."+book);return "{'module':'book update'}";}//    @RequestMapping(value = "/{id}" ,method = RequestMethod.GET)@GetMapping("/{id}")    //使用@GetMapping简化GET请求方法对应的映射配置public String getById(@PathVariable Integer id){System.out.println("book getById..."+id);return "{'module':'book getById'}";}//    @RequestMapping(method = RequestMethod.GET)@GetMapping             //使用@GetMapping简化GET请求方法对应的映射配置public String getAll(){System.out.println("book getAll...");return "{'module':'book getAll'}";}
}

@RestController

类型:类注解

位置:基于SpringMVC的RESTful开发控制器类定义上方

作用:

是Spring框架中的一个注解,用于标识一个类是一个RESTful风格的控制器。它是@Controller和@ResponseBody注解的组合,表示这个类中的方法返回的是数据而不是视图。使用@RestController注解可以简化代码,不需要在每个方法上添加@ResponseBody注解,同时也可以让Spring自动将方法返回的数据转换为JSON格式。这样就可以方便地构建RESTful风格的API。

@GetMapping  @PostMapping

@PutMapping @DeleteMapping

类型:方法注解

位置:基于SpringMVC的RESTful开发控制器方法定义上方

作用:设置当前控制器方法请求访问路径与请求动作,每种对应一个请求动作,例如@GetMapping对应GET请求 

属性 value(默认):请求访问路径

 1.6案例实现

实体类

package com.yanyu.pojo;import lombok.*;@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Book {private Integer id;private String type;private String name;private String description;}

 控制类

package com.yanyu.controller;import com.yanyu.pojo.Book;
import org.springframework.web.bind.annotation.*;import java.util.ArrayList;
import java.util.List;@RestController
@RequestMapping("/books")
public class BookController {@PostMappingpublic String save(@RequestBody Book book){System.out.println("book save ==> "+ book);return "{'module':'book save success'}";}@GetMappingpublic List<Book> getAll(){System.out.println("book getAll is running ...");List<Book> bookList = new ArrayList<Book>();Book book1 = new Book();book1.setType("计算机");book1.setName("SpringMVC入门教程");book1.setDescription("小试牛刀");bookList.add(book1);Book book2 = new Book();book2.setType("计算机");book2.setName("SpringMVC实战教程");book2.setDescription("一代宗师");bookList.add(book2);Book book3 = new Book();book3.setType("计算机丛书");book3.setName("SpringMVC实战教程进阶");book3.setDescription("一代宗师呕心创作");bookList.add(book3);return bookList;}}

测试

POST http://localhost:8080/books
Content-Type: application/json{"id" : 11111,"type" : "计算机丛书","name" : "Springmvc","description" : "好书"}
GET http://localhost:8080/books

配置类-过滤器

package com.itheima.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {//设置静态资源访问过滤,当前类需要设置为配置类,并被扫描加载@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {//当访问/pages/????时候,从/pages目录下查找内容registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");registry.addResourceHandler("/js/**").addResourceLocations("/js/");registry.addResourceHandler("/css/**").addResourceLocations("/css/");registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");}
}

二、拦截器

2.1概述

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

**过滤器与拦截器的区别:**拦截器是AOP思想的具体应用。

过滤器

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

拦截器

  • 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
  • 拦截器只会拦截访问的控制器方法, 如果访问的是jsp/html/css/image/js是不会进行拦截的

  1. 浏览器发送一个请求会先到Tomcat的web服务器
  2. Tomcat服务器接收到请求以后,会去判断请求的是静态资源还是动态资源
  3. 如果是静态资源,会直接到Tomcat的项目部署目录下去直接访问
  4. 如果是动态资源,就需要交给项目的后台代码进行处理
  5. 在找到具体的方法之前,我们可以去配置过滤器(可以配置多个),按照顺序进行执行
  6. 然后进入到到中央处理器(SpringMVC中的内容),SpringMVC会根据配置的规则进行拦截
  7. 如果满足规则,则进行处理,找到其对应的controller类中的方法进行执行,完成后返回结果
  8. 如果不满足规则,则不进行处理
  9. 这个时候,如果我们需要在每个Controller方法执行的前后添加业务,具体该如何来实现?这个就是拦截器要做的事。

2.2入门案例

拦截器配置

package com.yanyu.interceptor;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;@Component
//定义拦截器类,实现HandlerInterceptor接口
//注意当前类必须受Spring容器控制
public class ProjectInterceptor implements HandlerInterceptor {@Override//原始方法调用前执行的内容//返回值类型可以拦截控制的执行,true放行,false终止public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String contentType = request.getHeader("Content-Type");HandlerMethod hm = (HandlerMethod)handler;System.out.println("preHandle..."+contentType);return true;}@Override//原始方法调用后执行的内容public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle...");}@Override//原始方法调用完成后执行的内容public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion...");}
}

 这段代码是一个基于Spring MVC的拦截器。它实现了HandlerInterceptor接口,并重写了preHandlepostHandleafterCompletion三个方法。在preHandle方法中,首先获取请求头中的"Content-Type",然后将其与处理器对象进行类型转换,最后输出"preHandle..."。postHandle方法中只输出"postHandle..."。afterCompletion方法中只输出"afterCompletion..."。这个拦截器的作用是在请求处理过程中,对请求进行预处理、后处理和完成处理。

 监听器

package com.yanyu.config;import com.yanyu.interceptor.ProjectInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {@Autowiredprivate ProjectInterceptor projectInterceptor;//设置静态资源访问过滤,当前类需要设置为配置类,并被扫描加载@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {//当访问/pages/????时候,从/pages目录下查找内容registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");}@Overrideprotected void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");}
}

测试

POST http://localhost:8080/books
Content-Type: application/json{"id" : 11111,"type" : "计算机丛书","name" : "Springmvc","description" : "好书"}

2.3运行流程

2.4拦截器参数

前置处理方法

原始方法之前运行preHandle

public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception {//handler:被调用的处理器对象,本质上是一个方法对象,对反射中的Method对象进行了再包装return true;
}

 使用handler参数,可以获取方法的相关信息,例如

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HandlerMethod hm = (HandlerMethod)handler;String methodName = hm.getMethod().getName();//可以获取方法的名称return true;
}
后置处理方法
@Override//原始方法调用后执行的内容public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle...");}
前三个参数和上面的是一致的。
modelAndView: 如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行调整
因为咱们现在都是返回 json 数据,所以该参数的使用率不高。
完成处理方法
拦截器最后执行的方法,无论原始方法是否执行
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex) throws Exception {System.out.println("afterCompletion");
}
//ex:如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理  
//因为我们现在已经有全局异常处理器类,所以该参数的使用率也不高。

2.5拦截器链配置

拦截器执行的顺序是和配置顺序有关。就和前面所提到的运维人员进入机房的案例,先进后出。
当配置多个拦截器时,形成拦截器链
拦截器链的运行顺序参照拦截器添加顺序为准
当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
当拦截器运行中断,仅运行配置在前面的拦截器的 afterCompletion 操作

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/263358.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mysql- 流程函数-(If, CASE WHEN)的使用及练习

目录 4.1 If函数语法格式 4.2 CASE WHEN 条件表达式格式 4.3 update与 case when 4.4 练习题1 4.5 练习题2 4.6 练习题3-行转列 4.7 牛客练习题 4.8 LeetCode练习题 4.1 If函数语法格式 IF(expr1,expr2,expr3) 解释&#xff1a; 如果表达式expr1true(expr1 <>…

SSL 数字证书的一些细节

参考&#xff1a;TLS/SSL 协议详解(6) SSL 数字证书的一些细节1 证书验证 地址&#xff1a;https://wonderful.blog.csdn.net/article/details/77867063 参考&#xff1a;TLS/SSL协议详解 (7) SSL 数字证书的一些细节2 地址&#xff1a;https://wonderful.blog.csdn.net/articl…

Proteus仿真--基于12864的自制硬件汉字库的应用

本文介绍基于12864的自制硬件汉字库的应用设计&#xff08;完整仿真源文件及代码见文末链接&#xff09; 其中12864LCD中显示的汉字是存储在2块AT24C1024芯片中 仿真图如下 仿真运行视频 Proteus仿真--基于12864的自制硬件字库的应用 附完整Proteus仿真资料代码资料 链接&am…

【C++进阶】AVL树

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

论文阅读[2023ICME]Edge-FVV: Free Viewpoint Video Streaming by Learning at the Edge

Edge-FVV: Free Viewpoint Video Streaming by Learning at the Edge 会议信息&#xff1a; Published in: 2023 IEEE International Conference on Multimedia and Expo (ICME) 作者&#xff1a; 1 背景 FVV允许观众从多个角度观看视频&#xff0c;但是如果所选视点的视频…

idea的基本使用

1.创建一个基础的项目 2.创建一个包 3.创建一个java文件 4.查看日志

关于AllowBeanDefinitionOverriding属性设置问题

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是「奇点」&#xff0c;江湖人称 singularity。刚工作几年&#xff0c;想和大家一同进步&#x1f91d;&#x1f91d; 一位上进心十足的【Java ToB端大厂…

华为配置Smart Link负载分担示例

Smart Link基本概念 Smart Link通过两个端口相互配合工作来实现功能。这样的一对端口组成了一个Smart Link组。为了区别一个Smart Link组中的两个端口&#xff0c;我们将其中的一个叫做主端口&#xff0c;另一个叫做从端口。同时我们利用Flush报文、Smart Link实例和控制VLAN等…

时间序列预测专栏介绍 — 算法原理、源码解析、项目实战

专栏链接&#xff1a;https://blog.csdn.net/qq_41921826/category_12495091.html 专栏内容 所有文章提供源代码、数据集、效果可视化 文章多次上热搜和每日必看榜单 时间序列预测存在的问题 现有的大量方法没有真正的预测未来值&#xff0c;只是用历史数据做验证 利用时间序列…

Python模块化设计程序(以打印日期为例)

我们现在接触过了大量的函数。有自己编写的函数、有内置函数、有模块中的函数等等。编写程序、制作软件&#xff0c;不可避免的使用大量函数。今天我采用编写日历的例子&#xff0c;很多函数都是由我们自己编写的。自己编写了函数,就知道函数中到底发生了什么样的运算,传入了什…

Oracle高可用一家老小全在这里

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

JUC并发编程02——锁

一.乐观锁和悲观锁 悲观锁 认为自己在使用数据的时候一定有别的线程来修改数据&#xff0c;因此在获取数据的时候会先加锁&#xff0c;确保数据不会被别的线程修改。synchronized关键字和Lock的实现类都是悲观锁。 适用场景&#xff1a;适合写操作多的场景&#xff0c;先加锁…