共计 36831 个字符,预计需要花费 93 分钟才能阅读完成。
(1)SpringMVC 的申请解决
1、SpringMVC 对申请参数的解决
在之前的 servlet 中咱们能够通过 request.getParameter()来获取申请中的参数,然而在咱们编写的 SpringMVC 的应用程序中,在具体申请的办法中并不蕴含 request 参数,那么咱们应该如何获取申请中的参数呢?
须要应用以下几个注解:
@RequestParam:获取申请的参数
@RequestHeader:获取申请头信息
@CookieValue:获取 cookie 中的值
@RequestParam 的根本应用
package com.mashibing.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class RequestController {
/**
* 如何获取 SpringMVC 中申请中的信息
* 默认状况下,能够间接在办法的参数中填写跟申请一样的名称,此时会默认承受参数
* 如果有值,间接赋值,如果没有,那么间接给空值
*
* @RequestParam: 获取申请中的参数值, 应用此注解之后,参数的名称不须要跟申请的名称统一,然而必须要写
* public String request(@RequestParam("user") String username){
*
* 此注解还蕴含三个参数:* value: 示意要获取的参数值
* required:示意此参数是否必须,默认是 true,如果不写参数那么会报错,如果值为 false,那么不写参数不会有任何谬误
* defaultValue: 如果在应用的时候没有传递参数,那么定义默认值即可
*
*
* @param username
* @return
*/
@RequestMapping("/request")
public String request(@RequestParam(value = "user",required = false,defaultValue = "hehe") String username){System.out.println(username);
return "success";
}
}
@RequestHeader 的根本应用:
package com.mashibing.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import sun.management.resources.agent;
@Controller
public class RequestController {
/**
* 如果须要获取申请头信息该如何解决呢?* 能够应用 @RequestHeader 注解,* public String header(@RequestHeader("User-Agent") String agent){* 相当于 request.getHeader("User-Agent")
*
* 如果要获取申请头中没有的信息,那么此时会报错,同样,此注解中也蕴含三个参数, 跟 @RequestParam 一样
* value
* required
* defalutValue
* @param agent
* @return
*/
@RequestMapping("/header")
public String header(@RequestHeader("User-Agent") String agent){System.out.println(agent);
return "success";
}
}
@CookieValue 的根本应用
package com.mashibing.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import sun.management.resources.agent;
@Controller
public class RequestController {
/**
* 如果须要获取 cookie 信息该如何解决呢?* 能够应用 @CookieValue 注解,* public String cookie(@CookieValue("JSESSIONID") String id){
* 相当于
* Cookie[] cookies = request.getCookies();
* for(Cookie cookie : cookies){* cookie.getValue();
* }
* 如果要获取 cookie 中没有的信息,那么此时会报错,同样,此注解中也蕴含三个参数, 跟 @RequestParam 一样
* value
* required
* defalutValue
* @param id
* @return
*/
@RequestMapping("/cookie")
public String cookie(@CookieValue("JSESSIONID") String id){System.out.println(id);
return "success";
}
}
如果申请中传递的是某一个对象的各个属性值,此时如何在控制器的办法中获取对象的各个属性值呢?
在 SpringMVC 的管制中,能间接实现对象的属性赋值操作,不须要人为干涉。
User.java
package com.mashibing.bean;
import java.util.Date;
public class User {
private Integer id;
private String name;
private Integer age;
private Date date;
private Address address;
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 Integer getAge() {return age;}
public void setAge(Integer age) {this.age = age;}
public Date getDate() {return date;}
public void setDate(Date date) {this.date = date;}
public Address getAddress() {return address;}
public void setAddress(Address address) {this.address = address;}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", date=" + date +
", address=" + address +
'}';
}
}
Address.java
package com.mashibing.bean;
public class Address {
private String province;
private String city;
private String town;
public String getProvince() {return province;}
public void setProvince(String province) {this.province = province;}
public String getCity() {return city;}
public void setCity(String city) {this.city = city;}
public String getTown() {return town;}
public void setTown(String town) {this.town = town;}
@Override
public String toString() {
return "Address{" +
"province='" + province + '\'' +
", city='" + city + '\'' +
", town='" + town + '\'' +
'}';
}
}
login.jsp
<%--
Created by IntelliJ IDEA.
User: root
Date: 2020/3/7
Time: 0:11
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="addUser" method="post">
编号:<input type="text" name="id"/><br>
姓名:<input type="text" name="name"/><br>
年龄:<input type="text" name="age"/><br>
日期:<input type="text" name="date"/><br>
省份:<input type="text" name="address.province"/><br>
城市:<input type="text" name="address.city"/><br>
区域:<input type="text" name="address.town"/><br>
<input type="submit" value="submit"/><br>
</form>
</body>
</html>
UserController.java
package com.mashibing.controller;
import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {@RequestMapping("/addUser")
public String addUser(User user){System.out.println(user);
return "success";
}
}
2、乱码问题的解决
咱们在表单或者发送申请的时候,常常会遇到中文乱码的问题,那么如何解决乱码问题呢?
GET 申请:在 server.xml 文件中,增加 URIEncoding=“UTF-8”
POST 申请:编写过滤器进行实现
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 配置 DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--
关联 springmvc 的配置文件:此配置文件的属性能够不增加,然而须要在 WEB-INF 的目录下创立 前端控制器名称 -servlet.xml 文件
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
</servlet>
<!-- 匹配 servlet 的申请,/:标识匹配所有申请,然而不会 jsp 页面
/*:拦挡所有申请,拦挡 jsp 页面
然而须要留神的是,当配置成 index.html 的时候,会发现申请不到
起因在于,tomcat 下也有一个 web.xml 文件,所有的我的项目下 web.xml 文件都须要继承此 web.xml
在服务器的 web.xml 文件中有一个 DefaultServlet 用来解决动态资源,然而 url-pattern 是 /
而咱们在本人的配置文件中如果增加了 url-pattern=/ 会笼罩父类中的 url-pattern,此时在申请的时候
DispatcherServlet 会去 controller 中做匹配,找不到则间接报 404
而在服务器的 web.xml 文件中蕴含了一个 JspServlet 的解决,所以不过拦挡 jsp 申请
-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 解决 post 申请乱码 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!-- 解决响应乱码 -->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
留神:如果配置了多个过滤器,那么字符编码过滤器肯定要在最后面,否则生效。
3、SpringMVC 对原生 API 的反对
package com.mashibing.controller;
import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.PrintWriter;
@Controller
public class UserController {@RequestMapping("/addUser")
public String addUser(User user){System.out.println(user);
return "success";
}
/**
* SpringMVC 也能够在参数上应用原生的 Servlet API
*
* HttpSession
* HttpServletRequest
* HttpServletResponse
*
* java.security.Principal 平安协定相干
* Locale:国际化相干的区域信息对象
* InputStream:
* ServletInputStream inputStream = request.getInputStream();
* OutputStream:
* ServletOutputStream outputStream = response.getOutputStream();
* Reader:
* BufferedReader reader = request.getReader();
* Writer:
* PrintWriter writer = response.getWriter();
* @param session
* @param request
* @param response
* @return
*/
@RequestMapping("api")
public String api(HttpSession session, HttpServletRequest request, HttpServletResponse response){request.setAttribute("requestParam","request");
session.setAttribute("sessionParam","session");
return "success";
}
}
4、应用 Model,Map,ModelMap 传输数据到页面
在刚开始的 helloworld 我的项目中,咱们传递了参数回到咱们页面,然而后续的操作都只是承受用户的申请,那么在 SpringMVC 中除了能够应用原生 servlet 的对象传递数据之外,还有什么其余的形式呢?
能够在办法的参数上传入 Model,ModelMap,Map 类型,此时都可能将数据传送回页面
OutputController.java
package com.mashibing.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Map;
@Controller
public class OutputController {@RequestMapping("output1")
public String output1(Model model){model.addAttribute("msg","hello,Springmvc");
return "output";
}
@RequestMapping("output2")
public String output2(ModelMap model){model.addAttribute("msg","hello,Springmvc");
return "output";
}
@RequestMapping("output3")
public String output1(Map map){map.put("msg","hello,Springmvc");
return "output";
}
}
当应用此形式进行设置之后,会发现所有的参数值都设置到了 request 作用域中,那么这三个对象是什么关系呢?
5、应用 ModelAndView 对象传输数据到页面
package com.mashibing.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class OutputController {@RequestMapping("mv")
public ModelAndView mv(){ModelAndView mv = new ModelAndView();
mv.setViewName("output");
mv.addObject("msg","hello.modelAndView");
return mv;
}
}
发现当应用 modelAndView 对象的时候,返回值的类型也是此对象,能够将要跳转的页面设置成 view 的名称,来实现跳转的性能,同时数据也是放到 request 作用中。
6、应用 session 传输数据到页面
@SessionAttribute:此注解能够示意,当向 request 作用域设置数据的时候同时也要向 session 中保留一份, 此注解有两个参数,一个 value(示意将哪些值设置到 session 中),另外一个 type(示意依照类型来设置数据,个别不必,因为有可能会将很多数据都设置到 session 中,导致 session 异样)。
@Controller
@SessionAttributes(value = "msg")
public class OutputController {@RequestMapping("output1")
public String output1(Model model){model.addAttribute("msg","hello,Springmvc");
System.out.println(model.getClass());
return "output";
}
}
7、应用 @ModelAttribute 来获取申请中的数据
@ModelAttribute 注解用于将办法的参数或者办法的返回值绑定到指定的模型属性上,并返回给 web 视图。首先来介绍一个业务场景,来帮忙大家做了解,在理论工作中,有些时候咱们在批改数据的时候可能只须要批改其中几个字段,而不是全副的属性字段都获取,那么当提交属性的时候,从 form 表单中获取的数据就有可能只蕴含了局部属性,此时再向数据库更新的时候,必定会失落属性,因为对象的封装是 springmvc 主动帮咱们 new 的,所以此时须要先将从数据库获取的对象保留下来,当提交的时候不是 new 新的对象,而是在原来的对象上进行属性笼罩,此时就须要应用 @ModelAttribute 注解。
User.java
package com.mashibing.bean;
public class User {
private Integer id;
private String name;
private String password;
private Integer age;
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 String getPassword() {return password;}
public void setPassword(String password) {this.password = password;}
public Integer getAge() {return age;}
public void setAge(Integer age) {this.age = age;}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
", age=" + age +
'}';
}
}
UserController.java
package com.mashibing.controller;
import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {
Object o1 = null;
Object o2 = null;
Object o3 = null;
@RequestMapping("update")
public String update(@ModelAttribute("user") User user,Model model){System.out.println(user);
o2 = model;
// 能够看到所有的 model 都是同一个对象
System.out.println(o1==o2);
// 能够看到存储的 user 对象也是同一个
System.out.println(user == o3);
return "output";
}
@ModelAttribute
public void MyModelAttribute(Model model){
o1 = model;
User user = new User();
user.setId(1);
user.setName("张三");
user.setAge(12);
user.setPassword("123");
model.addAttribute("user",user);
System.out.println("modelAttribute:"+user);
o3 = user;
}
}
index.jsp
<%--
Created by IntelliJ IDEA.
User: root
Date: 2020/3/11
Time: 13:45
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="update" method="post">
<input type="hidden" value="1" name="id">
姓名:张三 <br>
明码:<input type="text" name="password"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
其实在应用的时候能够简化写法,也就是说,在办法的参数上不加 @ModelAttribute 也不会有问题
@RequestMapping("update")
public String update(User user,Model model){System.out.println(user);
o2 = model;
// 能够看到所有的 model 都是同一个对象
System.out.println(o1==o2);
// 能够看到存储的 user 对象也是同一个
System.out.println(user == o3);
return "output";
}
如果增加的 @ModelAttribute(“”)属性的值不对,那么也是获取不到值的。同时能够增加 @SessionAttributes 属性,然而留神,如果没有设置值的话,会报错
package com.mashibing.controller;
import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
@Controller
@SessionAttributes("u")
public class UserController {
Object o1 = null;
Object o2 = null;
Object o3 = null;
@RequestMapping("update")
public String update(@ModelAttribute("u") User user,Model model){System.out.println(user);
o2 = model;
// 能够看到所有的 model 都是同一个对象
System.out.println(o1==o2);
// 能够看到存储的 user 对象也是同一个
System.out.println(user == o3);
return "output";
}
@ModelAttribute
public void MyModelAttribute(Model model){
o1 = model;
User user = new User();
user.setId(1);
user.setName("张三");
user.setAge(12);
user.setPassword("123");
model.addAttribute("user",user);
System.out.println("modelAttribute:"+user);
o3 = user;
}
}
留神:ModelAttribute 除了能够应用设置值到 model 中之外,还能够利用返回值。
package com.mashibing.controller;
import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
@Controller
public class UserController {
Object o1 = null;
Object o2 = null;
Object o3 = null;
@RequestMapping("update")
public String update(@ModelAttribute("u") User user,Model model){System.out.println(user);
o2 = model;
// 能够看到所有的 model 都是同一个对象
System.out.println(o1==o2);
// 能够看到存储的 user 对象也是同一个
System.out.println(user == o3);
return "output";
}
@ModelAttribute("u")
public User MyModelAttribute(Model model){
o1 = model;
User user = new User();
user.setId(1);
user.setName("张三");
user.setAge(12);
user.setPassword("123");
// model.addAttribute("user",user);
System.out.println("modelAttribute:"+user);
o3 = user;
return user;
}
}
总结:通过刚刚的给参数赋值,大家应该可能发现,当给办法中的参数设置值的时候,如果增加了 @ModelAttribute 注解,那么在查找值的时候,是遵循以下形式:
1、办法的参数应用参数的类型首字母小写,或者应用 @ModelAttribute(“”)的值
2、先看之前是否在 model 中设置过该属性值,如果设置过就间接获取
3、看 @SessionAttributes 注解标注类中的办法是否给 session 中赋值,如果有的话,也是间接获取,没有报异样
8、应用 forward 实现页面转发
在发送申请的时候,能够通过 forward: 来实现转发的性能:
package com.mashibing.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ForWardController {
/**
* 当应用转发的时候能够增加前缀 forward:index.jsp, 此时是不会通过视图解析器的,所以要增加残缺的名称
*
* forward: 也能够由一个申请跳转到另外一个申请
*
* @return
*/
@RequestMapping("/forward01")
public String forward(){System.out.println("1");
return "forward:/index.jsp";
}
@RequestMapping("/forward02")
public String forward2(){System.out.println("2");
return "forward:/forward01";
}
}
9、应用 redirect 来实现重定向
package com.mashibing.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class RedirectController {
/**
* redirect : 重定向的门路
* 相当于 response.sendRedirect("index.jsp")
* 跟视图解析器无关
* @return
*/
@RequestMapping("redirect")
public String redirect(){System.out.println("redirect");
return "redirect:/index.jsp";
}
@RequestMapping("/redirect2")
public String redirect2(){System.out.println("redirect2");
return "redirect:/redirect";
}
}
在 javaweb 的时候大家应该都接触过重定向和转发的区别,上面再具体说一下:
转发:
由服务器的页面进行跳转,不须要客户端从新发送申请:
特点如下:
1、地址栏的申请不会发生变化,显示的还是第一次申请的地址
2、申请的次数,有且仅有一次申请
3、申请域中的数据不会失落
4、根目录:localhost:8080/ 我的项目地址 /, 蕴含了我的项目的拜访地址
重定向:
在浏览器端进行页面的跳转,须要发送两次申请(第一次是人为的,第二次是主动的)
特点如下:
1、地址栏的地址发生变化,显示最新发送申请的地址
2、申请次数:2 次
3、申请域中的数据会失落,因为是不同的申请
4、根目录:localhost:8080/ 不蕴含我的项目的名称
比照:
区别 | 转发 forward() | 重定向 sendRedirect() |
---|---|---|
根目录 | 蕴含我的项目拜访地址 | 没有我的项目拜访地址 |
地址栏 | 不会发生变化 | 会发生变化 |
哪里跳转 | 服务器端进行的跳转 | 浏览器端进行的跳转 |
申请域中数据 | 不会失落 | 会失落 |
10、动态资源的拜访
当页面中蕴含动态资源的时候咱们可能正确的获取到吗?
hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
pageContext.setAttribute("ctx",request.getContextPath());
%>
<html>
<head>
<title>Title</title>
</head>
<body>
hello springmvc
<img src="${ctx}/images/timg.jpg">
</body>
</html>
此时大家发现咱们申请的图片基本拜访不到,依据查看发现门路是没有问题的,那么为什么会找不到动态资源呢?
大家发现此时是找不到对应的 mapping 映射的,此时是因为 DispatcherServlet 会拦挡所有的申请,而此时咱们没有对应图片的申请解决办法,所以此时报错了,想要解决的话非常简单,只须要增加一个配置即可
<!--
此配置示意 咱们本人配置的申请由 controller 来解决,然而不能申请的解决交由 tomcat 来解决
动态资源能够拜访,然而动静申请无法访问
-->
<mvc:default-servlet-handler/>
然而加上此配置之后,大家又发现此时除了动态资源无法访问之外,咱们失常的申请也无奈获取了,因而还须要再增加另外的配置:
<!-- 保障动态资源和动静申请都可能拜访 -->
<mvc:annotation-driven/>
(2)自定义视图解析器
咱们在之前的操作中曾经用了 SpringMVC 中提供的视图解析器,那么如果咱们须要实现本人的视图解析器该如何操作呢?
MyViewController.java
package com.mashibing.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class MyViewController {@RequestMapping("/myview")
public String myView(Model model){model.addAttribute("msb","马士兵");
return "msb:/index";
}
}
MyViewResolver.java
package com.mashibing.view;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import java.util.Locale;
public class MyViewResolver implements ViewResolver, Ordered {
private int order = 0;
public View resolveViewName(String viewName, Locale locale) throws Exception {
// 如果前缀是 msb: 结尾的就进行解析
if (viewName.startsWith("msb:")){System.out.println("msb:");
return new MyView();}else{
// 如果不是,则间接返回 null
return null;
}
}
public int getOrder() {return this.order;}
public void setOrder(Integer order) {this.order = order;}
}
MyView.java
package com.mashibing.view;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.View;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
public class MyView implements View {public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {System.out.println("保留的对象是:"+model);
response.setContentType("text/html");
response.getWriter().write("欢送退出马士兵教育");
}
/**
* 返回数据内容的类型
* @return
*/
public String getContentType() {return "text/html";}
}
springmvc.xml
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.mashibing"></context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean class="com.mashibing.view.MyViewResolver">
<property name="order" value="1"></property>
</bean>
</beans>
(3)自定义类型转换器
在日常的企业开发需要中,咱们输出文本框的内容全部都是字符串类型,然而在后端解决的时候咱们能够用其余根本类型来承受数据,也能够应用实体类来承受参数,这个是怎么实现的呢?就是通过 SpringMVC 提供的类型转换器,SpringMVC 外部提供了十分丰盛的类型转换器的反对,然而有些状况下有可能难以满足咱们的需要,因而须要咱们本人实现,如下:
User.java
package com.mashibing.bean;
public class User {
private Integer id;
private String name;
private Integer age;
private String gender;
public User() {}
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 Integer getAge() {return age;}
public void setAge(Integer age) {this.age = age;}
public String getGender() {return gender;}
public void setGender(String gender) {this.gender = gender;}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
MyConverter.java
package com.mashibing.converter;
import com.mashibing.bean.User;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
@Component
public class MyConverter implements Converter<String, User> {public User convert(String source) {
User user = null;
String[] split = source.split("-");
if (source!=null && split.length==4){user = new User();
user.setId(Integer.parseInt(split[0]));
user.setName(split[1]);
user.setAge(Integer.parseInt(split[2]));
user.setGender(split[3]);
}
return user;
}
}
UserController.java
package com.mashibing.controller;
import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {@RequestMapping("/user")
public String add(User user, Model model){System.out.println(user);
model.addAttribute("user","user");
return "success";
}
}
success.jsp
<%--
Created by IntelliJ IDEA.
User: root
Date: 2020/3/12
Time: 21:36
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${requestScope.user}
</body>
</html>
springmvc.xml
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.mashibing"></context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean class="com.mashibing.view.MyViewResolver">
<property name="order" value="1"></property>
</bean>
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="myConverter"></ref>
</set>
</property>
</bean>
</beans>
(4)自定义日期格式化转换器
有时候咱们常常须要在页面增加日期等相干信息,此时须要制订日期格式化转换器,此操作非常简单:只须要在独自的属性上增加 @DateTimeFormat 注解即可,制订对应的格局
User.java
package com.mashibing.bean;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
public class User {
private Integer id;
private String name;
private Integer age;
private String gender;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birth;
public User() {}
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 Integer getAge() {return age;}
public void setAge(Integer age) {this.age = age;}
public String getGender() {return gender;}
public void setGender(String gender) {this.gender = gender;}
public Date getBirth() {return birth;}
public void setBirth(Date birth) {this.birth = birth;}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", birth=" + birth +
'}';
}
}
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="dateConvertion" method="post">
编号:<input type="text" name="id"><br>
姓名:<input type="text" name="name"><br>
年龄:<input type="text" name="age"><br>
性别:<input type="text" name="gender"><br>
日期:<input type="text" name="birth"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
DateConvertionController.java
package com.mashibing.controller;
import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class DateConvertionController {@RequestMapping("dateConvertion")
public String dateConvertion(User user){System.out.println(user);
return "hello";
}
}
springmvc.xml
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.mashibing"></context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean class="com.mashibing.view.MyViewResolver">
<property name="order" value="1"></property>
</bean>
<!-- 此配置示意 咱们本人配置的申请由 controller 来解决,然而不能申请的解决交由 tomcat 来解决
动态资源能够拜访,然而动静申请无法访问
-->
<mvc:default-servlet-handler/>
<!-- 保障动态资源和动静申请都可能拜访 -->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
此时运行发现是没有问题的,然而须要留神的是,如果同时配置了自定义类型转换器之后,那么日期格局转化是有问题的。
springmvc.xml
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.mashibing"></context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean class="com.mashibing.view.MyViewResolver">
<property name="order" value="1"></property>
</bean>
<!-- 此配置示意 咱们本人配置的申请由 controller 来解决,然而不能申请的解决交由 tomcat 来解决
动态资源能够拜访,然而动静申请无法访问
-->
<mvc:default-servlet-handler/>
<!-- 保障动态资源和动静申请都可能拜访 -->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="myConverter"></ref>
</set>
</property>
</bean>
</beans>
起因就在于 ConversionServiceFactoryBean 对象中有且仅有一个属性 converters,此时能够应用另外一个类来做替换 FormattingConversionServiceFactoryBean
springmvc.xml
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.mashibing"></context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean class="com.mashibing.view.MyViewResolver">
<property name="order" value="1"></property>
</bean>
<!-- 此配置示意 咱们本人配置的申请由 controller 来解决,然而不能申请的解决交由 tomcat 来解决
动态资源能够拜访,然而动静申请无法访问
-->
<mvc:default-servlet-handler/>
<!-- 保障动态资源和动静申请都可能拜访 -->
<!-- <mvc:annotation-driven></mvc:annotation-driven>-->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="myConverter"></ref>
</set>
</property>
</bean>
</beans>
(5)数据校验
个别状况下咱们会在前端页面实现数据的校验,然而大家须要留神的是前端校验会存在数据的不平安问题,因而个别状况下咱们都会应用前端校验 + 后端校验的形式,这样的话既可能满足用户的体验度,同时也能保证数据的平安,上面来说一下在 springmvc 中如何进行后端数据校验。
JSR303 是 Java 为 Bean 数据合法性校验提供的规范框架,它曾经蕴含在 JavaEE 6.0 中。JSR 303 (Java Specification Requests 意思是 Java 标准提案)通过 在 Bean 属性上标注 相似于 @NotNull、@Max 等规范的注解指定校验规定,并通过规范的验证接口对 Bean 进行验证。
JSR303:
Hibernate Validator 扩大注解:
spring 中领有本人的数据校验框架,同时反对 JSR303 规范的校验框架,能够在通过增加注解的形式进行数据校验。在 spring 中自身没有提供 JSR303 的实现,须要导入依赖的包。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mashibing</groupId>
<artifactId>springmvc_viewResolver</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.0.Final</version>
</dependency>
</dependencies>
</project>
index.jsp
<%--
Created by IntelliJ IDEA.
User: root
Date: 2020/3/12
Time: 15:23
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="dataValidate" method="post">
编号:<input type="text" name="id"><br>
姓名:<input type="text" name="name"><br>
年龄:<input type="text" name="age"><br>
性别:<input type="text" name="gender"><br>
日期:<input type="text" name="birth"><br>
邮箱:<input type="text" name="email"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
DataValidateController.java
package com.mashibing.controller;
import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;
@Controller
public class DataValidateController {@RequestMapping("/dataValidate")
public String validate(@Valid User user, BindingResult bindingResult) {System.out.println(user);
if (bindingResult.hasErrors()) {System.out.println("验证失败");
return "redirect:/index.jsp";
} else {System.out.println("验证胜利");
return "hello";
}
}
}
User.java
package com.mashibing.bean;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import java.util.Date;
public class User {
private Integer id;
@NotNull
@Length(min = 5,max = 10)
private String name;
private Integer age;
private String gender;
@Past
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birth;
@Email
private String email;
public User() {}
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 Integer getAge() {return age;}
public void setAge(Integer age) {this.age = age;}
public String getGender() {return gender;}
public void setGender(String gender) {this.gender = gender;}
public Date getBirth() {return birth;}
public void setBirth(Date birth) {this.birth = birth;}
public String getEmail() {return email;}
public void setEmail(String email) {this.email = email;}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", birth=" + birth +
", email='" + email + '\'' +
'}';
}
}
此时大家发现在报错的中央无奈呈现谬误提醒,能够换另外一种形式:
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="add"> 增加用户 </a>
</body>
</html>
add.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form:form action="dataValidate" modelAttribute="user" method="post">
id:<form:input path="id"></form:input><form:errors path="id"></form:errors> <br/>
name:<form:input path="name"></form:input><form:errors path="name"></form:errors><br/>
age:<form:input path="age"></form:input><form:errors path="age"></form:errors><br/>
gender:<form:input path="gender"></form:input><form:errors path="gender"></form:errors><br/>
birth:<form:input path="birth"></form:input><form:errors path="birth"></form:errors><br/>
email:<form:input path="email"></form:input><form:errors path="email"></form:errors><br/>
<input type="submit" value="submit">
</form:form>
</body>
</html>
DataValidateController.java
package com.mashibing.controller;
import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;
@Controller
public class DataValidateController {@RequestMapping("/dataValidate")
public String validate(@Valid User user, BindingResult bindingResult, Model model) {System.out.println(user);
if (bindingResult.hasErrors()) {System.out.println("验证失败");
return "add";
} else {System.out.println("验证胜利");
return "hello";
}
}
@RequestMapping("add")
public String add(Model model){model.addAttribute("user",new User(1,"zhangsan",12,"女",null,"1234@qq.com"));
return "add";
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</context-param>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encoding</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
原生的表单如何获取错误信息:
DataValidateController.java
package com.mashibing.controller;
import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Controller
public class DataValidateController {@RequestMapping("/dataValidate")
public String validate(@Valid User user, BindingResult bindingResult, Model model) {System.out.println(user);
Map<String,Object> errorsMap = new HashMap<String, Object>();
if (bindingResult.hasErrors()) {System.out.println("验证失败");
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
for (FieldError fieldError : fieldErrors) {System.out.println(fieldError.getDefaultMessage());
System.out.println(fieldError.getField());
errorsMap.put(fieldError.getField(),fieldError.getDefaultMessage());
}
model.addAttribute("errorInfo",errorsMap);
return "add";
} else {System.out.println("验证胜利");
return "hello";
}
}
@RequestMapping("add")
public String add(Model model){model.addAttribute("user",new User(1,"zhangsan",12,"女",null,"1234@qq.com"));
return "add";
}
}
add.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form:form action="dataValidate" modelAttribute="user" method="post">
编号:<form:input path="id"></form:input><form:errors path="id"></form:errors>--->${errorInfo.id} <br/>
姓名:<form:input path="name"></form:input><form:errors path="name"></form:errors>--->${errorInfo.name}<br/>
年龄:<form:input path="age"></form:input><form:errors path="age"></form:errors>--->${errorInfo.age}<br/>
性别:<form:input path="gender"></form:input><form:errors path="gender"></form:errors>--->${errorInfo.gender}<br/>
生日:<form:input path="birth"></form:input><form:errors path="birth"></form:errors>--->${errorInfobirth}<br/>
邮箱:<form:input path="email"></form:input><form:errors path="email"></form:errors>--->${errorInfo.email}<br/>
<input type="submit" value="submit">
</form:form>
</body>
</html>