SpringMVC(Rest+映射请求数据+模型数据+视图和视图解析器)
笔记型博客之SpringMVC(Rest+映射请求数据+模型数据+自定义视图和视图解析器)
目录
1.2解读@RequestParam(value="name", required=false)
1.2方式 1: 通过 HttpServletRequest 放入 request 域
1.3方式 2: 通过请求的方法参数 Map 放入 request 域,object>
1.4 方式 3: 通过返回 ModelAndView 对象 实现 request 域数据
3.@ModelAttribute 实现 prepare 方法(前置方法)
一.Rest-优雅的 url 请求风格
1.Rest-基本介绍
1.说明
2.REST 的核心过滤器
2.Rest 风格的 url-完成增删改查
2.1代码实现
1. 修改 web.xml 添加 HiddenHttpMethodFilter
<!-- 1. 配置 HiddenMethodFilter 过滤器-->
<!-- 2. 可以将以 post 方式提交的 delete 和 put 请求进行转换-->
<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>
2. 修改 springDispatcherServlet-servlet.xml
<!-- 加入两个常规配置 -->
<!-- 能支持 SpringMVC 高级功能,比如 JSR303 校验,映射动态请求 -->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 将 SpringMVC 不能处理的请求交给 Tomcat, 比如请求 css,js 等-->
<mvc:default-servlet-handler/>
3.rest.jsp前端页面
<%--
User:海绵hong
Date: 2022/10/26
Time: 19:46
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>rest </title>
</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, 删除一本书</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>
2.2查询GET
//查询[GET]
@GetMapping (value = "/book/{id}")
public String getBook(@PathVariable("id") String id) {
System.out.println("查询书籍 id=" + id );
return "success";
}
2.3添加POST
//添加[POST]
@PostMapping(value = "/book")
public String addBook(String bookName) {
System.out.println("添加书籍 bookName== " + bookName);
return "success";
}
2.4删除DELETE
1. 默认情况下 <a href="user/book/600">删除指定id的书</a> 是get 2. 怎么样将 get 请求转成 springmvc 可以识别的 delete 就要考虑HiddenHttpMethodFilter机制
public static final String DEFAULT_METHOD_PARAM = "_method";
---------------------------------------------------
private static final List<String> ALLOWED_METHODS =
Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(),
HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
---------------------------------------------------
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);
}
}
}
3. 上面代码可以看到 HiddenHttpMethodFilter 过滤器可以对以Post方式提交的delete,put,patch进行转换,成springmvc 识别的 RequestMethod.DELETE / RequestMethod.PUT /... 4. 我们需要将 get <a href="user/book/600">删除指定id的书</a> 以post方式提交给后端handler, 这样过滤器还会生效 5. 我们可以同jquery来处理-引入jquery
<%-- 引入jquery--%>
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function () { //当页面加载完成后,就执行=> 如果你完全忘记,去回顾我们讲过的jquery
//给删除超链接绑定一个点击事件
$("#deleteBook").click(function (){
//alert("点击。。。。");
//我们自己定义给提交的行为
$("#hiddenForm").attr("action", this.href);//将超链接的值赋值给表单hiddenForm
$(":hidden").val("DELETE");//给它设置一个delete
$("#hiddenForm").submit();
return false; //改变点击超链接的行为, 不在提交
})
})
</script>
2.5修改[PUT]
@PutMapping("/book/{id}")
public String updateBook(@PathVariable("id") String id) {
System.out.println("修改书籍 id=" + id);
return "redirect:/user/success"; //重定向到一个没有指定 method 的 Handler 方法
}
2.6注意事项和细节说明

