SpringMvc教程
1.基础
1.mvc的流程图
将应用程序分为Controller、Model、View三层。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z85RYLQY-1618990797969)(C:\Users\31797\Desktop\1.png)]
2.spring MVC的核心组件
-
DispatcherServlet:前置控制器,是整个流程控制的核心,控制其他组件,降低耦合性。
-
Hander:处理器,完成具体业务逻辑,相当于Servlet或Action
-
HandlerMapping:DispatchServlet接受请求之后,通过HandlerMapping将不同不同的请求映射到不同的Hander
-
HnaderInterceptor:处理器拦截口,是一个接口,完成一些拦截操作。
-
HandlerExecutionChain:处理器执行链,包括两部分:Handler和 HanderInterceptor
-
HanderAdaper:处理器适配器,Handler执行任前,需要一系列操作,包括数据转换,表单验证,将表单数据封装到JavaBean等。这些HanderAdapter都可以完成。DispatcherServlet通过HandlerAdapter执行不同的Handler。
-
ModelAndView:装载了模型数据和视图信息,作为Handler的处理结果,返回给DispacherServlet。
-
ViewResolver:视图解析器,DispatcheServlet通过它将逻辑视图变为物理视图,最终将渲染结果传给客户端。
3.spring mvc工作流程
- 客户端请求被DispatcherServlet接受
- 通过HandlerManpping映射到Handler
- 生成Handler和HandlerInterceptor
- Handler和HandlerInterceptor以HandlerExecutionChain的形式一并返回给DispatcherServlet.
- DispatcherServlet通过HanderAdapter调用Handler的方法完成业务逻辑处理
- Handler返回一个ModerAndView给DispatcherServlet。
- DispatchServlet将获取的ModelAndView对象传给ViewResovler视图解析器,讲逻辑视图转为物理视图View。
- ViewResovler返回一个View给DispatcherServlet。
- DispatcherServlet根据View进行视图渲染(将模型数据Model填充到视图View中)。
- DispatcherServlet将渲染的结果相应给客户端
4.spring mvc的特点
Spring MVC流程非常复杂,实际开发中很简单。真正处理的只有Handler、View.
5.如何使用
-
创建Maven工程,pom.xml
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r1Bbfjr6-1618990797978)(C:\Users\31797\AppData\Roaming\Typora\typora-user-images\1618751669300.png)]
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.0.11.RELEASE</version> </dependency>
第一次要加载才能正常显示
-
在web.xml中配置DispacherServlet。
要在resources下创建springmvc.xml文件
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <!-- 让spring读取springmvc的配置文件--> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <!-- 拦截所有请求--> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-
spring.xml进行配置
<?xml version='1.0' encoding='UTF-8' ?> <!-- was: <?xml version="1.0" encoding="UTF-8"?> --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 自动扫描,交给aoc管理--> <context:component-scan base-package="com.xxx"></context:component-scan> <!-- 视图解析器--> <!-- 把逻辑视图转化为物理视图--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 前缀是根目录,表示webapp的根目录--> <property name="prefix" value="/"></property> <!-- 表示后缀--> <property name="suffix" value=".jsp"></property> </bean> </beans>
-
创建Handler(控制器)
package com.xxx.controller; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; //交给aoc容器管理 //@Component,没有控制器的功能 @Controller //区别不同的Handler @RequestMapping("/user") public class HelloHandler { @RequestMapping("/index") public String index(){ System.out.println("wwwwwwww"); //逻辑视图 return "index"; } }
2.Spring Mvc注解
1.@RequestMapping
Spring Mvc通过@RequestMapping注解将URL请求和业务方法映射,在Handler的类定义及方法定义处都可以添加@RequstMapping,在类定义处添加,相当于客户端多了一从访问路径。
2.@Controller
@Controller在类的定义处添加,将该类交给IoC容器管理(结合springmvc.xml的自动扫描配置使用),同时使其成为一个控制器,可以接受客户端请求。
package com.xxx.controller;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
//交给aoc容器管理
//@Component,没有控制器的功能
@Controller
//区别不同的Handler
@RequestMapping("/user")
public class HelloHandler {
@RequestMapping("/index")
public String index(){
System.out.println("wwwwwwww");
//逻辑视图
return "index";
}
}
3.@RequestMapping相关参数
1.value:指定URl的实际地址,是RequestMapping的默认值。
@RequestMapping("/index")
public String index(){
System.out.println("wwwwwwww");
//逻辑视图
return "index";
}
等于
@RequestMapping(value="/index")
public String index(){
System.out.println("wwwwwwww");
//逻辑视图
return "index";
}
2.method:指定请求的method类型:get、post、put、delete
@RequestMapping(value = "/index",method = RequestMethod.GET)
public String index(){
System.out.println("wwwwwwww");
//逻辑视图
return "index";
}
上述代码表示index方法只能接受get请求
405错误:方法不被允许
不加就没有限制
3.params:指定参数中必须包含某些参数,否则无法调用该方法。
@RequestMapping(value = "/index",method = RequestMethod.GET,params{"name","id=10"})
public String index(){
System.out.println("wwwwwwww");
//逻辑视图
return "index";
}
以上代码表示请求参数必须包含name和id两个参数,同时id的值必须是10。
在形参列表中通过添加**@RequsetParam**注解完成HTTP请求参数与业务方法的映射。
@RequestMapping(value = "/index",method = RequestMethod.GET,params {"name","id=12"})
public String index(@RequestParam("name") String ww,int id){
System.out.println(ww+":"+id);
System.out.println("wwwwwwww");
//逻辑视图
return "index";
}
上述代码表示将请求代码的参数name和id分别赋给了ww和id,并且自动完成了数据类型的转换,将“10”转化为int的10,再赋给id,这些工作都是由HandlerAdapter完成的。
4.Spring MVC也支持RESTful风格的URL。
传统风格:http://localhost:8080/user/index?name=zhangsan&id=10
RESTful:http://localhost:8080/user/index/zhangsan/10
@RequestMapping("/rest/{name}/{id}")
public String rest(@PathVariable("name") String name,@PathVariable("id") int id){
System.out.println(name);
System.out.println(id);
return "index";
}
通过@PathVarible注解完成请求参数与形参的映射,在RESTful风格中,这个注解必须存在,否则就无法完成映射,这一点与传统风格不同。
5.映射Cookie
Spring MVC通过映射可以直接在业务方法中获取Cookie的值。
@RequestMapping("/cookie")
public String cookie(@CookieValue(value = "JSESSIONID") String sessionId) {
System.out.println(sessionId);
return "index";
}
上述代码,必须通过@CookieValue(value=“JESSIONID”)这个注解来映射,否则取不到相应的值。
3.数据绑定(普通)
1.使用JavaBean绑定参数
Spring MVC会根据请求参数名和JavaBean属性名进行匹配,自动为对象填充属性值,同时支持级联属性(对象中包含对象)
Address
package com.xxx.entity;
import lombok.Data;
@Data
public class Address {
private String value;
}
User类
package com.xxx.entity;
import lombok.Data;
//@Data注解,可以不用写getter与setter方法,需要添加依赖
@Data
public class User {
private long id;
private String name;
private Address address;
}
register.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/user/save" method="post">
<%-- name:把这里的值与User中相匹配,必须对应--%>
用户id:<input type="text" name="id"/><br/>
用户名:<input type="text" name="name"/><br/>
<%-- address是个对象,要做级联操作--%>
用户地址:<input type="text" name="address.value"/><br/>
<input type="submit" value="注册">
</form>
</body>
</html>
如果出现中文乱码问题,在web.xml中添加Spring MVC自带的过滤器即可
<!-- 中文乱码要加过滤器-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 指定编码格式-->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<!-- 加一个映射,拦截所有请求-->
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在pom.xml添加依赖,实现@Data这个注解
<!-- @Data注解,可以不用写getter与setter方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
<scope>provided</scope>
</dependency>
2.JSP页面的转发和重定向
1.区别
- 转发:服务器跳转,地址栏不变,一次请求,可以取出存在请求里的数据。
- 重定向:客户端跳转,地址栏改变,两次请求,不可以存在请求里的数据。
Spring MVC默认是转发的模式
2.转发
@RequestMapping("/forward")
public String forward(){
return "forward:/index.jsp";
// 二者等价
// return "index";
}
3.重定向
@RequestMapping("/redirect")
public String redirect(){
return "redirect:/index.jsp";
}
4.Spring MVC数据绑定(全面)
1.概念
数据绑定:在后端的业务中直接获取客户端HTTP请求中的参数,将请求参数映射到业务方法的形参中,Spring MVC中的数据绑定是由HandlerAdapter来完成的。
2.基本数据类型
@RequestMapping("/baseType")
// 直接返回id值,而不是视图
@ResponseBody
public String baseType(int id){
return id+"";
}
@ResponseBody表示Spring MVC会直接将业务方法的返回值响应给客户端,如果不加@ResponseBody注解,Spring MVC会将业务方法的返回值传递给DispatcherServlet,再由DispatcherServlet调用ViewResolver对返回值进行解析,映射JSP资源。
3.包装
@RequestMapping("/packageType")
@ResponseBody
public String packageType(Integer id){
return id+"";
}
包装类可以接受null,当Http请求没有参数时,使用包装类定义形参的数据类型,程序不会抛异常。
4.@RequestParam
@RequestMapping("/packageType")
@ResponseBody
// @RequestParam:手动匹配,让请求参数和形参列表匹配
public String packageType(@RequestParam(value = "num",required = true,defaultValue = "0") Integer id){
return id+"";
}
1.value:
将HTTP请求中的名为num的参数传给形参id
2.requried:
设置num为必填项,true表示必填,false表示非必填,可省略。
3.default=“0”
如果HTTP请求参数没有num参数,默认值为0
5.数组
//可省略多个@ResponseBody,直接认为是值,返回的是model
@RestController
@RequestMapping("/data")
public class DataBindHandler {
@RequestMapping("/array")
public String array(String[] name){
String str = Arrays.toString(name);
return str;
}
}
@restController
表示该控制器会直接将业务方法的返回值响应给客户端,不进行视图解析
@Controller
表示该控制器的每一个业务方法的返回值交给视图解析器进行解析,如果只需要将数据响应给客户端,而不需要视图解析,则需要在对应的业务方法定义处添加**@ResponseBody**。
//可省略多个@ResponseBody,直接认为是值,返回的是model
@RestController
@RequestMapping("/data")
public class DataBindHandler {
@RequestMapping("/array")
public String array(String[] name){
String str = Arrays.toString(name);
return str;
}
}
等于
@Controller
@RequestMapping("/data")
public class DataBindHandler {
@RequestMapping("/array")
@ResponseBody
public String array(String[] name){
String str = Arrays.toString(name);
return str;
}
}
6.集合 List
Spring MVC不支持对List类型的直接转化,需要对List进行包装。(mvc不支持对对象赋值,只能给对象的属相赋值)
-
集合分装类
import lombok.Data; import java.util.List; @Data public class UserList { private List<User> users; public List<User> getUsers() { return users; } public void setUsers(List<User> users) { this.users = users; } }
-
addList.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form action="/data/list" method="post"> <%--只能和属性映射,不能和list映射--%> 用户1编号:<input type="text" name="users[0].id"/><br/> 用户1名称:<input type="text" name="users[0].name"/><br/> 用户2编号:<input type="text" name="users[1].id"/><br/> 用户2名称:<input type="text" name="users[1].name"/><br/> 用户3编号:<input type="text" name="users[2].id"/><br/> 用户3名称:<input type="text" name="users[2].name"/><br/> <input type="submit" value="提交"/> </form> </body> </html>
-
业务方法
@RequestMapping("/list") public String list(UserList userList){ StringBuffer str = new StringBuffer(); for (User user:userList.getUsers()) { str.append(user); } return str.toString(); }
-
处理@responseBody中文乱码
在spring mvc.xml中配置消息转换器
<mvc:annotation-driven> <!-- 消息转换器,在responseBody传值出现乱码时,需要加这个--> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes" value="text/html;charset=UTF-8"> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
7.map集合
-
自定义封装类
package com.xxx.entity; import lombok.Data; import java.util.Map; @Data public class UserMap { private Map<String,User> users; public Map<String, User> getUsers() { return users; } public void setUsers(Map<String, User> users) { this.users = users; } }
可以不加get和set方法,但必须要下载lombox插件,和配置相关依赖。
-
业务方法
@RequestMapping("/map") public String map(UserMap userMap){ StringBuffer str = new StringBuffer(); for (String key: userMap.getUsers().keySet()) { User user = userMap.getUsers().get(key); str.append(user); } return str.toString(); }
-
addMap.jsp
<form action="/data/map" method="post"> <%-- key值随便填 它把id和name取出来封装为一个user,再把user放在map中,并取名为key(a,b,c)--%> 用户1编号:<input type="text" name="users['a'].id"/><br/> 用户1名称:<input type="text" name="users['a'].name"/><br/> 用户2编号:<input type="text" name="users['b'].id"/><br/> 用户2名称:<input type="text" name="users['b'].name"/><br/> 用户3编号:<input type="text" name="users['c'].id"/><br/> 用户3名称:<input type="text" name="users['c'].name"/><br/> <input type="submit" value="提交"/> </form>
8.json
客户端放送了Json格式字符串,直接通过Spring MVC绑定到业务方法中
-
处理Spring MVC无法加载静态资源,在web.xml中配置即可
<!--spring mvc无法加载静态资源的处理--> <!--js请求不被拦截,不会交给dispatcherServlet处理--> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping>
-
json.jsp代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <script src="js/jquery-3.6.0.min.js"></script> </head> <body> <script> $(function () { var user = { "id":1, "name":"张三" }; $.ajax({ //要请求的后台地址 url:"/data/json", //把user转化为json格式 data:JSON.stringify(user), //发送的请求 type:"POST", //字符乱码 contentType:"application/json;charset=UTF-8", //返回的格式 dataType:"JSON", //回调函数,data指的是返回的数据 success:function (data) { alert(data.id+"--"+data.name); } }); }) </script> </body> </html>
-
业务代码
@RequestMapping("/json") //RequestBody:把客户端(前端)的数据(json)给我,然后赋给形参user(java对象),请求 //ResponseBody:作响应的时候,把数据作为json格式返回给客户端 //body与json相关 public User json(@RequestBody User user){ System.out.println(user); user.setId(6); user.setName("张六"); return user; }
Spring MVC中的JSON和JavaBean的转换需要借助fastjson,需要在pom.xml引入相关依赖。
<!-- 把json转化为java对象--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.32</version> </dependency>
同时,要在springmvc.xml中添加fastjson的配置
<mvc:annotation-driven> <!-- 消息转换器,在responseBody传值出现乱码时,需要加这个--> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes" value="text/html;charset=UTF-8"> </property> </bean> <!--配置fastjson--> <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"> </bean> </mvc:message-converters> </mvc:annotation-driven>
5.Spring MVC数据解析
1.JSP四大作用域对应的内置对象
- pageContent
- request
- session
- appication
模型数据 的绑定是由ViewResolver来完成的,实际开发中,我们需要添加模型数据再交给ViewResovler来绑定。
Spring MVC提供了以下几种方式来添加模型数据:
- Map
- Model
- ModelAndView
- @SessionAttribute
- @ModelAttribute
2.request中添加
1.Map
- 业务代码:
@RequestMapping("/map")
public String map(Map<String,User> map){
User user = new User();
user.setId(1);
user.setName("张三");
//把user加入域对象中,在jsp里,从域对象中进行解析
//map会自动传到视图里,并且放到request里,所以可以直接去取
map.put("user",user);
//把视图展示出来
return "view";
};
-
view.jsp代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%--不忽略el表达式,就对el表达式进行解析--%> <%@ page isELIgnored="false"%> <html> <head> <title>Title</title> </head> <body> <%--通过el表达式直接从作用域里取--%> ${requestScope.user}; </body> </html>
2.Model
-
业务代码:
@RequestMapping("/model") public String model(Model model){ User user = new User(); user.setId(1); user.setName("张三"); //把键值对存在request中 model.addAttribute("user",user); return "view"; }
3.ModelAndView
一共8种,但推荐3种,后面的几种写复杂了。
//推荐
@RequestMapping("/modelAndView")
public ModelAndView modelAndView(){
User user = new User();
user.setId(1);
user.setName("张三");
ModelAndView modelAndView = new ModelAndView();
//向modelAndView添加模型数据
modelAndView.addObject("user",user);
//向modelAndView添加视图信息名称
modelAndView.setViewName("view");
return modelAndView;
}
@RequestMapping("/modelAndView2")
public ModelAndView modelAndView2(){
User user = new User();
user.setId(1);
user.setName("张三");
ModelAndView modelAndView = new ModelAndView();
//向modelAndView添加模型数据
modelAndView.addObject("user",user);
//向modelAndView添加视图信息名称
//写的是完整的物理视图路径
View view = new InternalResourceView("/view.jsp");
modelAndView.setView(view);
return modelAndView;
}
//推荐
@RequestMapping("/modelAndView3")
public ModelAndView modelAndView3(){
User user = new User();
user.setId(1);
user.setName("张三");
//直接在构造方法中添加视图信息
ModelAndView modelAndView = new ModelAndView("view");
//向modelAndView添加模型数据
modelAndView.addObject("user",user);
return modelAndView;
}
@RequestMapping("/modelAndView4")
public ModelAndView modelAndView4(){
User user = new User();
user.setId(1);
user.setName("张三");
View view = new InternalResourceView("/view.jsp");
//直接在构造方法中添加视图信息
ModelAndView modelAndView = new ModelAndView(view);
//向modelAndView添加模型数据
modelAndView.addObject("user",user);
return modelAndView;
}
@RequestMapping("/modelAndView5")
public ModelAndView modelAndView5(){
User user = new User();
user.setId(1);
user.setName("张三");
Map<String,User> map = new HashMap<>();
map.put("user",user);
//直接在构造方法中添加视图信息
ModelAndView modelAndView = new ModelAndView("view",map);
return modelAndView;
}
@RequestMapping("/modelAndView6")
public ModelAndView modelAndView6(){
User user = new User();
user.setId(1);
user.setName("张三");
Map<String,User> map = new HashMap<>();
map.put("user",user);
View view = new InternalResourceView("/view.jsp");
//直接在构造方法中添加视图信息
ModelAndView modelAndView = new ModelAndView(view,map);
return modelAndView;
}
//推荐
@RequestMapping("/modelAndView7")
public ModelAndView modelAndView7(){
User user = new User();
user.setId(1);
user.setName("张三");
//直接在构造方法中视图和数据模型,第一个是视图,第二、三个是数据,第二个是key值
ModelAndView modelAndView = new ModelAndView("view","user",user);
return modelAndView;
}
@RequestMapping("/modelAndView8")
public ModelAndView modelAndView8(){
User user = new User();
user.setId(1);
user.setName("张三");
View view = new InternalResourceView("/view.jsp");
//直接在构造方法中视图和数据模型,第一个是视图,第二、三个是数据,第二个是key值
ModelAndView modelAndView = new ModelAndView(view,"user",user);
return modelAndView;
}
4.HttpServletRequest
- 业务代码
@RequestMapping("/request")
public String request(HttpServletRequest request){
User user = new User();
user.setId(1);
user.setName("张三");
//原生方式
request.setAttribute("user",user);
return "view";
}
-
需要添加servlet的相关依赖
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency>
5.@ModelAttribute
-
定义一个方法,该方法专门用来返回要填充到数据模型的的对象
// 优先业务方法执行,会向request中添加对象。 @ModelAttribute public User getUser(){ User user = new User(); user.setId(1); user.setName("张三"); return user; }
等价于
@ModelAttribute public void getUser(Map<String,User> map){ User user = new User(); user.setId(1); user.setName("张三"); //手动添加模型数据 map.put("user",user); }
-
业务方法中无需再处理模型数据,只需要返回视图即可。
@RequestMapping("/modelAttribute") public String modelAttribute(){ return "view"; }
3.Session中添加数据
1.使用原生的servlet api
@RequestMapping("/session")
public String session(HttpServletRequest request){
//从request中获得session
HttpSession session = request.getSession();
User user = new User();
user.setId(1);
user.setName("张三");
session.setAttribute("user",user);
return "view";
}
@RequestMapping("/session2")
//框架自动创建session对象
public String session2(HttpSession session){
User user = new User();
user.setId(1);
user.setName("张三");
session.setAttribute("user",user);
return "view";
}
2.通过SessionAttribute()
- 名字
@SessionAttributes(value = "user")
//多个
@SessionAttributes(value = {"user","address"})
public class ViewHandler {}
对于ViewHandler中所有业务方法,只要向request中添加key=“user”、key=“address”的对象时,Spring MVC会自动将数据添加到session中,保存key不变。
- 类型
//通过的是类型
@SessionAttributes(types = User.class)
@SessionAttributes(types ={User.class, Address.class})
public class ViewHandler {}
对于ViewHandler中所有业务方法,只要向request中添加User,Address的对象时,Spring MVC会自动将数据添加到session中,保存key不变。
4.application
@RequestMapping("/application")
public String application(HttpServletRequest request){
//从request中获得application
ServletContext application = request.getServletContext();
User user = new User();
user.setId(1);
user.setName("张三");
application.setAttribute("user",user);
return "view";
}
6.Spring MVC自定义的数据转换器
数据转换器是指将客户端HTTP请求的参数转化为业务方法中定义的形参,自定义表示开发者可以设计自主转换的方式,HandlerAdapter已经提供了通用的转化,String转int,表单数据的封装。
但在特殊的业务情境下,HanderAdapter无法进行转换,需要开发者自定义转换器。
1.String转Date
客户端输入String类型的数据“2019-03-3”,自定义转化器将该数据转为Data类型对象。
-
创建DateConverter转换器,实现Converter接口
package com.xxx.converter; import org.springframework.core.convert.converter.Converter; import java.text.SimpleDateFormat; import java.util.Date; public class DateConverter implements Converter<String, Date> { private String pattern; public DateConverter(String pattern) { this.pattern = pattern; } @Override public Date convert(String s) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(this.pattern); Date date = null; try{ date = simpleDateFormat.parse(s); }catch (Exception e){ e.printStackTrace(); } return date; } }
-
在springmvc.xml中配置转换器
<!-- 配置自定义转换器--> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <!-- 配置多个--> <list> <bean class="com.xxx.converter.DateConverter"> <constructor-arg type="java.lang.String" value="yyyy-MM-dd"> </constructor-arg> </bean> </list> </property> </bean> <!-- conversion-service:对conversionService进行注册--> <mvc:annotation-driven conversion-service="conversionService"> <!-- 消息转换器,在responseBody传值出现乱码时,需要加这个--> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes" value="text/html;charset=UTF-8"> </property> </bean> <!--配置fastjson--> <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"></bean> </mvc:message-converters> </mvc:annotation-driven>
-
addDate.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>title</title> </head> <body> <form action="/converter/date" method="post"> 请输入日期:<input type="text" name="date">(yyyy-MM-dd)<br/> <input type="submit" value="提交"> </form> </body> </html>
-
Hander
package com.xxx.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Date; @RestController @RequestMapping("/converter") public class ConverterHander { @RequestMapping("/date") public String date(Date date){ return date.toString(); } }
2.String转Student
-
StudentConverter
package com.xxx.converter; import com.xxx.entity.Student; import org.springframework.core.convert.converter.Converter; public class StudentConverter implements Converter<String, Student> { @Override public Student convert(String s) { String[] args = s.split("-"); Student student = new Student(); student.setId(Long.parseLong(args[0])); student.setName(args[1]); student.setAge(Integer.parseInt(args[2])); return student; } }
-
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form action="/converter/student" method="post"> 请输入学生信息:<input type="text" name="student">(id-name-age)<br/> <input type="submit" value="提交"> </form> </body> </html>
-
springnvc.xml
<!-- 配置自定义转换器--> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <!-- 配置多个--> <list> <bean class="com.xxx.converter.DateConverter"> <constructor-arg type="java.lang.String" value="yyyy-MM-dd"></constructor-arg> </bean> <!-- 对student的转换--> <bean class="com.xxx.converter.StudentConverter"></bean> </list> </property> </bean> <!-- conversion-service:对conversionService进行注册--> <mvc:annotation-driven conversion-service="conversionService"> <!-- 消息转换器,在responseBody传值出现乱码时,需要加这个--> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes" value="text/html;charset=UTF-8"></property> </bean> <!--配置fastjson--> <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"></bean> </mvc:message-converters> </mvc:annotation-driven>
-
Handler
@RequestMapping("/student") public String student(Student student){ return student.toString(); }
7.Spring MVC REST
1.概述
- REST:Representational State Transfer,资源表现层状态转换,是目前主流的互联网架构.
- 特点:结构清晰、标椎规范、易于理解、便于扩展。
-
资源(Resource)
网络上的一个实体,或者说网络中具体存在的信息。可以使用URI(统一资源定位符) 指向它,每个资源都有对应的一个特定的URL。
-
表现成(Representation)
资源具体呈现出来的形式,比如文本可以用tet格式表示,也可以是HTML、XML等表示。
-
状态转换(State Transfer)
客户端如果希望操作服务器的某个资源,就需要通过某种方式让服务端发生状态转换,而这种转换建立在表现层之上,所以叫做“表现层转态转换“。(具体资源生成URL,然后访问)
-
特点
- URL更加简便
- 有利于不同系统之间的资源共享,只需要遵守一定的规范,不需要进行配置即可实现资源共享。
2.具体使用
REST具体操作就是HTTP协议中四个表示操作方式的动词分别对应的CRUD基本操作。
GET用来表示获取资源
POST用来表示新建资源
PUT用来表示修改资源
DELETE用来表示删除资源
-
Handler
package com.xxx.controller; import com.xxx.entity.Student; import com.xxx.repository.StudentRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; import java.util.Collection; @RestController @RequestMapping("/rest") public class RestHandler { //根据类型去注入 @Autowired private StudentRepository studentRepository; // @RequestMapping(value = "/findAll",method = RequestMethod.GET) // 二者等价 @GetMapping("/findAll") public Collection<Student> findALL(HttpServletResponse response){ //配置文件里可以解决异步请求,这里的配置可以解决同步请求。 response.setContentType("text/json;charset=UTF-8"); return studentRepository.findAll(); } @GetMapping("/findById/{id}") // 通过@PathVarible注解完成请求参数与形参的映射, // 在RESTful风格中,这个注解必须存在,否则就无法完成映射,这一点与传统风格不同。 //如果他们请求参数与形参一致,就可以不用写value的值,即直接写@PathVariable即可。 public Student findById(@PathVariable("id") long id){ return studentRepository.findById(id); } @PostMapping("/save") //把客户端(前端)的数据(json)给我,然后赋给形参(java对象) public void save(@RequestBody Student student){ studentRepository.saveOrUpdate(student); } @PutMapping("/update") public void update(@RequestBody Student student){ studentRepository.saveOrUpdate(student); } @DeleteMapping("/deleteById/{id}") public void deleteById(@PathVariable("id") long id){ studentRepository.deleteById(id); } }
-
StudentRepository
package com.xxx.repository; import com.xxx.entity.Student; import java.util.Collection; public interface StudentRepository { public Collection<Student> findAll(); public Student findById(long id); public void saveOrUpdate(Student student); public void deleteById(long id); }
-
StudentRepositoryImpl
package com.xxx.repository.impl; import com.xxx.entity.Student; import com.xxx.repository.StudentRepository; import org.springframework.stereotype.Repository; import java.util.Collection; import java.util.HashMap; import java.util.Map; @Repository public class StudentRepositoryImpl implements StudentRepository { private static Map<Long,Student> studentMap; static { studentMap = new HashMap<>(); studentMap.put(1L,new Student(1L,"张三",22)); studentMap.put(2L,new Student(2L,"李四",23)); studentMap.put(3L,new Student(3L,"王五",24)); } @Override public Collection<Student> findAll() { return studentMap.values(); } @Override public Student findById(long id) { return studentMap.get(id); } @Override public void saveOrUpdate(Student student) { studentMap.put(student.getId(),student); } @Override public void deleteById(long id) { studentMap.remove(id); } }
8.Spring MVC文件的上传下载
1.上传
1.单个文件的上传
底层是使用Apache fileupload组件完成上传,Spring MVC对这种方式进行了封装。
-
在pom.xml文件中添加相关依赖
<!-- 文件上传要添加的依赖--> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependency>
-
在springmvc.xml中配置上传组件
<!-- 配置上传组件--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
-
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%--不忽略el表达式--%> <%@ page isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <%--method="post" enctype="multipart/form-data" 是必须的,如果是get,则只能把文件名上传上去--%> <form action="/file/upload" method="post" enctype="multipart/form-data"> <input type="file" name="img"> <input type="submit" value="上传"> </form> <img src="${path}"> </body> </html>
- input的type设置为file
- form的method设置为post(get请求只能将文件名上传给服务器)
- form的enctype设置为multipart-form-data(如果不设置只能将文件名上传给服务器)
-
handler
package com.xxx.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
@Controller
@RequestMapping("/file")
public class fileGHandler {
@PostMapping("/upload")
//MultipartFile:对前台传来的二进制数据进行封装
public String upload(MultipartFile img, HttpServletRequest request){
// System.out.println(img);
if (img.getSize()>0){
//上传文件的要保存的file文件夹的路径,把数据全部放到file文件里
//去tomcat中去找这个file文件夹,手动创建的话一定要有内容才能去识别
String path = request.getServletContext().getRealPath("file");
//获取上传文件名
String name = img.getOriginalFilename();
//在path路径下创建name文件
File file = new File(path,name);
try {
//把img对象中的数据传给新建的文件夹中
img.transferTo(file);
//把图片所在的路径的路径传给request中
request.setAttribute("path","/file/"+name);
} catch (IOException e) {
e.printStackTrace();
}
}
return "upload";
}
}
* 在web.xml添加代码,处理无法加载.jpg图片
~~~xml
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
2.多文件上传
-
pom.xml,添加jstl依赖
<dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency>
-
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%--不忽略el表达式--%> <%@ page isELIgnored="false" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>Title</title> </head> <body> <%--method="post" enctype="multipart/form-data" 是必须的,如果是get,则只能把文件名上传上去--%> <form action="/file/upload" method="post" enctype="multipart/form-data"> <input type="file" name="img"> <input type="submit" value="上传"> </form> <c:forEach items="${files}" var="file"> <img src="${file}" width="200px"> </c:forEach> </body> </html>
-
Handler
@PostMapping("/uploads") public String uploads(MultipartFile[] imgs, HttpServletRequest request){ List<String> files = new ArrayList<>(); for (MultipartFile img:imgs) { if (img.getSize()>0){ //上传文件的要保存的file文件夹的路径,把数据全部放到file文件里 //去tomcat中去找这个file文件夹,手动创建的话一定要有内容才能去识别 String path = request.getServletContext().getRealPath("file"); //获取上传文件名 String name = img.getOriginalFilename(); //在path路径下创建name文件 File file = new File(path,name); try { //把img对象中的数据传给新建的文件夹中 img.transferTo(file); files.add("/file/"+name); } catch (IOException e) { e.printStackTrace(); } } } request.setAttribute("files",files); return "upload"; }
2.下载
- jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="/file/download/10">1.jpg</a><br/>
<a href="/file/download/11">2.jpg</a><br/>
<a href="/file/download/12">3.jpg</a><br/>
</body>
</html>
-
Handler
@GetMapping("/download/{name}") public void download(@PathVariable String name, HttpServletRequest request, HttpServletResponse response){ if (name != null){ name+=".jpg"; String path = request.getServletContext().getRealPath("file"); File file = new File(path,name); OutputStream outputStream = null; if (file.exists()){ //做些下载的设置,并且指定下载的文件名。 response.setContentType("application/forc-download"); response.setHeader("Content-Disposition","attachment;filename="+name); try { outputStream = response.getOutputStream(); //把file转变为数组 outputStream.write(FileUtils.readFileToByteArray(file)); } catch (IOException e) { e.printStackTrace(); }finally { if (outputStream != null){ try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } } }
9.Spring MVC表单标签库
1.基本使用
-
Handler
@GetMapping("get") public ModelAndView modelAndView(){ ModelAndView modelAndView = new ModelAndView("tag"); Student student = new Student(1,"张三",22); modelAndView.addObject("student",student); return modelAndView; }
-
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page isELIgnored="false" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <html> <head> <title>Title</title> </head> <body> <h1>学生信息</h1> <form:form modelAttribute="student"> 学生ID:<form:input path="id"></form:input><br/> 学生姓名:<form:input path="name"></form:input><br/> 学生年龄:<form:input path="age"></form:input><br/> <input type="submit" value="提交"> </form:form> </body> </html>
-
Jsp页面导入Spring MVC表单标签库,与导入JSTL标签库的语法非常相似,前缀prefix可以自定义,通常定义为form。
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
-
将form表单与模型数据进行绑定,通过modelAttribute属性完成绑定,将modelAtrribute的值设置为模型数据对应的key值。
jsp: <form:form modelAttribute="student"> handler: modelAndView.addObject("student",student);
-
form表单完成绑定之后,将模型数据的值取出绑定不同的标签中,通过设置标签的path属性完成,将path属性的值设置为模型数据对应的属性名即可。
学生ID:<form:input path="id"></form:input><br/> 学生姓名:<form:input path="name"></form:input><br/> 学生年龄:<form:input path="age"></form:input><br/>
2.常用的表单标签
1.form
<form:from modelAttribute="student"/>
渲染的HTML中的<form></form>
,通过modelAttibute属性绑定具体的模型数据。
2.input
<form:input path="name"/>
渲染的是HTML中的<input type="text"/>
,form标签绑定的是模型数据,input标签绑定的是模型数据中的属性值,通过path属性可以与模型数据中的属性名对应,并支持级联操作
<from:input path="address.name"/>
3.password
<form:password path="password"/>
渲染的是HTML中的<input type="password"/>
,通过path属性与模型数据的属性值进行绑定,passwor标签的值不会在页面显示。
4.checkbox
<%--value是复选框所代表的值--%>
checkbox:<form:checkbox path="flag" value="flag"></form:checkbox><br/>
渲染的是HTML中的<input type="checkbox/>"
,通过path与模型数据的属性值进行绑定,可以绑定boolean、数组和集合。
如果绑定boolean值,若 该变量的值为true,则表示该复选框选中,否则表示不选中。
如果绑定数组或者集合,数组、集合中的元素等于checkbox的value的值,则选中,否则就不选中。
String[] hobbies = {"读书","看电影","做笔记","玩游戏"};
student.setHobbies(hobbies);
modelAndView.addObject("student",student);
jsp:
爱好:<br/>
<form:checkbox path="hobbies" value="读书"/>读书<br/>
<form:checkbox path="hobbies" value="看电影"/>看电影<br/>
<form:checkbox path="hobbies" value="做笔记"/>做笔记<br/>
<form:checkbox path="hobbies" value="玩游戏"/>玩游戏<br/>
<input type="submit" value="提交">
5.checkboxs
<form:checkboxes items={student.hobbies} path="selectHoby"/>
渲染的是HTML的一组<input type="checkbox"/>
,是对<form:checkbox/>
的一种简化,需要结合items和path属性来使用,items绑定被遍历的集合或数组,path绑定被选中的集合或数组,可以理解为,items为全部可选集合,path为默认的选中的集合。
- handler
List hobbylist = Arrays.asList("读书","看电影","做笔记","玩游戏");
student.setHobbies(hobbylist);
List selectHobby = Arrays.asList("读书","看电影","做笔记");
student.setSelectHobby(selectHobby);
modelAndView.addObject("student",student);
- jsp:
爱好: <form:checkboxes path="selectHobby" items="${student.hobbies}"/><br/>
需要注意的是:path可以直接绑模型数据的属性值,items则需要通过EL表达式的形式从域对象中获取数据,不能直接写属性名。
6.radiobutton
<from:radiobutton path="radioId" value=0/>
渲染的是HTML中的一个 <input type="radio"/>
,绑定的数据与标签的value值相等则为选中,否则不选中。
-
handler
student.setRadioId(1); modelAndView.addObject("student",student);
-
jsp
rediobutton:<form:radiobutton path="radioId" value="1"></form:radiobutton>radiobutton<br/>
7.radiobuttons
<form:radiobuttons items="${student.grade} path="selectGrade"/>
渲染的是HTML中的一组<input type="radio"/>
,这里需要结合items和path两个属性使用,items绑定被遍历的结合或数组,path被选中的值,items为全部可选类型,path为默认 选中的选项,用法和<form:checkboxes/>
一致。
-
handler:
Map<Integer,String> gradeMap = new HashMap<>(); gradeMap.put(1,"一年级"); gradeMap.put(2,"二年级"); gradeMap.put(3,"三年级"); gradeMap.put(4,"四年级"); gradeMap.put(5,"五年级"); gradeMap.put(6,"六年级"); student.setGradeMap(gradeMap); student.setSelectGrade(3); modelAndView.addObject("student",student);
-
jsp
学生年级:<form:radiobuttons path="selectGrade" items="${student.gradeMap}"></form:radiobuttons><br/>
-
最终的studnet类
package com.xxx.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; import java.util.Map; @Data @AllArgsConstructor @NoArgsConstructor public class Student { private long id; private String name; private int age; private boolean flag; private String[] hobbies; private List<String> selectHobby; private int radioId; private Map<Integer,String> gradeMap; private int selectGrade; public Student(long id, String name, int age) { this.id = id; this.name = name; this.age = age; } }
8.select
<form:select items="${student.cities} path="selectCity"/>
渲染的是HTML中的<select/>
标签,需要 结合itmes和path两个属性来使用,items绑定被遍历的集合合或数组,path绑定被选中的值,用法与<form:radiobuttons/>
一致。
- handler
Map<Integer,String> cityMap = new HashMap<>();
cityMap.put(1,"北京");
cityMap.put(2,"上海");
cityMap.put(3,"广州");
cityMap.put(4,"南京");
cityMap.put(5,"深圳");
student.setCityMap(cityMap);
student.setSelectCity(2);
-
jsp
地址:<form:select path="selectCity" items="${student.cityMap}"></form:select><br/>
9.options
form:select
结合form:options
的使用,form:select
标签内部添加一个子标签form:options
,设置items属性,获取被遍历的集合。
所在城市:<form:select path="selectCity">
<form:options items="${student.cityMap}"></form:options>
</form:select><br/>
10.option
form:select
集合form:option
的使用,from:select
定义path属性,给每一个form:option
设置value值,path的值与哪个value的值相等,该项默认选中。
所在城市:<form:select path="selectCity">
<form:option value="1">杭州</form:option><br>
<form:option value="2">成都</form:option><br>
<form:option value="3">西安</form:option><br>
</form:select>
这个是在前端写,而options
s是后端写的。
11.textarea
渲染的是HTML中的<textarea/>
,path绑定模型数据的属性值,作为文本输入框的默认值。
-
handler
student.setIntroduce("您好,我是xxx"); modelAndView.addObject("student",student);
-
jsp
自我介绍:<form:textarea path="introduce"/><br/>
12.errors
用来处理错误信息,一般用在数据校验这部分,该标签需要结合Spring MVC的验证结合起来使用
10.Spring MVC数据校验
Spring MVC提供了两种校验方式:
- 基于Valibdator接口
- 使用AnnotationJSR-303标椎进行校验。
基于Validator接口的需要自定义Validator验证器,每一条的验证规则需要开发者手动完成,使用AnotationJSR-303标准则不需要自定义验证器,通过注解的方式可以直接在实体类中添加每个属性的验证规则,这种方式更加方便,实际开发中推荐使用。
1.基于Valibdator接口
-
实体类Account
package com.xxx.entity; import lombok.Data; @Data public class Account { private String name; private String password; }
-
自定义验证器AccountValidation,实现Validator接口
package com.xxx.validator; import com.xxx.entity.Account; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; public class AccountValidator implements Validator { //是否支持这种类型,true就就验证,false就不去验证。 @Override public boolean supports(Class<?> aClass) { return Account.class.equals(aClass); } @Override public void validate(Object o, Errors errors) { // name为空就提示报错信息:姓名不能为空 ValidationUtils.rejectIfEmpty(errors,"name","","姓名不能为空"); ValidationUtils.rejectIfEmpty(errors,"password","","密码不能为空"); } }
-
Handler
package com.xxx.controller; import com.xxx.entity.Account; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/validator") public class ValidatorHandler { @GetMapping("/login") public String login(Model model){ model.addAttribute("account",new Account()); return "login"; } @PostMapping("/login") //@Validated:启用验证器,BindingResult:绑定结果集 public String login(@Validated Account account, BindingResult bindingResult){ if (bindingResult.hasErrors()){ return "login"; } return "index"; } }
-
springmvc.xml中配置验证器,否则不生效。
<!--配置Validator的配置--> <bean id="accountValidator" class="com.xxx.validator.AccountValidator"></bean> <mvc:annotation-driven validator="accountValidator"></mvc:annotation-driven>
-
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page isELIgnored="false" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <html> <head> <title>Title</title> </head> <body> <form:form modelAttribute="account" action="/validator/login" method="post"> 姓名:<form:input path="name"/><form:errors path="name"/><br/> 年龄:<form:input path="password"/><form:errors path="password"/>br/> <input type="submit" value="登录"> </form:form> </body> </html>
2.AnnotationJSR-303标椎
使用AnotationJSR-303标椎进行验证,需要导入支持这种标椎的依赖jar文件,这里我们使用HibenateValidator。
-
pom.xml
<!--JSR-303,数据验证--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.3.6.Final</version> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency> <dependency> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging</artifactId> <version>3.3.0.Final</version> </dependency>
-
通过注解的方式直接在实体类中添加验证规则 。
package com.xxx.entity;
import lombok.Data;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
@Data
public class Person {
@NotEmpty(message = "用户名不能为空")
private String username;
@Size(min = 6,max = 12,message = "密码6-12位")
private String password;
@Email(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$",message = "请输入正确的邮箱格式")
private String email;
@Pattern(regexp = "^(13[0-9]|14[5|7]|15[0|1||3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$",message = "请输入正确的电话")
private String phone;
}
- ValidatorHandler
@GetMapping("/register")
public String register(Model model){
model.addAttribute("person",new Person());
return "register";
}
@PostMapping("/register")
public String register(@Valid Person person, BindingResult bindingResult){
if (bindingResult.hasErrors()){
return "register";
}
return "index";
}
-
springmvc.xml
<!-- 需要重新写一次--> <mvc:annotation-driven></mvc:annotation-driven>
让注解驱动生效
-
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page isELIgnored="false" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <html> <head> <title>Title</title> </head> <body> <form:form modelAttribute="person" action="/validator/register2" method="post"> 用户名:<form:input path="username"></form:input><form:errors path="username"/> <br/> 密码:<form:password path="password"></form:password><form:errors path="password"/> <br/> 邮箱:<form:input path="email"></form:input><form:errors path="email"/> <br/> 电话:<form:input path="phone"></form:input><form:errors path="phone"/> <br/> <input type="submit" value="提交"> </form:form> </body> </html>
-
相关注解
- @Null 被注解的元素必须为null
- @NotNUll 被注解的元素不能为null
- @Min(value) 被注解的元素不许是一个数字,其值必须大于等于指定的值
- @Max(vale) 被注解的元素必须是一个数字,其值必须大于等于指定的最小值
- Email 被注解的值必须是电子邮箱的地址
- Pattern 被注解的元素必须符合对应的正则表达式
- Length 被注解的元素的大小必须在指定的范围内
- NotEmpty 被注解的字符串必须非空
Null与Empty是不同的结果,String str = null,str是null,String str ="",str不是null,其值为空。
private String password;
@Email(regexp = “^\w+([-+.]\w+)@\w+([-.]\w+)\.\w+([-.]\w+)*
"
,
m
e
s
s
a
g
e
=
"
请
输
入
正
确
的
邮
箱
格
式
"
)
p
r
i
v
a
t
e
S
t
r
i
n
g
e
m
a
i
l
;
@
P
a
t
t
e
r
n
(
r
e
g
e
x
p
=
"
(
13
[
0
−
9
]
∣
14
[
5
∣
7
]
∣
15
[
0
∣
1
∣
∣
3
∣
5
∣
6
∣
7
∣
8
∣
9
]
∣
18
[
0
∣
1
∣
2
∣
3
∣
5
∣
6
∣
7
∣
8
∣
9
]
)
d
8
",message = "请输入正确的邮箱格式") private String email; @Pattern(regexp = "^(13[0-9]|14[5|7]|15[0|1||3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}
",message="请输入正确的邮箱格式")privateStringemail;@Pattern(regexp="(13[0−9]∣14[5∣7]∣15[0∣1∣∣3∣5∣6∣7∣8∣9]∣18[0∣1∣2∣3∣5∣6∣7∣8∣9])d8”,message = “请输入正确的电话”)
private String phone;
}
* ValidatorHandler
~~~java
@GetMapping("/register")
public String register(Model model){
model.addAttribute("person",new Person());
return "register";
}
@PostMapping("/register")
public String register(@Valid Person person, BindingResult bindingResult){
if (bindingResult.hasErrors()){
return "register";
}
return "index";
}
-
springmvc.xml
<!-- 需要重新写一次--> <mvc:annotation-driven></mvc:annotation-driven>
让注解驱动生效
-
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page isELIgnored="false" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <html> <head> <title>Title</title> </head> <body> <form:form modelAttribute="person" action="/validator/register2" method="post"> 用户名:<form:input path="username"></form:input><form:errors path="username"/> <br/> 密码:<form:password path="password"></form:password><form:errors path="password"/> <br/> 邮箱:<form:input path="email"></form:input><form:errors path="email"/> <br/> 电话:<form:input path="phone"></form:input><form:errors path="phone"/> <br/> <input type="submit" value="提交"> </form:form> </body> </html>
-
相关注解
- @Null 被注解的元素必须为null
- @NotNUll 被注解的元素不能为null
- @Min(value) 被注解的元素不许是一个数字,其值必须大于等于指定的值
- @Max(vale) 被注解的元素必须是一个数字,其值必须大于等于指定的最小值
- Email 被注解的值必须是电子邮箱的地址
- Pattern 被注解的元素必须符合对应的正则表达式
- Length 被注解的元素的大小必须在指定的范围内
- NotEmpty 被注解的字符串必须非空
Null与Empty是不同的结果,String str = null,str是null,String str ="",str不是null,其值为空。
学习视频:https://www.bilibili.com/video/BV1GE411d7KE