SpringMVC整理

目录

1 SpringMVC介绍

2 SpringMVC执行流程

3 @RequestMapping

4 Rest-优雅的url请求风格

5 SpringMVC映射请求数据

6 模型数据

7 视图和视图解析器

8 验证以及格式化

8 数据格式化

10 中文乱码处理

11 处理json和HttpMessageConverter

12 SpringMVC文件下载和上传

13 自定义拦截器

14 异常处理

15 SpringMVC执行流程-源码剖析

16 Postman的使用

1 SpringMVC介绍

  • SpringMVC 是 WEB 层框架【 SpringMVC 接管了 Web 层组件, 比如控制器, 视 图, 视图解析, 返回给用户的数据格式, 同时支持 MVC 的开发模式/开发架构】
  • SpringMVC 通过注解,让 POJO 成为控制器,不需要继承类或者实现接口
  •  SpringMVC 采用低耦合的组件设计方式,具有更好扩展和灵活性.
  •  支持 REST 格式的 URL 请求.
  •  SpringMVC 是基于 Spring 的, 也就是 SpringMVC 是在 Spring 基础上的。SpringMVC 的核 心包 spring-webmvc-xx.jar 和 spring-web-xx.jar

2 SpringMVC执行流程

3 @RequestMapping

@RequestMapping 注解可以指定控制器/处理器的某个方法的请求的 url

说明: @RequestMapping 注解可以修饰方法,还可以修饰类 当同时修饰类和方法时, 请求的 url 就是组合 /类请求值/方法请求值

说明: @RequestMapping 还可以指定请求的方式(post/get/put/delete..), 请求的方式需 要和指定的一样,否则报错 2. SpringMVC 控制器默认支持GET和POST两种方式, 也就是你不指定 method , 可以接收 GET 和 POST 请求

@RequestMapping 可指定 params 和 headers 支持简单表达式 1. param1: 表示请求必须包含名为 param1 的请求参数 2. !=param1: 表示请求不能包含名为 param1 的请求参数 3. param1 != value1: 表示请求包含名为 param1 的请求参数,但其值不能为 value1 4. {"param1=value1", "param2"}: 请求必须包含名为 param1 和 param2 的两个请求参数, 且 param1 参数的值必须为 value1

@RequestMapping 支持 Ant 风格资源地址 1. ?:匹配文件名中的一个字符 2. *:匹配文件名中的任意字符 3. **:匹配多层路径 4. Ant 风格的 url 地址举例 /user/*/createUser: 匹配 /user/aaa/createUser、/user/bbb/createUser 等 URL /user/**/createUser: 匹配 /user/createUser、/user/aaa/bbb/createUser 等 URL /user/createUser??: 匹配 /user/createUseraa、/user/createUserbb 等 URL

5 @RequestMapping 可配合 @PathVariable 映射 URL 绑定的占位符 ;这样就不需要在 url 地址上带参数名了,更加的简洁明了,/book/100

@Controller
@RequestMapping("/book")
public class BookHandler {
    @RequestMapping(value = "/{id}",method = RequestMethod.GET)
    public String getBook(@PathVariable("id") String id) {
        //  /xx/参数值/参数值;可以用占位符配合PathVariable来获取
        System.out.println("查询书籍 id=" + id );
        return "success";
    }}

4 Rest-优雅的url请求风格

1. REST:即 Representational State Transfer。(资源)表现层状态转化。是目前流行的请求方 式。它结构清晰, 很多网站采用

2. HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应 四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用 韩顺平 Java 工程师 来删除资源。

3. 实例 传统的请求方法: getBook?id=1 GET    delete?id=1 GET    update POST     add POST

4. 说明: 传统的 url 是通过参数来说明 crud 的类型,rest 是通过 get/post/put/delete 来说 明 crud 的类型

● REST 的核心过滤器

    当前的浏览器只支持 post/get 请求,因此为了得到 put/delete 的请求方式需要使用 Spring 提供的 HiddenHttpMethodFilter 过滤器进行转换.

    HiddenHttpMethodFilter:浏览器 form 表单只支持 GET 与 POST 请求,而 DELETE、PUT 等 method 并不支持,Spring 添加了一个过滤器,可以将这些请求转换为标准的 http 方 法,使得支持 GET、POST、PUT 与 DELETE 请求

 HiddenHttpMethodFilter 能对 post 请求方式进行转换,因此我们需要特别的注意这一点

 这个过滤器需要在 web.xml 中配置

<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配置

