参照教程:https://www.bilibili.com/video/BV19K4y1L7MT

1.请求映射

1.1 rest使用与原理

1.1.1 使用

  • Rest风格支持(使用HTTP请求方式动词来表示对资源的操作

    • 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户
    • 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户
    • 核心Filter;HiddenHttpMethodFilter
    • 用法: 表单method=post,隐藏域 _method=put

    • SpringBoot中手动开启

      spring:mvc:hiddenmethod:filter:enabled: true
      

Controller:

@RestController
public class HelloController {@GetMapping("/user")public String getUser(){return "GET-张三";}@PostMapping("/user")public String saveUser(){return "POST-张三";}@PutMapping("/user")public String putUser(){return "PUT-张三";}@DeleteMapping("/user")public String deleteUser(){return "DELETE-张三";}}

测试页面:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>测试</title>
</head>
<body>
<h1>测试REST风格</h1>
<form method="post" action="/user"><input type="submit" value="POST"></form>
<form method="get" action="/user"><input type="submit" value="GET"></form>
<form method="post" action="/user"><input type="hidden" name="_method" value="put"><input type="submit" value="PUT">
</form>
<form method="post" action="/user"><input type="hidden" name="_method" value="delete"><input type="submit" value="DELETE">
</form>
</body>
</html>

自定义把_method 这个名字换成我们自己喜欢的:自定义HiddenHttpMethodFilter

@Configuration
public class WebConfiguration {@Beanpublic HiddenHttpMethodFilter hiddenHttpMethodFilter(){HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();hiddenHttpMethodFilter.setMethodParam("_m");return hiddenHttpMethodFilter;}
}

1.1.2 原理

Rest原理(表单提交要使用REST的时候)

  • 表单提交会带上**_method=PUT**

  • 请求过来被HiddenHttpMethodFilter拦截

    • 请求是否正常,并且是POST
    • 获取到**_method**的值。
    • 兼容以下请求;PUT.DELETE.PATCH
    • 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
    • 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的.
  • 为什么需要手动开启,以及可以自己配置HiddenHttpMethodFilter?

  • 为什么拦截的是_method?

  • 为什么表单请求方式需要是POST?

Rest使用客户端工具,

  • 如PostMan直接发送Put、delete等方式请求,无需Filter

1.2 请求映射原理

FrameworkServlet继承HttpServlet并重写了doGet()方法:

而doGet()最终还是要执行processRequest()这个方法,而processRequest()内部的核心方法是doService():

doService()是一个抽象方法:

protected abstract void doService(HttpServletRequest var1, HttpServletResponse var2) throws Exception;

在DispatcherServlet中有doService()的实现,而doService()中的核心是调用本类的doDispatch()方法,所以研究doDispatch()方法是最终的方法

对Spring MVC功能分析从DispatcherServlet的doDispatch()方法开始:

 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;boolean multipartRequestParsed = false;WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);try {try {ModelAndView mv = null;Object dispatchException = null;try {processedRequest = this.checkMultipart(request);multipartRequestParsed = processedRequest != request;//找到当前请求使用哪个Handler(Controller的方法)处理mappedHandler = this.getHandler(processedRequest);//HandlerMapping:处理器映射。/xxx->>xxxx

打断点,发送请求并进入这个方法:

可以看到,这个方法内部是将所有的handlerMappings用迭代器进行匹配:

这些handlerMappings有(index页发送的是Get请求):

进入第一个mapping,我们可以看到RequestMapping中有我们在控制器写的各种处理请求的方法

进入getHandler()方法,可以看到调用了getHandlerInternal()来处理:

进入getHandlerInternal()方法,可以看到调用了父类的getHandlerInternal()方法,再次打断点

在这个方法里再进行找路径以及请求方法:

总结:所有的请求映射都在HandlerMapping中。

  • SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html;

  • SpringBoot自动配置了默认 的 RequestMappingHandlerMapping

  • 请求进来,挨个尝试所有的HandlerMapping看是否有请求信息。

    • 如果有就找到这个请求对应的handler
    • 如果没有就是下一个 HandlerMapping
  • 我们需要一些自定义的映射处理,我们也可以自己给容器中放HandlerMapping。自定义 HandlerMapping

2.普通参数与基本注解

2.1 注解

@PathVariable、@RequesHeader

 @GetMapping("/car/id/{id}/owner/{owner}")public Map<String, Object> getCar(@PathVariable("id") Integer id,@PathVariable("owner") String owner,@PathVariable Map<String, String> kv,@RequestHeader("host") String host,@RequestHeader Map<String, String> headers){Map map = new HashMap();map.put("id", id);map.put("owner", owner);map.put("kv", kv);map.put("host", host);map.put("headers", headers);return map;}//前端页面:<a href="/car/id/11/owner/lisi">测试@PathVariable和@RequestHeader</a><br/>

@RequestParam、@CookieValue

  @GetMapping("/person")public Map<String, Object> getInfo(@RequestParam("id") Integer id, @RequestParam Map<String, String> info,@CookieValue("_ga") Cookie cookie, @CookieValue("_ga") String _ga){Map map = new HashMap();map.put("id", id);map.put("info", info);System.out.println(cookie.getName() + "---->");return map;}//<a href="/person?id=12&username=zhangsan&age=18">测试@RequestParam</a><br/>

@RequestBody

post方法请求才有请求体:

 @PostMapping("/save")public Map postMethod(@RequestBody String content){Map<String,Object> map = new HashMap<>();map.put("content",content);return map;}<form action="/save" method="post">姓名: <input type="text" name="username"><br/>密码: <input type="text" name="password"><br/><input type="submit" value="submit">
</form>

@RequestAttribute

获取请求域的值

@Controller
public class RequestTestController {@GetMapping("/goto")public String goToPage(HttpServletRequest request){request.setAttribute("username", "zhangsan");request.setAttribute("password", 1234567);return "forward:/success";}@ResponseBody@GetMapping("/success")public Map success(@RequestAttribute("username") String username,@RequestAttribute("password") Integer password,HttpServletRequest request){Map map = new HashMap();map.put("username", username);map.put("password", password);map.put("username_re", request.getAttribute("username"));map.put("password_re", request.getAttribute("password"));return map;}
}

@MatrixVariable与UrlPathHelper

矩阵变量:

配置:

@Configuration
public class WebConfiguration implements WebMvcConfigurer {@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {UrlPathHelper urlPathHelper = new UrlPathHelper();urlPathHelper.setRemoveSemicolonContent(false);configurer.setUrlPathHelper(urlPathHelper);}
}

或者:

@Configuration
public class WebConfiguration{@Beanpublic WebMvcConfigurer webMvcConfigurer(){return new WebMvcConfigurer(){@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {UrlPathHelper urlPathHelper = new UrlPathHelper();urlPathHelper.setRemoveSemicolonContent(false);configurer.setUrlPathHelper(urlPathHelper);}};}
}

测试:

  //1、语法: 请求路径:/cars/sell;low=34;brand=byd,audi,yd//2、SpringBoot默认是禁用了矩阵变量的功能//      手动开启:原理。对于路径的处理。UrlPathHelper进行解析。//              removeSemicolonContent(移除分号内容)支持矩阵变量的//3、矩阵变量必须有url路径变量才能被解析@GetMapping("/cars/{path}/{info}")public Map carsSell(@MatrixVariable("low") Integer low,@MatrixVariable("brand") List<String> brand,@PathVariable("path") String path,@MatrixVariable("price") Integer price){Map<String,Object> map = new HashMap<>();map.put("low",low);map.put("brand",brand);map.put("path",path);map.put("price", price);return map;}// /boss/1;age=20/2;age=10@GetMapping("/boss/{bossId}/{empId}")public Map boss(@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,@MatrixVariable(value = "age",pathVar = "empId") Integer empAge){Map<String,Object> map = new HashMap<>();map.put("bossAge",bossAge);map.put("empAge",empAge);return map;}

2.2 Servlet API

WebRequest、ServletRequest、MultipartRequest、 HttpSession、javax.servlet.http.PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId

2.3 复杂参数

Map、**Model(map、model里面的数据会被放在request的请求域 request.setAttribute)、**Errors/BindingResult、RedirectAttributes( 重定向携带数据)ServletResponse(response)、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder

Map<String,Object> map,  Model model, HttpServletRequest request 都是可以给request域中放数据,
request.getAttribute();

2.4 自定义参数

可以自动类型转换与格式化,可以级联封装。

/***     姓名: <input name="userName"/> <br/>*     年龄: <input name="age"/> <br/>*     生日: <input name="birth"/> <br/>*     宠物姓名:<input name="pet.name"/><br/>*     宠物年龄:<input name="pet.age"/>*/
@Data
public class Person {private String userName;private Integer age;private Date birth;private Pet pet;}@Data
public class Pet {private String name;private String age;}

自定义converter

    //1、WebMvcConfigurer定制化SpringMVC的功能@Beanpublic WebMvcConfigurer webMvcConfigurer(){return new WebMvcConfigurer() {@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {UrlPathHelper urlPathHelper = new UrlPathHelper();// 不移除;后面的内容。矩阵变量功能就可以生效urlPathHelper.setRemoveSemicolonContent(false);configurer.setUrlPathHelper(urlPathHelper);}@Overridepublic void addFormatters(FormatterRegistry registry) {registry.addConverter(new Converter<String, Pet>() {@Overridepublic Pet convert(String source) {// 啊猫,3if(!StringUtils.isEmpty(source)){Pet pet = new Pet();String[] split = source.split(",");pet.setName(split[0]);pet.setAge(Integer.parseInt(split[1]));return pet;}return null;}});}};}

3.响应处理

3.1 响应json

jackson.jar+@ResponseBody

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
web场景自动引入了json场景<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId><version>2.3.4.RELEASE</version><scope>compile</scope></dependency>

给前端自动返回json数据

    @ResponseBody@GetMapping("/pet")public Pet getPet(Pet pet){return pet;}<form action="/pet" method="get">姓名:<input type="text" name="name" value="cat"><br/>年龄:<input type="text" name="age" value="18"><br/><input type="submit" value="submit">
</form>

支持的返回值类型

ModelAndView
Model
View
ResponseEntity
ResponseBodyEmitter
StreamingResponseBody
HttpEntity
HttpHeaders
Callable
DeferredResult
ListenableFuture
CompletionStage
WebAsyncTask
有 @ModelAttribute 且为对象类型的
@ResponseBody 注解 ---> RequestResponseBodyMethodProcessor;

3.2 内容协商

根据客户端接收能力不同,返回不同媒体类型的数据

3.2.1 引入xml依赖

 <dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId>
</dependency>

3.2.2 使用postman测试接受不同类型的数据

只需要改变请求头中Accept字段。Http协议中规定的,告诉服务器本客户端可以接收的数据类型。

xml:

json:

4.模板引擎thymeleaf

4.1 thymeleaf简介

Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text.

现代化、服务端Java模板引擎

4.2 基本语法

1.表达式

2.字面量

  • 文本值: ‘one text’ , ‘Another one!’ **,…**数字: 0 , 34 , 3.0 , 12.3 **,…**布尔值: true , false

  • 空值: null

  • 变量: one,two,… 变量不能有空格

3.文本操作

  • 字符串拼接: +
  • 变量替换: |The name is ${name}|

4.数学运算

运算符: + , - , * , / , %

5.布尔运算

运算符: and , or

一元运算: ! , not

6.比较运算

比较: > , < , >= , <= ( gt , lt , ge , le **)**等式: == , != ( eq , ne )

7.条件运算

If-then: (if) ? (then)

If-then-else: (if) ? (then) : (else)

Default: (value) ?: (defaultvalue)

8.特殊操作

无操作: _

4.3 设置属性值-th:attr

设置单个值

<form action="subscribe.html" th:attr="action=@{/subscribe}"><fieldset><input type="text" name="email" /><input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/></fieldset>
</form>

设置多个值

<img src="../../images/gtvglogo.png"  th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

替代写法:

<input type="submit" value="Subscribe!" th:value="#{subscribe.submit}"/>
<form action="subscribe.html" th:action="@{/subscribe}">

4.4 迭代

<tr th:each="prod : ${prods}"><td th:text="${prod.name}">Onions</td><td th:text="${prod.price}">2.41</td><td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>
<tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'"><td th:text="${prod.name}">Onions</td><td th:text="${prod.price}">2.41</td><td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>

4.5 条件运算

<a href="comments.html"
th:href="@{/product/comments(prodId=${prod.id})}"
th:if="${not #lists.isEmpty(prod.comments)}">view</a>
<div th:switch="${user.role}"><p th:case="'admin'">User is an administrator</p><p th:case="#{roles.manager}">User is a manager</p><p th:case="*">User is some other thing</p>
</div>

4.6 属性优先级

4.7 thymeleaf使用

1.引入starter

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>

2.自动配好了thymeleaf

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
public class ThymeleafAutoConfiguration { }

自动配好的策略

  • 1、所有thymeleaf的配置值都在 ThymeleafProperties
  • 2、配置好了 SpringTemplateEngine
  • 3、配好了 ThymeleafViewResolver
  • 4、我们只需要直接开发页面
 public static final String DEFAULT_PREFIX = "classpath:/templates/";public static final String DEFAULT_SUFFIX = ".html";  //xxx.html

3.页面开发

html引入命名空间: xmlns:th=“http://www.thymeleaf.org”

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1 th:text="${msg}">哈哈</h1>
<h2><a href="www.atguigu.com" th:href="${link}">去百度</a>  <br/><a href="www.atguigu.com" th:href="@{link}">去百度2</a>
</h2>
</body>
</html>

4.8 应用

1.路径构建

    <form class="form-signin" action="index.html" method="post" th:action="@{/login}">

这是前端登录页面的表格,点击提交后会请求到相应的controller来处理:

@PostMapping("/login")public String main(User user, HttpSession session, Model model){String username = user.getUsername();String password = user.getPassword();if("deserts".equals(username) && "123".equals(password)){session.setAttribute("user", user);return "redirect:/main.html";}else{model.addAttribute("msg", "账号或者密码错误");return "login";}}@GetMapping("main.html")public String mainPage(HttpSession session, Model model){Object user = session.getAttribute("user");if (user != null){return "main";}else{model.addAttribute("msg", "请重新登录");return "login";}}

直接写入标签内的文本:

 <a href="#">[[${session.user.username}]]</a>

2.错误回显

前面处理的用户登录的controller在用户登录失败或着没登录直接访问main页面时,应该返回登录页及给出提示信息,通过model设置request域的值,从前端页面取出来,达到回显的效果

<label style="color:green;" th:text="${msg}"/>

3.抽取重复页面

这里主要参照官网,区分三种抽取的方式。抽取的片段:

<footer th:fragment="copy">&copy; 2011 The Good Thymes Virtual Grocery
</footer

页面引入抽取片段的三种方式:

<body>...<div th:insert="footer :: copy"></div><div th:replace="footer :: copy"></div><div th:include="footer :: copy"></div></body>

会导致的结果:

<body>...<div><footer>&copy; 2011 The Good Thymes Virtual Grocery</footer></div><footer>&copy; 2011 The Good Thymes Virtual Grocery</footer><div>&copy; 2011 The Good Thymes Virtual Grocery</div></body>

区别:insert是插入原引入标签的内部,replace是将原标签给替换成碎片部分的标签和内容,include是去掉标签将碎片内容包含在原标签中。

4.数据渲染(遍历)

controller:

    @GetMapping("/dynamic_table")public String dynamic_table(Model model){List<User> users = Arrays.asList(new User("aaa", "111"), new User("bbb", "222"),new User("ccc", "333"), new User("ddd", "444"));model.addAttribute("users", users);return "table/dynamic_table";}

页面:

<table class="display table table-bordered" id="hidden-table-info"><thead><tr><th class="hidden-phone">#</th><th class="hidden-phone">用户名</th><th class="hidden-phone">密码</th></tr></thead><tbody><tr class="gradeX" th:each="user,status:${users}"><td class="hidden-phone" th:text="${status.count}"></td><td class="center hidden-phone">[[${user.username}]]</td><td class="center hidden-phone" th:text="${user.password}"></td></tr></tbody></table>

效果:

Spring boot(4) web开发(2) 请求处理、响应处理、模板引擎相关推荐

  1. Spring Boot(5) web开发(3)拦截器、文件上传、异常处理

    Spring Boot(5) web开发(3)拦截器.文件上传.异常处理 学习视频: https://www.bilibili.com/video/BV19K4y1L7MT?p=49&spm_ ...

  2. Spring Boot之Web开发

    Web开发 简单了解 快速上手 JSON 的支持 RESTful 的支持 支持热部署 快速上手 拦截器与过滤器 自定义过滤器 示例 自定义拦截器 示例 打包部署 多环境配置 服务器配置 项目打包 简单 ...

  3. Spring Boot与web开发

    Spring Boot与web开发 1. 2. 3. 4. 5. 6. 7. 8. 9. 0. 四.Web开发 1.简介 使用SpringBoot: 1).创建SpringBoot应用,选中我们需要的 ...

  4. 【spring boot】第3篇:spring boot 进行 web 开发

    spring boot 对 web 静态资源的管理 经过前两篇文章我们知道spring boot最大的功能就是自动配置.主要是通过以下两个类实现该功能: xxxxAutoConfiguration : ...

  5. Gradle进阶:1: 结合spring boot进行web开发

    在前面的文章中介绍了如何使用gradle的基础知识,这篇文章在某种程度上才是真正意义上的第一个hello world,这里使用一个简单的spring boot的例子,通过gradle进行编译和构建以及 ...

  6. spring boot 整合web开发之文件上传、静态资源访问、异常处理、返回JSON数据

    目录 springboot 整合web开发 返回json数据 静态资源访问 文件上传 全局异常 1.返回json数据 springboot默认的是jackson-databind做为json处理器.也 ...

  7. Spring Boot与Web开发简介||SpringBoot对静态资源的映射规则

    Web开发 1.简介 使用SpringBoot: 1).创建SpringBoot应用,选中我们需要的模块: 2).SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运 ...

  8. SpringBoot资料合集-04【Spring Boot与Web开发】

    1.SpringMVC快速使用 1.基于restful http接口 的CURD 2.调用rest http接口 3.通过postman调用 4.通过swagger调用 2.SpringMVC自动配置 ...

  9. Spring boot的Web开发

    开发步骤 第一步,创建SpringBoot应用,选中我们需要的模块 第二步,SpringBoot已经默认,将这些场景配置好了 只需要在配置文件中,指定少量配置就可以运行起来 第三步,自己编写业务代码 ...

  10. spring boot 整合web开发(二)

    目录 自定义错误页 CORS支持(前端跨域请求) 拦截器HandlerInterceptor 启动系统任务 springboot配置AOP 整合servlet.filter.listener 下图为本 ...