二.SpringMVC 映射请求数据
1.获取参数值
1.1说明
1.2解读@RequestParam(value="name", required=false)
1. 获取到超链接传递的数据 请求 http://localhost:8080/springmvc/vote/vote01?name=xx
2. @RequestParam 表示会接收提交的参数
3. value="name" 表示提交的参数名是name
4. required=false 表示该参数可以没有, 默认是true,表示必须有这个参数
5. 当我们使用了@RequestParam(value="name", required=false)后就请求的参数名和方法的形参名可以不一致
1.3实践
@RequestMapping(value = "/vote01")
public String test01(@RequestParam(value = "name", required = false) String username) {
System.out.println("得到的username= " + username);
//返回到一个结果
return "success";
}
孩子单纯的认为这个注解有点多此一举的感觉,[狗头]
2.获取 http 请求消息头
2.1说明:
3.之前我们在servlet中使用其他方法来获取,但是在这个里面我们就可以使用@RequestHeader("Http请求头字段")来获取
/**
* 需求: 获取http请求头信息, 获取到Accept-Encoding 和 Host
* 1. 这里涉及到前面讲过的http协议,小伙伴可以进行回顾
*
* @RequestHeader("Http请求头字段")
*/
@RequestMapping(value = "/vote02")
public String test02(@RequestHeader("Accept-Encoding") String ae,
@RequestHeader("Host") String host) {
System.out.println("Accept-Encoding= " + ae);
System.out.println("Host= " + host);
//返回到一个结果
return "success";
}
结果:
Accept-Encoding(是浏览器发给服务器,声明浏览器支持的编码类型)= gzip, deflate, br
Host= localhost:8080
3.获取 javabean 形式的数据
3.1使用场景说明
开发中,如何获取到 javaben 的数据,就是以前的 entity/pojo 对象数据
演示如果获取到提交数据->封装成java对象 @return 说明 1. 方法的形参用对应的类型来指定即可, SpringMVC会自动的进行封装 2. 如果自动的完成封装, 要求提交的数据,参数名和对象的字段名保持一致 3. 如果属性是对象,这里就是仍然是通过 字段名.字段名 比如Master [pet]即提交的数据 参数名 是 pet.id pet.name, 这就是级联操作 4. 如果提交的数据 的参数名和对象的字段名不匹配,则对象的属性值就是null 5. 小伙伴疑惑,怎么就封装成功[底层仍然是反射+注解..]
先创建两个Javabean文件
package com.hong.web.requestparam.entity;
/**
* @author 海绵hong
* @version 1.0
*/
public class Pet {
private Integer id;
private String name;
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;
}
@Override
public String toString() {
return "Pet{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
package com.hong.web.requestparam.entity;
/**
* @author 海绵hong
* @version 1.0
*/
public class Master {
private Integer id;
private String name;
private Pet pet;//对象的属性是另外一个对象[涉及级联]
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 +
'}';
}
}
handler类
@RequestMapping(value = "/vote03")
public String test03(Master master) {
System.out.println("master=" + master);
//返回结果
return "success";
}
jsp文件
<h1>添加主人信息</h1>
<!--
解读
1. 这是一个表单,表单的数据对应Master对象
2. 提交的数据参数名和对象的字段名一致即可
-->
<form action="vote/vote03" method="post">
主人号:<input type="text" name="id"><br>
主人名:<input type="text" name="name"><br>
宠物号:<input type="text" name="pet.id"><br>
宠物名:<input type="text" name="pet.name"><br>
<input type="submit" value="添加主人和宠物">
</form>
结果显示
使用注意事项
4.获取 servlet api
4.1应用实例
4.2演示实例
/**
* 使用servlet api, 来获取提交的数据
*
* @return
*/
@RequestMapping(value = "/vote04")
public String test04(HttpServletRequest request,
HttpServletResponse response,
HttpSession hs) {
//获取到session
//servlet原生的方式
HttpSession session = request.getSession();
System.out.println("session=" + session);
//注意:通过参数传入的 hs 和 通request.getSession() 得到的对象是
//同一个
System.out.println("hs= " + hs);
String username = request.getParameter("username");
String pwd = request.getParameter("pwd");
System.out.println("username= " + username);
System.out.println("pwd= " + pwd);
//返回结果
return "success";
}
<h1>演示 servlet api的使用 </h1>
<form action="vote/vote04" method="post">
用户名:<input type="text" name="username"><br>
密 码:<input type="password" name="pwd"><br>
<input type="submit" value="添加用户">
</form>
4.3使用注意事项
三.模型数据
1.模型数据处理-数据放入 request
1.1 需求分析