<!-- 加入两个常规配置 -->
<!-- 能支持 SpringMVC 高级功能,比如 JSR303 校验,映射动态请求 -->
<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>
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function () {
$("#deleteBook").click(function () {
alert("ok");
var href = this.href;
$("#hiddenForm").attr("action", href);
$(":hidden").val("DELETE");
$("#hiddenForm").submit();//这里就是提交删除请求了
//这里必须返回 false,否则会提交两次
return false;
});
})
</script>
</head>
<body>
<h3>Rest 风格的 crud 操作案例</h3>
<br><hr>
<h3>rest 风格的 url 查询书籍[get]</h3>
<a href="user/book/100">点击查询书籍</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>
<!-- 1. 这里我们需要将删除方式(get)转成 delete 的方式,需要使用过滤器和 jquery 来完成
2. name="_method" 名字需要写成 _method 因为后台的 HiddenHttpMethodFilter
就是按这个名字来获取 hidden 域的值,从而进行请求转换的. -->
<a href="user/book/100" 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/100" method="post">
<input type="hidden" name="_method" value="PUT">
<input type="submit" value="修改书籍~">
</form>
</body>
</html>

后端代码:

@RequestMapping(value = "/user")
@Controller
public class BookHandler {
//查询[GET]
public String getBook(@PathVariable("id") String id) {
System.out.println("查询书籍 id=" + id );

return "success";
}
//添加[POST]
public String addBook(String bookName) {
System.out.println("添加书籍 bookName== " + bookName);
return "success";
}
//删除[DELETE]
public String delBook(@PathVariable("id") String id) {
System.out.println("删除书籍 id= " + id);
//return "success"; [如果 这样返 回会报错 JSPs only permit GET POST or
HEAD]
return "redirect:/user/success"; //重定向到一个没有指定 method 的 Handler 方
法
}
//修改[PUT]
public String updateBook(@PathVariable("id") String id) {
System.out.println("修改书籍 id=" + id);
return "redirect:/user/success"; 
//重定向到一个没有指定 method 的 Handler 方法
}
@RequestMapping(value = "/success")
public String successGenecal() {
return "success"; //由该方法 转发到 success.jsp 页面
}
}

5 SpringMVC映射请求数据

@RequestMapping("/vote")
@Controller
public class VoteHandler {
//获取到超链接传递的数据
/**
*  @RequestParam(value="name", required=false)
* 1.@RequestParam : 表示说明一个接受到的参数
* 2.value="name" : 接收的参数名是 name
* 3.required=false : 表示该参数可以有,也可以没有 ,如果 required=true,表示必须传递该
参数. * 默认是 required=true
*/
@RequestMapping(value = "/vote01")
public String test01(@RequestParam(value = "name", required = false)
String username) {
System.out.println("得到的 username= " + username);
//返回到一个结果
return "success";
}
}
/**
* 获取 http 请求头信息
* @param ae
* @param host
* @return
*/
@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";
}

获取javabean数据

后端代码:

@RequestMapping(value = "/vote03")
public String test03(Master master) {
System.out.println("主人信息= " + master);
//返回结果
return "success";
}

前端代码:

<!-- 
1. 这里的字段名称和对象的属性名保持一致,级联添加属性也是一样保持名字对应关系
2. 如果只是添加主人信息,则去掉宠物号和宠物名输入框即可 ,pet 为 null-->
<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>

获取servlet

/**
* 获取 servlet api
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/vote04")
public String test04(HttpServletRequest request, HttpServletResponse response) {
System.out.println("name= " + request.getParameter("username"));
System.out.println("pwd= " + request.getParameter("pwd"));
//返回结果
return "success";
}

6 模型数据

开发中, 控制器/处理器中获取的数据如何放入 request 域,然后在前端(VUE/JSP/...)取出显 示

方式 1: 通过 HttpServletRequest 放入 request 域

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>测试 模型数据</title>
</head>
<body>
<h1>添加主人信息</h1>
<!-- 
1. 这里的字段名称和对象的属性名保持一致,级联添加属性也是一样保持名字对应关系
2. 如果只是添加主人信息,则去掉宠物号和宠物名输入框即可 ,pet 为 null-->
<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>
</body>
</html>
/**
* 获取模型数据 master, 并放入到 request
* @param master
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/vote05")
public String test05(Master master, HttpServletRequest request, HttpServletResponse response) {
//1. springmvc 会自动把获取的 model 模型,放入到 request 域中,名字就是 master
//2. 也可以手动将 master 放入到 request
//request.setAttribute("master", master);
request.setAttribute("address", "北京");
//返回到一个结果
return "vote_ok";
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>vote_ok 页面</title>
</head>
<body>
<h1>获取的的数据显示页面</h1>
<hr>
取出 request 域的数据
<br>
address: ${address }<br>
主人名字= ${requestScope.master.name }
主人信息= ${requestScope.master }
宠物名字= ${requestScope.master.pet.name }
</body>
</html>

方式 2:数据放入session

@RequestMapping(value = "/vote08")
public String test08(Map<String, Object> map, Master master, HttpSession session) {
System.out.println("======test08()======");
map.put("address", "guangzhou");
//在 session 域也放入 master 对象
session.setAttribute("master2", master);
return "vote_ok";
}

修改vote_ok:主人名字= ${sessionScope.master2.name } 主人信息= ${sessionScope.master2 }

@ModelAttribute 实现 prepare 方法:

开发中,有时需要使用某个前置方法(比如 prepareXxx(), 方法名由程序员定)给目标方法准 备一个模型对象

  • @ModelAttribute 注解可以实现 这样的需求
  • 在某个方法上,增加了@ModelAttribute 注解后
  •  那么在调用该 Handler 的任何一个方法时,都会先调用这个方法
  • @ModelAttribute 最佳实践 : 修改用户信息(就是经典的使用这种机制的应用),流程如下: 1. 在修改前,在前置方法中从数据库查出这个用户 2. 在修改方法(目标方法)中,可以使用前置方法从数据库查询的用户 3. 如果表单中对用户的某个属性修改了,则以新的数据为准,如果没有修改,则以数据库 的信息为准,比如,用户的某个属性不能修改,就保持原来的值

7 视图和视图解析器

  • 在默认情况下,我们都是返回默认的视图, 然后这个返回的视图交由 SpringMVC 的 InternalResourceViewResolver 视图处理器来处理的
  • 在实际开发中,我们有时需要自定义视图,这样可以满足更多更复杂的需求.
<!-- 
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>
@RequestMapping("/goods")
@Controller
public class GoodsHandler {
@RequestMapping(value = "/buy")
public String buy() {
System.out.println("=======buy()=====");
return "myView";
}
}
/**
* 
* 1. @Component 表示 该视图会被加载到容器,id 为 myView
*/
@Component(value="myView")
public class MyView extends AbstractView {
@Override
protected void renderMergedOutputModel(Map<String, Object> arg0, HttpServletRequest arg1, HttpServletResponse arg2) throws Exception
{
System.out.println("进入到自己的视图");
// 这里我们自己来确定到哪个页面去,默认的视图解析机制就无效
arg1.getRequestDispatcher("/WEB-INF/pages/my_view.jsp").forward(arg1, arg2);
}
}