最新文章

  1. OEM 按钮乱码解决办法
  2. 30万奖金等你拿,“信也科技杯”第五届数据解决方案应用大赛火热报名中!...
  3. 百度地图标点点击变色_《和平精英》版本爆料第三弹:雪地洞穴开启!组队标点功能升级~...
  4. 山东专升本access知识点_全国各省份每年的专升本考试大纲啥时候公布?考纲公布之前你该做什么?...
  5. java调用存储过程同时获取[返回参数]和[结果集]
  6. 黑科技揭秘:如何通过阿里云超算,使得汽车仿真效率提升25%
  7. ASCII码从小到大排序(字典序)
  8. php上传完没进度条_php使用APC实现实时上传进度条功能
  9. 用于PC的骁龙1000近似实锤了,高通员工LinkedIn泄露天机
  10. 使用 Repeater方式和完全静态页面使用AJAX读取和提交数据
  11. Spark Structured Steaming 聚合、watermark 以及 window操作,结合输出模式的研究总结
  12. [ThinkPHP]打开页面追踪调试
  13. 第一章ASP程序设计概述
  14. Android常用的工具方法
  15. Java实现anagram算法
  16. 云:SD-WAN不断增长的驱动力
  17. STM32F427利用FSMC接口访问FPGA的SRAM(3)—— STM32F427访问FPGA的SRAM
  18. python不同方式爬qq音乐(get)及网易云(post)某歌手单曲歌名
  19. Nginx面试题(史上最全 + 持续更新)
  20. Android开发真实谎言:个人无空间nbsp;…

热门文章

  1. MATLAB图像处理之图像边缘提取
  2. linux如何判断网线插入_快速鉴定网线质量的常用方法
  3. Linux中MongoDB创建数据库
  4. Spring Data Jpa 报错org.hibernate.LazyInitializationException: could not initialize proxy
  5. IDEA中Maven项目中界面右边的Maven Projects中子项目出现灰色
  6. C语言求超级素数的个数,求一个输出a-b的超级素数程序(c)
  7. python怎么保存为nii文件_Ubuntu+python将nii图像保存成png格式
  8. MySQL5.7收集表统计信息时对该表上增删改查的影响
  9. Oracle中字符串转义问题总结
  10. css未生效,css不生效是什么原因