<%--
Created by IntelliJ IDEA.
User: 海绵hong
Version: 1.0
Filename: request_parameter
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>测试 模型数据</title>
</head>
<body>
<h1>添加主人信息</h1>
<form action="vote/vote05" method="post">
主人号:<input type="text" name="id"><br>
主人名:<input type="text" name="name"><br>
宠物号:<input type="text" name="pet.id"><br>
宠物名:<input type="text" name="pet.name"><br>
<input type="submit" value="添加主人和宠物">
</form>
<br/><hr/>
<h1>添加主人信息[测试 Map ]</h1>
<form action="vote/vote06" method="post">
主人号:<input type="text" name="id"><br>
主人名:<input type="text" name="name"><br>
宠物号:<input type="text" name="pet.id"><br>
宠物名:<input type="text" name="pet.name"><br>
<input type="submit" value="添加主人和宠物">
</form>
<br/><hr/>
<h1>添加主人信息[测试ModelAndView]</h1>
<form action="vote/vote07" method="post">
主人号:<input type="text" name="id"><br>
主人名:<input type="text" name="name"><br>
宠物号:<input type="text" name="pet.id"><br>
宠物名:<input type="text" name="pet.name"><br>
<input type="submit" value="添加主人和宠物">
</form>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: 海绵hong
Version: 1.0
Filename: vote05
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>vote_ok </title>
</head>
<body>
<h1>获取的的数据显示页面</h1>
<hr>
取出 request域的数据-通过前面讲解的el表达式来获取即可
<br>
address: ${requestScope.address}<br>
主人名字= ${requestScope.master.name}
主人id= ${requestScope.master.id}
宠物名字= ${requestScope.master.pet.name}
</html>
1.2方式 1: 通过 HttpServletRequest 放入 request 域
/**
* 解读
* 1. 演示将提交的数据->springmvc封装到java对象->springmvc 会自动的将其放入到request域
* 2. 这样我们就可以在跳转到的页面取出数据.
*
* @return
*/
@RequestMapping(value = "/vote05")
public String test05(Master master, HttpServletRequest request) {
//解读
//1. springmvc会自动把获取的model模型,放入到request域中,名字就是master
//2. 也可以手动将master放入到request
request.setAttribute("address", "beijing");
//3. 如果我们希望修改master的属性值
master.setName("nono");//request域中的值也会发生变化
//4. 分析一下springmvc默认存放对象到request域中,属性名是
// request域 ("master", master) 属性名是类名/类型名 首字母小写
//返回到一个结果
return "vote_ok";
}
request域 ("master", master) 属性名是类名/类型名 首字母小写
1.3方式 2: 通过请求的方法参数 Map<String,Object> 放入 request 域
/**
* 演示通过Map<String,Object> 设置数据到request域
*
* @return
*/
@RequestMapping(value = "/vote06")
public String test06(Master master, Map<String, Object> map) {
System.out.println("------test06-----");
//解读
//1. 需求是通过map对象,添加属性到request中
//2. 原理分析:springmvc会遍历map,然后将map的k-v, 存放到request域
map.put("address", "beijing...");
return "vote_ok";
}
1.4 方式 3: 通过返回 ModelAndView 对象 实现 request 域数据
/**
* 演示通过返回ModelAndView对象,将数据放入到request域
* @return
*/
@RequestMapping(value = "/vote07")
public ModelAndView test07(Master master) {
System.out.println("----test07----");
ModelAndView modelAndView = new ModelAndView();
//放入属性到modelAndView对象
modelAndView.addObject("address", "shanghai");
//modelAndView.addObject("master", null);
//可以把从数据库得到的数据->对象-》放入modelAndView[Service-dao-db]
//这里指定跳转的视图名称
modelAndView.setViewName("vote_ok");
//返回结果
return modelAndView;
}
5. 使用注意事项
2.模型数据处理-数据放入 session
1 .需求分析/图解
2.环境搭配
<br/><hr/>
<h1>添加主人信息[测试session]</h1>
<form action="vote/vote08" method="post">
主人号:<input type="text" name="id"><br>
主人名:<input type="text" name="name"><br>
宠物号:<input type="text" name="pet.id"><br>
宠物名:<input type="text" name="pet.name"><br>
<input type="submit" value="添加主人和宠物">
</form>
<hr>
取出 session域的数据 <br>
address: ${sessionScope.address}<br>
主人名字= ${sessionScope.master.name}
主人信息= ${sessionScope.master}
</body>
3.代码实现
/**
* 演示如何将数据设置到session域中
* @return
*/
@RequestMapping(value = "/vote08")
public String test08(Master master, HttpSession httpSession) {
System.out.println("----test08----");
//master对象是默认放在request域
//我们将master对象放入到session域
httpSession.setAttribute("master", master);
httpSession.setAttribute("address", "guangzhou");
return "vote_ok";//请求转发
}
3.@ModelAttribute 实现 prepare 方法(前置方法)
1 .应用实例
2.代码解读
/**
* 解读
* 1. 当Handler的方法被标识 @ModelAttribute,就视为一个前置方法
* 2. 当调用该Handler的其它的方法时,都会先执行该前置方法
* 3. 类似我们前面讲解Spring时,AOP的前置通知[底层是AOP机制]
* 4. prepareModel前置方法,会切入到其它方法前执行..
*/
@ModelAttribute
public void prepareModel(){
System.out.println("prepareModel()-----完成准备工作-----");
}
3.@ModelAttribute 最佳实践
四.视图和视图解析器
1.基本介绍
2.自定义视图
2.1 为什么需要自定义视图