8 验证以及格式化

  • 对输入的数据(比如表单数据),进行必要的验证,并给出相应的提示信息。
  • 对于验证表单数据,springMVC 提供了很多实用的注解, 这些注解由 JSR 303 验证框架提 供.

● JSR 303 验证框架

  •  JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 中
  •  JSR 303 通过在 Bean 属性上标注类似于 @NotNull、@Max 等标准的注解指定校验规则, 并通过标准的验证接口对 Bean 进行验证
  •  JSR 303 提供的基本验证注解有:

 

 

使用:

 

//处理添加,根据请求的方法来确定
@RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(@Valid Monster monster, Errors errors, Map<String, Object> map) {
System.out.println("email= " + email);
System.out.println("monster= " + monster);
if (errors.hasErrors()) {
System.out.println("验证出错!");
for (ObjectError error : errors.getAllErrors()) {
System.out.println(error);
}
//返回添加界面
return "/datavalid/monster_addUI";
//return "forward:/addMonsterUI";
}
return "datavalid/success";
}
  • 1. 在需要验证的 Javabean/POJO 的字段上加上相应的验证注解.
  • 2. 目标方法上,在 JavaBean/POJO 类型的参数前, 添加 @Valid 注解. 告知 SpringMVC 该 bean 是需要验证的
  • 3. 在 @Valid 注解之后, 添加一个 Errors 或 BindingResult 类型的参数, 可以获取到验证 的错误信息
  • 4. 需要使用 标签来显示错误消息, 这个标签, 需要写在 标签内生效.
  • 5. 错误消息的国际化文件 i18n.properties , 中文需要是 Unicode 编码,使用工具转码. √ 格式: 验证规则.表单 modelAttribute 值.属性名=消息信息 √ NotEmpty.monster.name=\u540D\u5B57\u4E0D\u80FD\u4E3A\u7A7A √ typeMismatch.monster.age=\u7C7B\u578B\u4E0D\u5339\u914D 5.
  • 注解@NotNull 和 @NotEmpty 的区别说明
  • 1) 查看源码可以知道 : @NotEmpty Asserts that the annotated string, collection, map or array is not {@code null} or empty.
  • 2) 查看源码可以知道 : @NotNull * The annotated element must not be {@code null}.Accepts any type.
  • 3) 如果是字符串验证空, 建议使用 @NotEmpty

取消某个属性的绑定:在默认情况下,表单提交的数据都会和 pojo 类型的 javabean 属性绑定,如果 程序员在开发中,希望取消某个属性的绑定,也就是说,不希望接收到某个表单对应的属 性的值,则可以通过 @InitBinder 注解取消绑定

 

8 数据格式化

10 中文乱码处理

自定义:

public class MyCharacterFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse
servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}

配置web.xml

<!-- 
1. 配置中文乱码处理过滤器
2. 配置到最前面
-->
<filter>
<filter-name>myCharacterFilter</filter-name>
<filter-class>com.hspedu.web.filter.MyCharacterFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myCharacterFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

11 处理json和HttpMessageConverter<T>

12 SpringMVC文件下载和上传

13 自定义拦截器

14 异常处理

15 SpringMVC执行流程-源码剖析

16 Postman的使用

后面的懒得整理了,省略10000w字

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值