目录
一、前言
二、@RequestMapping
三、params表达式
四、Ant风格资源地址
五、@PathVariable
六、Rest风格的请求数据
七、请求映射数据
相关文章
【SpringMVC】入门篇:带你了解SpringMVC的执行流程 | 【SpringMVC】入门篇:带你了解SpringMVC的执行流程 |
一、前言
在入门篇中,我们对SpringMVC做了简单的介绍。对它的执行流程有了大概的认识,我们从这节开始讲解它使用。
二、@RequestMapping
在上节的演示中,我们使用到了@RequestMapping
,这里我们对他做一个详解。了解它的作用是什么。
<form action="user/buy" method="get">
购买人:<input type="text" name="username"><br>
购买数量:<input type="text" name="nums"><br>
<input type="submit" value="登录">
</form>
package com.jl.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
/**
* ClassName: UserHandler
* Package: com.jl.web
* Description: @RequestMapping的介绍使用
*
* @Author: Long
* @Create: 2022/11/26 - 16:38
* @Version: v1.0
*
*/
@RequestMapping(value = "/user")
@Controller // 这就是一个控制器
public class UserHandler {
@RequestMapping(value = "/buy")
public String buy(){
System.out.println("购买商品");
return "success";
}
}
- @RequestMapping可以在方法、类上使用。当然也可以组合使用。例如:我们上上边示例的访问路径就是:
http://localhost:8080/web工程路径/user/buy
。 - @RequestMapping的参数中可以指定浏览器的请求方式。默认支持 POST 和 GET(即:不指定method参数的时候)。例:
// @RequestMapping(value = "/buy",method = RequestMethod.POST)
- 通过 method 指定请求方式:最常用的有 POST、GET、DELETE、PUT。
- 如果前端的请求方式和后端指定的请求方式不一致,就会报405错误。
"HTTP Status 405 - Request method 'GET' not supported"
- 对于请求路径和请求方式都指定的时候,我们可以使用简化的一种注解:
- @DeleteMapping:指定DELETE请求方式。
- @PostMapping:指定POST请求方式。
- @GetMapping:指定GET请求方式。
- @PutMapping:指定Put请求方式。
三、params表达式
<h1>演示params的使用</h1>
<a href="user/find?bookId=100">查询书籍</a>
@RequestMapping(value = "/find",params = "bookId",method = RequestMethod.GET)
public String search(String bookId){
System.out.println("购买书籍的ID为:" + bookId);
return "success";
}
- params = “bookId” 表示请求该目标方法时,必须给一个bookId,但值没有限制。如果没有携带此参数,就会报错400。
- 并且此参数会自动赋值给 search(String bookId)。
- 如果 params = “bookId=100”,就必须要求参数值为100。如果值不为100就会报错。
- 也可以 params = “bookId!=100”,来限制参数不为某个值。
SpringMVC当你的形参名和请求参数名一样的使用,也会自动注入到形参中。也就是说我们可以不使用其他任何的注解,也可以注入到形参中。
四、Ant风格资源地址
这个有点类似于我们以前学的通配符。
这里我们提出一个需求:同时匹配 /message/aa、/message/aa/bb/cc
<h1>Ant风格请求资源地址</h1>
<a href="user/message/aa">发送消息1</a>
<a href="user/message/aa/bb/cc">发送消息2</a>
@RequestMapping(value = "/message/**")
public String im(){
System.out.println("发送消息");
return "success";
}
@RequestMapping(value = “/message/**”)表示可以匹配多层路径
五、@PathVariable
使用@PathVariable
可以简化我们的资源请求地址。我们来将传统的方式和简化之后的资源请求URI做一个对比:
传统方式:http://localhost:8080/web工程路径/资源地址?参数1=参数值1&参数2=参数值2
简化之后:http://localhost:8080/web工程路径/资源地址?参数值1/参数值2
当想要支持这种URI就得配合使用@PathVariable
。
<h1>占位符的演示</h1>
<a href="user/reg/mary/100">占位符的演示</a>
@RequestMapping(value = "/reg/{username}/{userid}")
public String register(@PathVariable("username") String name,
@PathVariable("userid") String id){
System.out.println("username= " + name + " userid= " + id);
return "success";
}
- 从他的注解就可以知道,它中文译为
路径变量
。就是说它是根据路径来获取参数,而不是根据参数名来获取的。 {}
里边的名称要和我们@PathVariable
的参数值一致。他就会自动将获取到的参数值注入到添加注解的形参中。
六、Rest风格的请求方式
我们先来了解一下它是一个什么东西❓
Rest风格的请求方式,用请求方式来体现业务逻辑。
- GET:用来获取资源
- POST:用来新建资源
- DELETE:用来更新资源
- PUT:用来删除资源
后端一般通过表单来获取前端发送的参数,所以我们有以下几个需要处理的问题:
- 浏览器form表单只支持 get post,因此得到put/delete需要Spring提供的
HiddenHttpMethodFilter
。过滤器进行转换。可以将这些请求转换为标准的http方法,使得支持POST、PUT、DELETE、GET。 HiddenHttpMethodFilter
只可以对POST请求进行转换。- 这个过滤器要在web.xml中配置。
配置文件中配置转换的过滤器
<!--配置过滤器,用于转换Rest风格的请求方式
除了这个过滤器,还得在Spring配置文件中添加两个配置
-->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在Spring配置文件中添加需要的配置
<!--两个常用配置-->
<!--支持MVC的高级功能,比如JS303的校验,映射动态请求-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--将springMVC不能处理的请求,交给tomcat处理,比如css,js-->
<mvc:default-servlet-handler/>
前端演示用到的代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>rest </title>
<%-- 引入jquery--%>
<script type="text/javascript" src="script/jquery.js"></script>
<script type="text/javascript">
$(function () { //当页面加载完成后,就执行=> 如果你完全忘记,去回顾我们讲过的jquery
//给删除超链接绑定一个点击事件
$("#deleteBook").click(function (){
//我们自己定义给提交的行为
// 将我们a标签中的超链接的值设置给form表单的action中,最后提交
$("#hiddenForm").attr("action", this.href);
$(":hidden").val("DELETE");
$("#hiddenForm").submit();
return false; //改变点击超链接的行为, 不在提交
})
})
</script>
</head>
<body>
<h3>Rest风格的crud操作案例</h3>
<br><hr>
<h3>rest风格的url 查询书籍[get]</h3>
<a href="user/book/200">点击查询书籍</a>
<br><hr>
<h3>rest风格的url 添加书籍[post]</h3>
<form action="user/book" method="post">
name:<input name="bookName" type="text"><br>
<input type="submit" value="添加书籍">
</form>
<br><hr>
<h3>rest风格的url, 删除一本书[delete]</h3>
<a href="user/book/600" id="deleteBook">删除指定id的书</a>
<form action="" method="post" id="hiddenForm">
<input type="hidden" name="_method"/>
</form>
<br><hr>
<h3>rest风格的url 修改书籍[put]</h3>
<form action="user/book/666" method="post">
<input type="hidden" name="_method" value="PUT">
<input type="submit" value="修改书籍~">
</form>
</body>
</html>
<a>
标签是使用GET方式发送的请求,当我们想通过<a>
标签来使用Rest风格的请求方式的时候,需要通过javaScrpit+Ajax
来转成一个POST
请求。我们的过滤器底层是通过参数_method
来获取需要转换的类型,所以我们的请求参数里边得有_method=转换的类型
。
后端代码
package com.jl.web.rest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* ClassName: BookHandler
* Package: com.jl.web.rest
* Description: 处理rest风格的请求-crud
*
* @Author: Long
* @Create: 2022/11/26 - 18:40
* @Version: v1.0
*/
@RequestMapping(value = "/user")
@Controller
public class BookHandler {
@RequestMapping(value = "/book/{id}",method = RequestMethod.GET)
public String getBook(@PathVariable("id")String id){
System.out.println("查询的书籍的id= " + id);
return "success";
}
@RequestMapping(value = "/book",method = RequestMethod.POST)
public String addBook(String bookName){
System.out.println("添加书籍的name= " + bookName);
return "success";
}
// 删除[DELETE]
@RequestMapping(value = "/book/{id}",method = RequestMethod.DELETE)
public String delBook(@PathVariable("id") String id){
System.out.println("删除书籍的id= " + id);
// 这里会报一个405的错误【HTTP Status 405 - JSPs only permit GET POST or HEAD】
// 因为JSP只支持 GET 和 POST 、HEAD请求。我们可以通过请求重定向的方式进行跳转。
// return "success"; // 这是请求转发
return "redirect:/user/success";
}
// 修改[put]
@RequestMapping(value = "/book/{id}",method = RequestMethod.PUT)
public String updateBook(@PathVariable("id") String id){
System.out.println("修改书籍的id= " + id);
return "redirect:/user/success";
}
// 如果是 user/success,就转发到 success.jsp
@RequestMapping(value = "/success")
public String successGeneral(){
return "success";
}
}
到这里虽然我们已经演示完毕,但至于它到底是怎样执行的,我相信很多小伙伴还是一头雾水,下边我们来梳理一下,它底层的执行转换流程。
// 源码:
// HiddenHttpMethodFilter 会根据参数名为 "_method" 来获取它的参数,而此参数值是我们需要
// 转换的请求方式。
public static final String DEFAULT_METHOD_PARAM = "_method";
if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
String paramValue = request.getParameter(this.methodParam);
if (StringUtils.hasLength(paramValue)) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
if (ALLOWED_METHODS.contains(method)) {
requestToUse = new HttpMethodRequestWrapper(request, method);
}
}
}
//而且我们只会转换 ”POST“ 方式的请求。并且不是所有的都转换,转换的是包含在 ALLOWED_METHODS 里边的
private static final List<String> ALLOWED_METHODS =
Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(),
HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
//ALLOWED_METHODS里边只会将其转化为 DELETE、PUT、PATCH
七、请求映射数据
@RequestParam
当我们的请求参数和形参名的定义不一致时,可以使用@RequestParam
来实现参数的注入。
<h2>获取到超链接的值</h2>
<hr/>
<a href="vote/vote01?name=mary">获取超链接的参数</a>
@RequestMapping(value = "vote")
@Controller
public class VoteHandler {
@RequestMapping(value = "/vote01")
public String test01(@RequestParam(value = "name",required = false) String username){
System.out.println("拿到的username = " + username);
return "success";
}
}
- @RequestParam(value = “name”)会获取到参数名为 name 的参数值。
- required = false 表示,此参数可以没有。默认是true,即:参数值不能为空
- @RequestParam会将获取到的参数值赋值给(String username)。
- 使用@RequestParam可以解决我们的前后端参数名不一致的情况。
- 使用了@RequestParamd之后,前端的参数名必须和@RequestParam的value保持一致。
@RequestHeader
使用此注解可以获取到请求头信息。
<h2>获取请求头信息</h2>
<hr/>
<a href="vote/vote02">获取请求头信息</a>
</body>
/**
* 需求:获取请求头的参数
*/
@RequestMapping(value = "/vote02")
public String test02(@RequestHeader(value = "Accept-Encoding") String ae,
@RequestHeader(value = "Host") String host){
System.out.println("Accept-Encoding = " + ae);
System.out.println("Host = " + host);
return "success";
}
获取JavaBean
在SpringMVC中,可以将请求参数自动封装成一个对象。
<h2>添加主人信息</h2>
<hr/>
<form action="vote/vote03" method="post">
主人编号<input type="text" name="id">
主人姓名<input type="text" name="name">
宠物号<input type="text" name="pet.id">
宠物名<input type="text" name="pet.name">
<input type="submit" value="提交">
</form>
对应的对象
package com.jl.web.requestparam.entity;
/**
* ClassName: Monster
* Package: com.jl.web.requestparam.entity
* Description:
*
* @Author: Long
* @Create: 2022/11/27 - 12:44
* @Version: v1.0
*/
public class Master {
private Integer id;
private String name;
private Pet pet;
public Master(Integer id, String name, Pet pet) {
this.id = id;
this.name = name;
this.pet = pet;
}
public Master() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Pet getPet() {
return pet;
}
public void setPet(Pet pet) {
this.pet = pet;
}
@Override
public String toString() {
return "Master{" +
"id=" + id +
", name='" + name + '\'' +
", pet=" + pet +
'}';
}
}
@RequestMapping(value = "/vote03")
public String test03(Master master){
System.out.println("主人的信息 = " + master);
return "success";
}
- 方法的形参对应的类型来指定即可。SpringMVC会自动的进行封装。
- 如果是自动封装,提交的参数名必须要和对象的属性名保持一致。
- 如果属性是对象,这里仍然是通过 字段名.字段 = 值 就行。例如:pet.name进行提交即可(级联操作)。
- 如果提交的参数名和对象的属性名不一致,则对象的属性值就为null。
SevletyAPI的使用
在SpringMVC中,它提供了我们原生的Servlet对象,供我们调用。
<h2>演示servlet API 的使用</h2>
<hr/>
<form action="vote/vote04" method="post">
用户名:<input type="text" name="username"><br/>
密码:<input type="text" name="password"><br/>
<input type="submit" value="提交">
</form>
/**
* 使用原生的Servlet的API。前提:要先引入相应的jar包:servlet-api.jar
*
*/
@RequestMapping(value = "/vote04")
public String test04(HttpServletRequest request, HttpServletResponse response,HttpSession session){
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username);
System.out.println(password);
// 补充:
// 我们通过HttpSession形参传入和request获取的session是同一个对象。
HttpSession session1 = request.getSession();
System.out.println(session == session1);
return "success";
}
以上就是我们这节对于SpringMVC基本使用的讲解。下节我们对SpringMVC视图以及它的模型数据最进一步了解。
如果文章中有描述不准确或者错误的地方,还望指正。您可以留言📫或者私信我。🙏
最后希望大家多多 关注+点赞+收藏^_^,你们的鼓励是我不断前进的动力!!!
感谢感谢~~~🙏🙏🙏