2.2 自定义视图实例-代码实现
配置自定义视图解析器
<!-- 解读
1. 配置可以解析自定义的视图的解析器
2. BeanNameViewResolver 这个就是可以解析自定义视图的解析器
3. name="order" :表示给这个解析器设置优先级,
默认优先级很低 值 Integer.MAX_VALUE
4. 一般来说明,我们自己的视图解析优先级高,Order 值越小,优先级越高
-->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="99"></property>
</bean>
首先我们需要配置一个视图
<%--
Created by IntelliJ IDEA.
User: 海绵hong
Version: 1.0
Filename: view
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>自定义视图测试</title>
</head>
<body>
<h1>自定义视图测试</h1>
<a href="goods/buy">点击到自定义视图-</a><br/>
<a href="goods/order">测试在目标方法中指定请求转发或者重定向的页面-</a><br/>
</body>
</html>
由这个jsp跳转到handler
package com.hong.web.viewresolver;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author 海绵hong
* @version 1.0
*/
@RequestMapping("/goods")
@Controller
public class GoodsHandler {
@RequestMapping(value = "/buy")
public String buy() {
System.out.println("------buy()-----");
return "hongView";//待会再填写自定义视图名
}
}
因为这个handler的重定向,继续跳转到id=hspView的handler自定义视图中
最后指向my_view.jsp
<%--
Created by IntelliJ IDEA.
User: 海绵hong
Version: 1.0
Filename: my_view
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>my_view页面</title>
</head>
<h1>进入到my_view页面</h1>
<p>是从自定义视图来的..</p>
<body>
</body>
</html>
3.自定义视图工作流程小结
4.自定义视图-工作流程
4.目标方法直接指定转发或重定向
4.1使用实例

4.2代码演示
/**
* 演示直接指定要请求转发的或者是重定向的页面
* @return
*/
@RequestMapping(value = "/order")
public String order() {
System.out.println("=======order()=====");
//请求转发到 /WEB-INF/pages/my_view.jsp
//下面的 /WEB-INF/pages/my_view.jsp 被解析成 /springmvc/WEB-INF/pages/my_view.jsp
//return "forward:/WEB-INF/pages/my_view.jsp";
//return "forward:/aaa/bbb/ok.jsp";
//直接指定要重定向的页面
//1. 对于重定向来说,不能重定向到 /WEB-INF/ 目录下
//2. redirect 关键字,表示进行重定向
//3. /login.jsp 在服务器解析 /springmvc/login.jsp
return "redirect:/login.jsp";
// /WEB-INF/pages/my_view.jsp 被解析 /springmvc/WEB-INF/pages/my_view.jsp
//return "redirect:/WEB-INF/pages/my_view.jsp";
}
直接指定要重定向的页面 1. 对于重定向来说,不能重定向到 /WEB-INF/ 目录下 2. redirect 关键字,表示进行重定向

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)