SpringMVC笔记
【1】MVC
M;模型层,包含数据校验
V:视图层,包含国际化、标签库
C:控制层,包含转发重定向、参数、拦截器、作用域等
【2】Spring中的父子容器问题
【3】@RequestMapping
@RequestMapping ( path = { "/add" , "/add2" , "/add1" } , name = "userController.add" , method = { RequestMethod . GET } ,
params = { "name" , "age=20" } , / * consumes = { "text/html" } , * /
produces = { "text/plain; charset=UTF-8" }
)
public ModelAndView add ( ) {
System . out. println ( "add方法运行" ) ;
ModelAndView mv = new ModelAndView ( ) ;
mv. setViewName ( "forward:/index.jsp" ) ;
mv. addObject ( "t" , "测试请求作用域传递数据" ) ;
return mv;
}
【4】请求参数的处理
普通参数: 请求参数没有同名,使用字符串,数字等类型变量处理的参数。
- 在控制方法参数表中,定义同名的参数,自动处理。类型不匹配,则400错误
- 如果请求参数名字和方法参数名字不同,使用注解@RequestParam(value="请求参数名") 修饰方法参数
- 注解@RequestParam中的属性value可以省略,默认和方法参数同名
数组参数: 请求参数同名多个,是一个数组。eg: localhost:8080/bjsxt/test1?name=zs&name=ls
- 在控制方法参数表中,定义同名的数组类型参数,自动处理。或使用注解修饰List集合参数,自动处理。
对象参数: 使用自定义的实体类型,处理若干请求参数。
- 在控制方法参数表中,定义任意变量名称的应用类型参数,springmvc自动的基于自定义类型中的property同名处理请求参数,并封装对象。
- 注意,不能再使用@RequestParam注解修饰方法参数了,一定是请求参数名和property名同名处理。
- 同名处理请求参数的时候,类型也要匹配。
- 如果普通参数和对象参数的属性同名,springmvc秉承着雨露均沾的想法,给所有方法参数赋值
普通参数如果是日期格式如何处理? java.util.Date
- 1. 默认转换: 看自己个人电脑右下角的时间格式。一般都是yyyy/M/d HH:mm:ss。只要传递的参数字符串格式符合,即可自动转换。
格式可以是年月日,或年月日时分秒。 不能只有时分秒。
- 2. 指定转换: 使用注解实现转换 @DateTimeFormat。指定具体的格式。注解提供的格式是什么,请求参数格式必须符合。否则400错误。
- 即使自定义类型中包含日期类型的属性,转换方案等同普通参数。
如果自定义类型有关系,如何处理? 如:A中有B类型的引用,或A中有B泛型的集合
- 如果User类型中有命名是idCard的IdCard类型参数,那么请求参数名称是 idCard.IdCard类型中的属性名
- 如果User类型中有命名是addressList的Address泛型List参数。那么请求参数名称是 addressList[下标].Address类型中的属性名。eg: idCard.cardNo=123&addressList[0].addr=address1&addressList[1].addr=address2
@RequestMapping ( "/param8" )
public String param8 ( @RequestParam ( name= "n" , required = false , defaultValue = "默认值" ) String name,
@RequestParam ( name = "a" , required = false , defaultValue = "0" ) int a,
@DateTimeFormat ( pattern = "yyyy-MM-dd" ) @RequestParam ( defaultValue = "2022-01-01" ) Date d) {
System . out. println ( name) ;
System . out. println ( "a = " + a) ;
System . out. println ( "d = " + d) ;
return "/index.jsp" ;
}
@RequestMapping ( "/param7" )
public String param7 ( User user) {
System . out. println ( user) ;
return "/index.jsp" ;
}
@RequestMapping ( "/param6" )
public String param6 ( @DateTimeFormat ( pattern = "yyyy-MM-dd HH:mm:ss" ) Date d) {
System . out. println ( d) ;
return "/index.jsp" ;
}
@RequestMapping ( "/param5" )
public String param5 ( Date d) {
System . out. println ( "时间是:" + d) ;
return "/index.jsp" ;
}
@RequestMapping ( "/param4" )
public String param4 ( User user, String name) {
System . out. println ( "user = " + user) ;
System . out. println ( "name = " + name) ;
return "/index.jsp" ;
}
@RequestMapping ( "/param3" )
public String param3 ( User user) {
System . out. println ( user) ;
return "/index.jsp" ;
}
@RequestMapping ( "/param2" )
public String param2 ( String [ ] hobbies, @RequestParam List < String > books) {
System . out. println ( "hobbies = " + Arrays . toString ( hobbies) + " ; books = " + books) ;
return "/index.jsp" ;
}
@RequestMapping ( "/param1" )
public String param1 ( @RequestParam ( value= "n" ) String name, int age) {
System . out. println ( "name = " + name + " ; age = " + age) ;
return "/index.jsp" ;
}
@RequestMapping ( value = "/testProduces" , produces = { "text/plain; charset=UTF-8" } )
@ResponseBody
public String testProduces ( ) {
System . out. println ( "方法运行" ) ;
return "这是测试的返回结果" ;
}
【5】@RequestParam
注解 RequestParam - 是专门处理请求参数的注解。是用于修饰方法参数的。
使用注解声明的描述方法参数和请求参数的对应关系及其他要求
value & name - 互为别名。相当于一个属性。 代表请求的参数名字。只能描述普通参数。忽略方法参数名称,使用配置的请求参数名称处理
required - boolean类型的属性。代表这个请求参数是否是必要的。默认值是true。如果未传递此参数,400系列错误
defaultValue - 默认值。仅在未传递请求参数时生效。给方法参数提供默认值
注意:这个请求参数的值,不符合Java习惯,统称未传递请求参数。
如: 数学类型的转换异常, 仅在 "" 或 null转换数学类型时生效。 其他具体值,默认值无效
如: 字符串转换,仅在 "" 或 null 时默认值生效
如: 日期转换, 仅在 "" 或 null 时默认值生效
【6】获取Servlet相关对象
@RequestMapping ( "/testServlet" )
public String testServlet (
HttpServletRequest request,
HttpServletResponse response,
HttpSession session
) {
System . out. println ( request) ;
System . out. println ( request. getParameter ( "name" ) ) ;
System . out. println ( response) ;
System . out. println ( session) ;
System . out. println ( session. getAttribute ( "name" ) ) ;
System . out. println ( request. getServletContext ( ) ) ;
return "/index.jsp" ;
}
【7】请求头获取
@RequestMapping ( "/testHeader" )
public String testHeader ( @RequestHeader String Accept ,
@RequestHeader String connection,
@RequestHeader ( value = "host" ) String host,
@RequestHeader ( "Accept-Encoding" ) String h) {
System . out. println ( "accept = " + Accept ) ;
System . out. println ( "connection = " + connection) ;
System . out. println ( "host = " + host) ;
System . out. println ( "accept-encoding = " + h) ;
return "/index.jsp" ;
}
【8】 请求转发和响应重定向
在SpringMVC的控制单元中,方法定义返回类型可以有多种。理论上是返回任意类型都对。包括void。
忽略AJAX请求处理方式,请求转发和响应重定向对应的控制单元返回值类型包括:
1. String - 返回的字符串,默认就是结果视图的地址。
默认是请求转发。实际上,类似指定请求转发方案 forward:/path
响应重定向: redirect:/path
2. ModelAndView - 使用Model传递请求作用域数据,使用view传递结果视图地址。
默认的结果视图地址就是请求转发,可以使用类似的功能语法 forward:/path 提供viewName
可以使用redirect:/path 提供重定向viewName
如果使用ModelAndView实现重定向,那么其中的model请求作用域数据,会自动转换成同名请求参数传递
3. void - 使用ServletAPI实现请求转发和重定
注意:如果结果路径是其他的控制器RequestMapping地址,编程方式和普通视图返回处理一致。
注意:如果返回的路径使用forward:或redirect:开头,路径和前缀一定要紧挨在一起
注意:所有的返回结果地址,建议都使用 '/' 开头,都是相对应服务器的根开始寻址。准确。
@RequestMapping ( "/servletRedirect" )
public void servletRedirect ( HttpServletResponse response) throws IOException , ServletException {
System . out. println ( "servletRedirect运行" ) ;
response. sendRedirect ( "/index.jsp" ) ;
}
@RequestMapping ( "/servletForward" )
public void servletForward ( HttpServletRequest request, HttpServletResponse response) throws IOException , ServletException {
System . out. println ( "servletForward运行" ) ;
request. getRequestDispatcher ( "/index.jsp" ) . forward ( request, response) ;
}
@RequestMapping ( "/redirectMV" )
public ModelAndView redirectMV ( ) {
System . out. println ( "redirectMV运行" ) ;
ModelAndView mv = new ModelAndView ( ) ;
mv. addObject ( "t" , "测试重定向" ) ;
mv. setViewName ( "redirect:/index.jsp" ) ;
return mv;
}
@RequestMapping ( "/forwardMV" )
public ModelAndView forwardMV ( ) {
System . out. println ( "forwardMV运行" ) ;
ModelAndView mv = new ModelAndView ( ) ;
mv. addObject ( "t" , "测试数据传递" ) ;
mv. setViewName ( "forward:/index.jsp" ) ;
return mv;
}
@RequestMapping ( "/testRedirect" )
public String testRedirect ( ) {
System . out. println ( "testRedirect方法运行" ) ;
return "redirect:/index.jsp" ;
}
@RequestMapping ( "/testForward" )
public String testForward ( ) {
System . out. println ( "testForward方法运行" ) ;
return "forward:/index.jsp" ;
}
【9】控制器中的方法返回值
1. void - 没有返回值。在只有@RequestMapping注解修饰方法的时候,代表返回的结果地址就是当前请求地址。
相对路径是,最近一次请求的上级地址。
如: 请求地址是 localhost:8080/add, 返回结果是 /add
如: 请求地址是 localhost:8080/bjsxt/add, 返回结果是 /bjsxt/bjsxt/add
当类型上没有RequestMapping注解定义统一的地址前缀时,方法返回值类型是void,会产生无限递归。
2. String - 只有RequestMapping注解修饰方法,代表返回的字符串,就是要显示的视图地址。默认请求转发。
如果返回地址是 path, 相对于,最近请求的上级地址。 不推荐的写法。
如果返回地址是 /path, 相对于应用的根。 建议写法
3. ModelAndView - SpringMVC通用返回结果类型。使用viewName属性确定视图结果地址。
model决定请求作用域数据。
【10】视图解析器
用于视图跳转
如果JSP视图隐藏,一般都会保存到同一个隐藏保护目录中
如: /WEB-INF/jsp/ 中保存所有的JSP文件
/WEB-INF/jsp/users/ 中保存所有和用户相关的JSP
/WEB-INF/jsp/admin/ 中保存素有和管理员相关的JSP等。
所有的视图都是JSP文件
所有的视图地址有统一的前缀: /WEB-INF/jsp/
有统一的后缀: .jsp
如果可以提供前后缀拼接处理,则方法只需要返回中间变化的部分即可。
如果请求转发的视图,需要忽略视图解析器中的统一前后缀,可以增加返回字符串viewName的前缀 forward:
<?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
https://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"
default-autowire = " default" >
< context: component-scan base-package = " com.bjsxt.controller" > </ context: component-scan>
< mvc: annotation-driven> </ mvc: annotation-driven>
< bean id = " viewResolver" class = " org.springframework.web.servlet.view.InternalResourceViewResolver" >
</ bean>
</ beans>
@RequestMapping ( "/toSuibian" )
public String toSuibian ( ) {
System . out. println ( "跳转到/WEB-INF/jsp/suibian.jsp" ) ;
return "/WEB-INF/jsp/suibian.jsp" ;
}
@RequestMapping ( "/toSuibian2" )
public String toSuibian2 ( ) {
System . out. println ( "toSuibian2() 运行了" ) ;
return "/toSuibian" ;
}
@RequestMapping ( "/toSuibian3" )
public String toSuibian3 ( ) {
System . out. println ( "toSuibian3() 运行了" ) ;
return "/WEB-INF/jsp/suibian.jsp" ;
}
【11】变量作用域
请求变量作用域: request
设置:
1. 使用ModelAndView : 使用Model传递数据
2. 使用控制单元(方法)参数,Map类型的参数。 直接在方法参数表中定义Map类型的参数,put的键值对,自动传递到请求作用域
3. 使用控制单元参数, Model类型的参数。 在方法参数表中定义Model类型的参数,调用add系列方法,自动传递到请求作用域。
4. 使用ServletAPI, request.setAttribute。 Servlet原生API。
取值
1. 使用ServletAPI, request.getAttribute
2. 使用方法参数 + 注解 @RequestAttribute,让SpringMVC帮助从请求作用域中获取attribute。
会话变量作用域: session
设置:
1. 只能通过ServletAPI实现。
取值:
1. 使用ServletAPI获取, request.getSession().getAttribute() 或者 session.getAttribute()
2. 使用方法参数 + 注解 @SessionAttribute 实现
应用上下文变量作用域: application。避免全局直接使用,存在的安全隐患。 不推荐使用。
设置:
1. 使用ServletAPI实现。 request.getServletContext().setAttribute()
取值:
1. 使用ServletAPI实现。 request.getServletContext().getAttribute()
@RequestMapping ( "/getAppScope" )
public String getAppScope ( HttpServletRequest request) {
System . out. println ( "application app = " + request. getServletContext ( ) . getAttribute ( "app" ) ) ;
return "/index.jsp" ;
}
@RequestMapping ( "/applicationScope" )
public String applicationScope ( HttpServletRequest request) {
request. getServletContext ( ) . setAttribute ( "app" , "通过application传递的数据" ) ;
return "/index.jsp" ;
}
@RequestMapping ( "/getSessionScope" )
public String getSessionScope ( @SessionAttribute ( "session1" ) String session1,
@SessionAttribute String session2) {
System . out. println ( "session1 = " + session1) ;
System . out. println ( "session2 = " + session2) ;
return "/index.jsp" ;
}
@RequestMapping ( "/sessionScope" )
public String sessionScope ( HttpServletRequest request, HttpSession session) {
request. getSession ( ) . setAttribute ( "session1" , "基于request.getSession.setAttribute传递" ) ;
session. setAttribute ( "session2" , "基于session.setAttribute传递" ) ;
return "/index.jsp" ;
}
@RequestMapping ( "/getReqScope" )
public String getReqScope ( @RequestAttribute ( "msg" ) String msg,
@RequestAttribute String testMap) {
System . out. println ( "请求作用域: msg = " + msg) ;
System . out. println ( "请求作用域: testMap = " + testMap) ;
return "/index.jsp" ;
}
@RequestMapping ( "/reqScopeModel" )
public String reqScoopeModel ( Model model) {
System . out. println ( model. getClass ( ) . getName ( ) ) ;
model. addAttribute ( "msg" , "使用Model传递的数据" ) ;
Map < String , Object > attrs = new HashMap < > ( ) ;
attrs. put ( "testMap" , "测试使用addAllAttributes传递数据" ) ;
model. addAllAttributes ( attrs) ;
return "/bjsxt/getReqScope" ;
}
【12】静态资源放行
<?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" >
< context-param>
< param-name> contextConfigLocation</ param-name>
< param-value> classpath:applicationContext.xml</ param-value>
</ context-param>
< listener>
< listener-class> org.springframework.web.context.ContextLoaderListener</ listener-class>
</ listener>
< filter>
< filter-name> charset</ 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> charset</ filter-name>
< url-pattern> /*</ url-pattern>
</ filter-mapping>
< servlet>
< servlet-name> mvc</ servlet-name>
< servlet-class> org.springframework.web.servlet.DispatcherServlet</ servlet-class>
< init-param>
< param-name> contextConfigLocation</ param-name>
< param-value> classpath:spring-mvc.xml</ param-value>
</ init-param>
< load-on-startup> 1</ load-on-startup>
</ servlet>
< servlet-mapping>
< servlet-name> mvc</ servlet-name>
< url-pattern> /</ url-pattern>
</ servlet-mapping>
</ web-app>
<?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
https://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"
default-autowire = " default" >
< context: component-scan base-package = " com.bjsxt.controller" > </ context: component-scan>
< mvc: annotation-driven> </ mvc: annotation-driven>
< mvc: resources mapping = " /pic/**" location = " /pic/" > </ mvc: resources>
< mvc: resources mapping = " /pic2/**" location = " /WEB-INF/pic/" > </ mvc: resources>
< bean id = " viewResolver" class = " org.springframework.web.servlet.view.InternalResourceViewResolver" >
</ bean>
</ beans>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<img src="/pic2/2.webp">
<img src="/pic/webp/1.webp">
<h3>这是springmvc返回的视图</h3>
<h3>请求作用域 msg : ${requestScope.msg}</h3>
<h3>请求作用域 testMap : ${requestScope.testMap}</h3>
<h3>会话作用域 session1 : ${sessionScope.session1}</h3>
<h3>会话作用域 session2 : ${sessionScope.session2}</h3>
<h3>上下文作用域 app : ${applicationScope.app}</h3>
<img src="/pic/1.webp">
</body>
</html>
【13】Restful请求格式
Rest(Representational State Transfer:表现层状态转译)是一种软件架构风格,其核心是面向资源的一种设计。
Restful的出现同时也解决了客户端的种类多种多样造成请求的格式比较混乱的问题,Restful提供了一种统一的前后端交互的接口规范,可以更好的实现数据的交互。
通俗讲就是每个资源都有一个url地址,而不是不同的操作有不同的url地址。
package com. bjsxt. controller ;
import org. springframework. stereotype. Controller ;
import org. springframework. web. bind. annotation. GetMapping ;
import org. springframework. web. bind. annotation. PathVariable ;
@Controller
public class PageDispatcherController {
@GetMapping ( "/page/{model}/{view}" )
public String dispatch ( @PathVariable String model, @PathVariable String view) {
String path = "/" ;
if ( ! model. equals ( "root" ) ) {
path += ( model + "/" ) ;
}
path += ( view + ".jsp" ) ;
return path;
}
}
package com. bjsxt. controller ;
import com. bjsxt. pojo. User ;
import org. springframework. stereotype. Controller ;
import org. springframework. web. bind. annotation. * ;
@Controller
public class TestRestController {
@PostMapping ( "/user" )
public String addUser ( User user) {
System . out. println ( "新增 : " + user) ;
return "/index.jsp" ;
}
@DeleteMapping ( "/user/{suibian}" )
@ResponseBody
public String removeUser ( @PathVariable ( "suibian" ) Integer id) {
System . out. println ( "删除: " + id) ;
return "删除成功" ;
}
@PutMapping ( "/user/{id}/{name}" )
@ResponseBody
public String modifyUser ( @PathVariable Integer id, @PathVariable String name) {
System . out. println ( "修改:id = " + id + " , name = " + name) ;
return "修改" ;
}
@GetMapping ( "/user/{id}" )
public String getUser ( @PathVariable Integer id) {
System . out. println ( "查询 : " + id) ;
return "/index.jsp" ;
}
}
【14】@ResponseBody注解
package com. bjsxt. controller ;
import com. bjsxt. pojo. User ;
import org. springframework. stereotype. Controller ;
import org. springframework. web. bind. annotation. GetMapping ;
import org. springframework. web. bind. annotation. ResponseBody ;
import org. springframework. web. bind. annotation. RestController ;
import java. util. * ;
@RestController
public class TestResponseBodyController {
@GetMapping ( "/testSet" )
public Set < User > testSet ( ) {
System . out. println ( "返回Set集合" ) ;
Set < User > set = new HashSet < > ( ) ;
set. add ( new User ( 1 , "吕布" ) ) ;
set. add ( new User ( 2 , "貂蝉" ) ) ;
return set;
}
@GetMapping ( "/testList" )
public List < User > testList ( ) {
System . out. println ( "返回List集合" ) ;
List < User > list = new ArrayList < > ( ) ;
list. add ( new User ( 1 , "关羽" ) ) ;
list. add ( new User ( 2 , "张飞" ) ) ;
list. add ( new User ( 3 , "刘备" ) ) ;
return list;
}
@GetMapping ( "/testMap" )
public Map < String , Object > testMap ( ) {
System . out. println ( "返回Map集合" ) ;
Map < String , Object > map = new HashMap < > ( ) ;
map. put ( "name" , "李四" ) ;
map. put ( "gender" , "男" ) ;
return map;
}
@GetMapping ( "/testRef" )
public User testReturnReference ( ) {
System . out. println ( "返回引用类型对象" ) ;
User user = new User ( ) ;
user. setId ( 10 ) ;
user. setName ( "张三" ) ;
return user;
}
@GetMapping ( value = "/testStr" , produces = { "text/html; charset=UTF-8" } )
public String testReturnString ( ) {
System . out. println ( "返回字符串" ) ;
return "返回值" ;
}
@GetMapping ( value = "/testInt" , produces = { "application/json; charset=UTF-8" } )
public int testReturnInt ( ) {
System . out. println ( "测试返回整数" ) ;
return 1 ;
}
}
<?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" >
< parent>
< artifactId> sj125_springmvc</ artifactId>
< groupId> com.bjsxt</ groupId>
< version> 1.0-SNAPSHOT</ version>
</ parent>
< modelVersion> 4.0.0</ modelVersion>
< artifactId> sj125_springmvc_2</ artifactId>
< packaging> war</ packaging>
< dependencies>
< dependency>
< groupId> javax.servlet</ groupId>
< artifactId> javax.servlet-api</ artifactId>
< version> 4.0.1</ version>
< scope> provided</ scope>
</ dependency>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-webmvc</ artifactId>
< version> 5.3.20</ version>
</ dependency>
< dependency>
< groupId> org.aspectj</ groupId>
< artifactId> aspectjweaver</ artifactId>
< version> 1.9.9.1</ version>
< scope> runtime</ scope>
</ dependency>
< dependency>
< groupId> com.fasterxml.jackson.core</ groupId>
< artifactId> jackson-databind</ artifactId>
< version> 2.9.10.8</ version>
</ dependency>
</ dependencies>
< pluginRepositories>
< pluginRepository>
< id> mvnrepository</ id>
< url> https://artifacts.alfresco.com/nexus/content/repositories/public/</ url>
</ pluginRepository>
</ pluginRepositories>
< build>
< plugins>
< plugin>
< groupId> org.apache.tomcat.maven</ groupId>
< artifactId> tomcat8-maven-plugin</ artifactId>
< version> 3.0-r1756463</ version>
< configuration>
< port> 80</ port>
< path> /</ path>
</ configuration>
</ plugin>
</ plugins>
</ build>
</ project>
【15】@RequestBody注解
在客户端中无论使用的是`<form>`表单,还是Ajax请求,默认的请求时内容类型都是application/x-www-form-urlencoded,DataFormate 中 数据请求参数用&连接。eg: ie=utf-8&mod=1
package com. bjsxt. controller ;
import com. bjsxt. pojo. User ;
import org. springframework. web. bind. annotation. PostMapping ;
import org. springframework. web. bind. annotation. RequestBody ;
import org. springframework. web. bind. annotation. RestController ;
import java. util. List ;
import java. util. Map ;
@RestController
public class TestRequestBodyController {
@PostMapping ( "/testRequestBodyUser" )
public User testRequestBody1 ( @RequestBody User user) {
System . out. println ( user) ;
return user;
}
@PostMapping ( "/listUser" )
public List < User > listUser ( @RequestBody List < User > userList) {
System . out. println ( userList) ;
return userList;
}
@PostMapping ( "/listMap" )
public List < Map < String , Object > > listMap ( @RequestBody List < Map < String , Object > > listMap) {
System . out. println ( listMap) ;
return listMap;
}
@PostMapping ( "/map" )
public Map < String , Object > map ( @RequestBody Map < String , Object > map) {
System . out. println ( map) ;
return map;
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="/js/jquery.js"></script>
<script>
/**
* 当请求content-type=application/json时,
* 使用ajax发起请求,一定要设置dataType(响应数据类型)。
* 只有content-type和dataType同时设置,请求体参数,才会封装成json对象。
* 否则都是 参数名=参数值&参数名=参数值 的字符串|表单域。
*
* 请求参数JSON对象,被AJAX处理后,转换成了名值对表单参数。
* 使用JSON.stringify(JSON对象),手工转换对象成为JSON格式字符串。可以实现请求体传递JSON格式字符串。
*
* JSON.stringify(JSON对象) - 是把参数对象,转换成JSON格式字符串的方法。
* JSON对象 {"id":1, "name":"admin"}
* JSON格式字符串是 "{\"id\":1, \"name\":\"admin\"}" '{"id":1, "name":"admin"}'
*
*/
$(function () {
$("#btn").on('click', function () {
var data = {"id":$("#id").val(), "name":$("#name").val()};
$.ajax({
'url' : '/testRequestBodyUser',
'type' : 'post',
'contentType' : "application/json",
'data' : JSON.stringify(data),
//'data' : '{"id":3, "name":"abc"}',
'success' : function (data) {
alert(data);
},
'dataType':'json' // 响应的
});
})
$("#mapBtn").on('click', function () {
var data = {"name":"张三", "gender" : "男"};
$.ajax({
'url': '/map',
'type': 'post',
'data':JSON.stringify(data),
'contentType': 'application/json',
'dataType': 'json',
'success': function (data) {
alert(data);
}
});
})
$("#listMapBtn").on('click', function () {
var data = [];
data.push({"name":"李四", "gender":"男"});
data.push({"name":"王五", "gender":"男"});
$.ajax({
'url': '/listMap',
'type': 'post',
'data':JSON.stringify(data),
'contentType': 'application/json',
'dataType': 'json',
'success': function (data) {
alert(data);
}
});
})
$("#listUserBtn").on('click', function () {
var data = [];
data.push({"id":1, "name":"赵四"});
data.push({"id":2, "name":"刘能"});
$.ajax({
'url': '/listUser',
'type': 'post',
'data':JSON.stringify(data),
'contentType': 'application/json',
'dataType': 'json',
'success': function (data) {
alert(data);
}
});
})
});
</script>
</head>
<body>
<div style="width: 800px; margin:auto">
<form method="post" action="/testRequestBodyUser">
主键:<input type="text" name="id" id="id"><br>
姓名:<input type="text" name="name" id="name"><br>
<input type="button" value="提交" id="btn">
</form>
<input type="button" value="测试Map" id="mapBtn"><br>
<input type="button" value="测试List<Map>" id="listMapBtn"><br>
<input type="button" value="测试List<User>" id="listUserBtn">
</div>
</body>
</html>
【16】SpringMVC中文乱码问题
Spring MVC默认没有去解决中文乱码问题。需要根据请求的方式的类型去选择对应的中文乱码解决方案。常见的两种请求方式就是GET和POST
GET方式中文乱码解决
GET方式中文乱码需要开发者自己进行转码。因为Tomcat默认的接收请求GET方式的是IOS-8859-1,所以无论客户端传递过来的数据是哪种编码方式,都会被Tomcat转换为ISO-8859-1.如果希望正确的显示中文,还需要把内容转换为UTF-8编码。
POST方式中文乱码解决
在Spring MVC提供了一个类CharacterEncodingFilter,里面直接写好了POST方式中文乱码解决代码
@RequestMapping ( "/testEncoding" )
public String testEncoding ( String name) throws UnsupportedEncodingException {
System . out. println ( "接收到name:" + name) ;
String newName = new String ( name. getBytes ( "iso-8859-1" ) , "utf-8" ) ;
System . out. println ( "转换后的name:" + newName) ;
return "suiyi" ;
}
< filter>
< filter-name> code</ 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> code</ filter-name>
< url-pattern> /*</ url-pattern>
</ filter-mapping>
【17】文件上传
Spring MVC 文件上传有如下几点要求:
1)客户端:
请求方式必须是POST
enctype必须为multipart/form-data
2)服务端:
必须配置MultipartResovler。否则无法解析上传文件的流数据。(<bean>的id值必须叫做multipartResovler)如果没有配置MultipartResovler不仅仅是文件流数据无法解析,连带着其他表单域数据也无法解析。因为文件流数据和表单数据都在请求体中,不解析的话,文件流数据和表单数据都接收不到
注意文件域的name取值,文件域必须MultipartFile类型接收。且name的取值必须和MultipartFile对象名相同
<?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" >
< parent>
< artifactId> sj125_springmvc</ artifactId>
< groupId> com.bjsxt</ groupId>
< version> 1.0-SNAPSHOT</ version>
</ parent>
< modelVersion> 4.0.0</ modelVersion>
< artifactId> sj125_springmvc_2</ artifactId>
< packaging> war</ packaging>
< dependencies>
< dependency>
< groupId> javax.servlet</ groupId>
< artifactId> javax.servlet-api</ artifactId>
< version> 4.0.1</ version>
< scope> provided</ scope>
</ dependency>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-webmvc</ artifactId>
< version> 5.3.20</ version>
</ dependency>
< dependency>
< groupId> org.aspectj</ groupId>
< artifactId> aspectjweaver</ artifactId>
< version> 1.9.9.1</ version>
< scope> runtime</ scope>
</ dependency>
< dependency>
< groupId> com.fasterxml.jackson.core</ groupId>
< artifactId> jackson-databind</ artifactId>
< version> 2.9.10.8</ version>
</ dependency>
< dependency>
< groupId> commons-fileupload</ groupId>
< artifactId> commons-fileupload</ artifactId>
< version> 1.4</ version>
</ dependency>
</ dependencies>
< pluginRepositories>
< pluginRepository>
< id> mvnrepository</ id>
< url> https://artifacts.alfresco.com/nexus/content/repositories/public/</ url>
</ pluginRepository>
</ pluginRepositories>
< build>
< plugins>
< plugin>
< groupId> org.apache.tomcat.maven</ groupId>
< artifactId> tomcat8-maven-plugin</ artifactId>
< version> 3.0-r1756463</ version>
< configuration>
< port> 80</ port>
< path> /</ path>
</ configuration>
</ plugin>
</ plugins>
</ build>
</ project>
<?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
https://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"
default-autowire = " default" >
< context: component-scan base-package = " com.bjsxt.controller" > </ context: component-scan>
< mvc: annotation-driven> </ mvc: annotation-driven>
< mvc: resources mapping = " /js/**" location = " /js/" > </ mvc: resources>
< bean id = " multipartResolver" class = " org.springframework.web.multipart.commons.CommonsMultipartResolver" >
< property name = " maxUploadSize" value = " 102400000000000" > </ property>
< property name = " defaultEncoding" value = " UTF-8" > </ property>
< property name = " maxInMemorySize" value = " 102400" > </ property>
</ bean>
</ beans>
package com. bjsxt. controller ;
import org. springframework. stereotype. Controller ;
import org. springframework. web. bind. annotation. RequestBody ;
import org. springframework. web. bind. annotation. RequestMapping ;
import org. springframework. web. bind. annotation. RequestParam ;
import org. springframework. web. bind. annotation. ResponseBody ;
import org. springframework. web. multipart. MultipartFile ;
import javax. servlet. http. HttpServletRequest ;
import java. io. File ;
import java. io. FileOutputStream ;
import java. io. InputStream ;
import java. util. UUID ;
@Controller
public class UploadFileController {
@RequestMapping ( "/upload" )
@ResponseBody
public String upload ( @RequestParam ( "uploadFile" ) MultipartFile file, HttpServletRequest request) throws Exception {
System . out. println ( "getName : " + file. getName ( ) ) ;
System . out. println ( "getOriginalFileName : " + file. getOriginalFilename ( ) ) ;
System . out. println ( "getInputStream : " + file. getInputStream ( ) ) ;
String type = file. getOriginalFilename ( ) . substring ( file. getOriginalFilename ( ) . lastIndexOf ( "." ) ) ;
if ( ! ".png" . equalsIgnoreCase ( type) ) {
return "error file type" ;
}
String originalFileName = file. getOriginalFilename ( ) ;
String suffix = originalFileName. substring ( originalFileName. lastIndexOf ( "." ) ) ;
String fileName = UUID . randomUUID ( ) . toString ( ) + suffix;
String dir = request. getServletContext ( ) . getRealPath ( "/images/" ) ;
System . out. println ( dir) ;
File dirFile = new File ( dir) ;
if ( ! dirFile. exists ( ) ) {
dirFile. mkdir ( ) ;
}
FileOutputStream outputStream = new FileOutputStream ( dir + "\\" + fileName) ;
InputStream inputStream = file. getInputStream ( ) ;
byte [ ] tmp = new byte [ 1024 ] ;
int length = 0 ;
while ( ( length = inputStream. read ( tmp) ) != - 1 ) {
outputStream. write ( tmp, 0 , length) ;
}
outputStream. close ( ) ;
return "upload finish" ;
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<div style="width: 800px; margin:auto">
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="uploadFile">
<br>
<input type="submit" value="上传">
</form>
</div>
</body>
</html>
【18】文件上传和下载案例
功能如下:
1. 实现文件上传
2. 上传成功后的结果,响应重定向到控制器path地址。 地址是 /showAllPic
3. 新增showAllPic功能。访问控制器,调用服务,调用mapper,查询数据库中所有已上传的文件数据,并在
show.jsp页面中显示全部信息。
4. 修改show.jsp中的显示效果。把图片的地址修改成在线预览图片内容。也就是<img src="pic.path">标签
增加控制方法,路径地址是 /pic, 参数名是path,值是图片地址。由服务器返回图片内容。
5. 修改show.jsp中的显示效果。给图片名称增加超链接,使用新页面的形式打开超链接。实现下载图片。
要求:下载的文件的名字是上传的文件原始名字。
下载地址是 /download, 请求参数是 id,值是图片的主键。
从数据库查询图片完整信息,把服务磁盘中的文件读取并写到客户端,实现下载。数据库中的原始名称
是下载的文件名字
文件下载:
服务器返回的响应头 content-disposition 默认值是inline,含义是:浏览器可以识别的资源直接显示。不能识别的资源,直接下载
<?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" >
< parent>
< artifactId> sj125_springmvc</ artifactId>
< groupId> com.bjsxt</ groupId>
< version> 1.0-SNAPSHOT</ version>
</ parent>
< modelVersion> 4.0.0</ modelVersion>
< artifactId> sj125_springmvc_3_homework</ artifactId>
< packaging> war</ packaging>
< dependencies>
< dependency>
< groupId> javax.servlet</ groupId>
< artifactId> javax.servlet-api</ artifactId>
< version> 4.0.1</ version>
< scope> provided</ scope>
</ dependency>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-webmvc</ artifactId>
< version> 5.3.20</ version>
</ dependency>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-jdbc</ artifactId>
< version> 5.3.20</ version>
</ dependency>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-tx</ artifactId>
< version> 5.3.20</ version>
</ dependency>
< dependency>
< groupId> org.aspectj</ groupId>
< artifactId> aspectjweaver</ artifactId>
< version> 1.9.9.1</ version>
< scope> runtime</ scope>
</ dependency>
< dependency>
< groupId> com.fasterxml.jackson.core</ groupId>
< artifactId> jackson-databind</ artifactId>
< version> 2.9.10.8</ version>
</ dependency>
< dependency>
< groupId> commons-fileupload</ groupId>
< artifactId> commons-fileupload</ artifactId>
< version> 1.4</ version>
</ dependency>
< dependency>
< groupId> mysql</ groupId>
< artifactId> mysql-connector-java</ artifactId>
< version> 8.0.29</ version>
</ dependency>
< dependency>
< groupId> org.mybatis</ groupId>
< artifactId> mybatis</ artifactId>
< version> 3.5.9</ version>
</ dependency>
< dependency>
< groupId> org.mybatis</ groupId>
< artifactId> mybatis-spring</ artifactId>
< version> 2.0.7</ version>
</ dependency>
< dependency>
< groupId> javax.servlet</ groupId>
< artifactId> jstl</ artifactId>
< version> 1.2</ version>
</ dependency>
</ dependencies>
< pluginRepositories>
< pluginRepository>
< id> mvnrepository</ id>
< url> https://artifacts.alfresco.com/nexus/content/repositories/public/</ url>
</ pluginRepository>
</ pluginRepositories>
< build>
< plugins>
< plugin>
< groupId> org.apache.tomcat.maven</ groupId>
< artifactId> tomcat8-maven-plugin</ artifactId>
< version> 3.0-r1756463</ version>
< configuration>
< port> 80</ port>
< path> /</ path>
</ configuration>
</ plugin>
</ plugins>
</ build>
</ project>
<?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" >
< welcome-file-list>
< welcome-file> index.jsp</ welcome-file>
</ welcome-file-list>
< context-param>
< param-name> contextConfigLocation</ param-name>
< param-value> classpath:spring/applicationContext-*.xml</ param-value>
</ context-param>
< listener>
< listener-class> org.springframework.web.context.ContextLoaderListener</ listener-class>
</ listener>
< filter>
< filter-name> charset</ 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> charset</ filter-name>
< url-pattern> /*</ url-pattern>
</ filter-mapping>
< servlet>
< servlet-name> mvc</ servlet-name>
< servlet-class> org.springframework.web.servlet.DispatcherServlet</ servlet-class>
< init-param>
< param-name> contextConfigLocation</ param-name>
< param-value> classpath:springmvc/applicationContext-mvc.xml</ param-value>
</ init-param>
< load-on-startup> 1</ load-on-startup>
</ servlet>
< servlet-mapping>
< servlet-name> mvc</ servlet-name>
< url-pattern> /</ url-pattern>
</ servlet-mapping>
</ web-app>
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd"
default-autowire = " default" >
< context: component-scan base-package = " com.bjsxt.service" > </ context: component-scan>
</ beans>
<?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: tx= " http://www.springframework.org/schema/tx"
xmlns: aop= " http://www.springframework.org/schema/aop"
xsi: schemaLocation= " http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd"
default-autowire = " default" >
< bean id = " dataSource" class = " org.springframework.jdbc.datasource.DriverManagerDataSource" >
< property name = " driverClassName" value = " com.mysql.cj.jdbc.Driver" />
< property name = " url" value = " jdbc:mysql://localhost:3306/mvc?serverTimezone=Asia/Shanghai" />
< property name = " username" value = " root" > </ property>
< property name = " password" value = " root" />
</ bean>
< bean id = " sqlSessionFactory" class = " org.mybatis.spring.SqlSessionFactoryBean" >
< property name = " dataSource" ref = " dataSource" />
< property name = " typeAliasesPackage" value = " com.bjsxt.pojo" />
< property name = " mapperLocations" value = " classpath:mappers/PicMapper.xml" />
</ bean>
< bean class = " org.mybatis.spring.mapper.MapperScannerConfigurer" >
< property name = " sqlSessionFactoryBeanName" value = " sqlSessionFactory" > </ property>
< property name = " basePackage" value = " com.bjsxt.mapper" />
</ bean>
< bean id = " transactionManager" class = " org.springframework.jdbc.datasource.DataSourceTransactionManager" >
< property name = " dataSource" ref = " dataSource" />
</ bean>
< tx: advice id = " txAdvice" transaction-manager = " transactionManager" >
< tx: attributes>
< tx: method name = " *" rollback-for = " java.lang.Exception" />
< tx: method name = " get*" read-only = " true" />
</ tx: attributes>
</ tx: advice>
< aop: config>
< aop: pointcut id = " txPc" expression = " execution( * com.bjsxt.service.*.* (..) )" />
< aop: advisor advice-ref = " txAdvice" pointcut-ref = " txPc" />
</ aop: config>
</ beans>
<?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
https://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"
default-autowire = " default" >
< context: component-scan base-package = " com.bjsxt.controll" > </ context: component-scan>
< mvc: annotation-driven> </ mvc: annotation-driven>
< mvc: resources mapping = " /dir/**" location = " /dir/" > </ mvc: resources>
< bean id = " multipartResolver" class = " org.springframework.web.multipart.commons.CommonsMultipartResolver" > </ bean>
</ beans>
package com. bjsxt. controll ;
import com. bjsxt. pojo. Pic ;
import com. bjsxt. service. PicService ;
import org. apache. commons. io. IOUtils ;
import org. springframework. beans. factory. annotation. Autowired ;
import org. springframework. stereotype. Controller ;
import org. springframework. web. bind. annotation. GetMapping ;
import org. springframework. web. bind. annotation. PostMapping ;
import org. springframework. web. bind. annotation. RequestMapping ;
import org. springframework. web. bind. annotation. ResponseBody ;
import org. springframework. web. multipart. MultipartFile ;
import javax. servlet. ServletOutputStream ;
import javax. servlet. http. HttpServletRequest ;
import javax. servlet. http. HttpServletResponse ;
import javax. servlet. http. HttpSession ;
import java. io. FileInputStream ;
import java. io. IOException ;
import java. io. OutputStream ;
import java. util. List ;
@Controller
public class PicController {
@Autowired
private PicService picService;
@GetMapping ( "/download" )
public void download ( Integer id, HttpServletResponse response) {
try {
Pic pic = picService. getById ( id) ;
FileInputStream inputStream = new FileInputStream ( pic. getPath ( ) ) ;
OutputStream outputStream = response. getOutputStream ( ) ;
response. setContentType ( "application/octet-stream" ) ;
response. setHeader ( "content-disposition" , "attachment;filename=" + pic. getOriginalName ( ) ) ;
IOUtils . copy ( inputStream, outputStream) ;
outputStream. flush ( ) ;
inputStream. close ( ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
@GetMapping ( "/pic" )
public void showOnline ( String path, HttpServletResponse response) {
try {
FileInputStream inputStream = new FileInputStream ( path) ;
ServletOutputStream outputStream = response. getOutputStream ( ) ;
IOUtils . copy ( inputStream, outputStream) ;
outputStream. flush ( ) ;
inputStream. close ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
try {
response. getOutputStream ( ) . flush ( ) ;
} catch ( Exception e1) {
e1. printStackTrace ( ) ;
}
}
}
@GetMapping ( "/showAllPic" )
public String showPic ( HttpSession session) {
List < Pic > list = picService. getAll ( ) ;
session. setAttribute ( "list" , list) ;
return "redirect:/show.jsp" ;
}
@PostMapping ( value = "/uploadFile" , produces = { "text/html; charset=UTF-8" } )
public String uploadFile ( MultipartFile uploadFile, HttpServletRequest request) {
try {
int flag = picService. uploadPic ( uploadFile, request) ;
if ( flag == - 1 ) {
return "redirect:/uploadFail.jsp" ;
}
return "redirect:/showAllPic" ;
} catch ( RuntimeException e) {
e. printStackTrace ( ) ;
return "redirect:/uploadFail.jsp" ;
}
}
}
package com. bjsxt. service ;
import com. bjsxt. pojo. Pic ;
import org. springframework. web. multipart. MultipartFile ;
import javax. servlet. http. HttpServletRequest ;
import java. util. List ;
public interface PicService {
Pic getById ( Integer id) ;
List < Pic > getAll ( ) ;
int uploadPic ( MultipartFile uploadFile, HttpServletRequest request) ;
}
package com. bjsxt. service. impl ;
import com. bjsxt. mapper. PicMapper ;
import com. bjsxt. pojo. Pic ;
import com. bjsxt. service. PicService ;
import org. springframework. beans. factory. annotation. Autowired ;
import org. springframework. stereotype. Service ;
import org. springframework. web. multipart. MultipartFile ;
import javax. servlet. http. HttpServletRequest ;
import java. io. File ;
import java. io. IOException ;
import java. util. List ;
import java. util. UUID ;
@Service
public class PicServiceImpl implements PicService {
@Autowired
private PicMapper picMapper;
@Override
public Pic getById ( Integer id) {
return picMapper. selectById ( id) ;
}
@Override
public List < Pic > getAll ( ) {
return picMapper. selectAll ( ) ;
}
@Override
public int uploadPic ( MultipartFile uploadFile, HttpServletRequest request) {
String dirPath = null ;
String fileName = null ;
try {
dirPath = request. getServletContext ( ) . getRealPath ( "/images/" ) ;
File dir = new File ( dirPath) ;
if ( ! dir. exists ( ) ) {
dir. mkdir ( ) ;
}
fileName = UUID . randomUUID ( ) . toString ( ) ;
String originalFileName = uploadFile. getOriginalFilename ( ) ;
String suffix = originalFileName. substring ( originalFileName. lastIndexOf ( "." ) ) ;
fileName += suffix;
uploadFile. transferTo ( new File ( dir, fileName) ) ;
Pic pic = new Pic ( ) ;
pic. setOriginalName ( originalFileName) ;
pic. setPath ( dirPath + File . separator + fileName) ;
picMapper. insertPic ( pic) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
return - 1 ;
} catch ( RuntimeException e) {
e. printStackTrace ( ) ;
File file = new File ( dirPath+ "/" + fileName) ;
file. delete ( ) ;
throw e;
}
return 1 ;
}
}
package com. bjsxt. mapper ;
import com. bjsxt. pojo. Pic ;
import java. util. List ;
public interface PicMapper {
Pic selectById ( Integer id) ;
int insertPic ( Pic pic) ;
List < Pic > selectAll ( ) ;
}
package com. bjsxt. pojo ;
import java. io. Serializable ;
import java. util. Objects ;
public class Pic implements Serializable {
private Integer id;
private String originalName;
private String path;
public Pic ( ) {
}
@Override
public String toString ( ) {
return "Pic{" +
"id=" + id +
", originalName='" + originalName + '\'' +
", path='" + path + '\'' +
'}' ;
}
@Override
public boolean equals ( Object o) {
if ( this == o) return true ;
if ( o == null || getClass ( ) != o. getClass ( ) ) return false ;
Pic pic = ( Pic ) o;
return Objects . equals ( id, pic. id) &&
Objects . equals ( originalName, pic. originalName) &&
Objects . equals ( path, pic. path) ;
}
@Override
public int hashCode ( ) {
return Objects . hash ( id, originalName, path) ;
}
public Integer getId ( ) {
return id;
}
public void setId ( Integer id) {
this . id = id;
}
public String getOriginalName ( ) {
return originalName;
}
public void setOriginalName ( String originalName) {
this . originalName = originalName;
}
public String getPath ( ) {
return path;
}
public void setPath ( String path) {
this . path = path;
}
}
【19】getRealPath()
【20】跨域@CrossOrigin
当前项目的协议、ip、端口和访问的URL的协议、IP、端口中有一个不同,这种访问就叫跨域
只要在控制单元方法上添加了@CrossOrigin注解后,会在响应头中添加Access-Control-Allow-Origin:*
Access-Control-Allow-Origin是HTTP协议中允许哪些IP的项目跨域访问,*表示所有IP
@GetMapping ( value = "/test" , produces = { "text/html; charset=UTF-8" } )
@ResponseBody
@CrossOrigin
public String test ( HttpServletResponse response, String flag) throws IOException {
System . out. println ( "test方法运行" ) ;
if ( flag == null ) {
throw new IOException ( "测试其他异常" ) ;
}
return "test方法返回结果" ;
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="/js/jquery.js"></script>
<script>
$(function () {
$("#btn81").click(function () {
// 同源访问,不是跨域
$.ajax({
'url': '/test',
'type': 'get',
'success': function (data) {
alert(data);
}
});
})
$("#btn80").click(function () {
// 跨域访问
$.ajax({
'url': 'http://localhost:80/test',
'type': 'get',
'success': function (data) {
alert(data);
}
});
})
});
</script>
</head>
<body>
<h3>测试页面</h3>
<input type="button" value="访问81端口test" id="btn81">
<br>
<input type="button" value="访问80端口test" id="btn80">
</body>
</html>
<?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
https://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"
default-autowire = " default" >
< context: component-scan base-package = " com.bjsxt.controller" > </ context: component-scan>
< mvc: annotation-driven> </ mvc: annotation-driven>
< bean id = " multipartResolver" class = " org.springframework.web.multipart.commons.CommonsMultipartResolver" > </ bean>
< mvc: resources mapping = " /js/**" location = " /js/" > </ mvc: resources>
</ beans>
【21】拦截器
Servlet 中过滤器的作用是保护请求的服务器资源,在请求资源被执行之前,如果请求地址符合拦截范围,则会先执行过滤器
SpringMVC 中Servlet只有一个是DisptcherServlet,如果仍然使用过滤器来完成请求的拦截,就会造成拦截DispatcherServlet所有的请求。那么,如果部分请求不想被拦截,SpringMVC的拦截器来实现单元方法的拦截
拦截器的执行是在DispatcherServlet之后和单元方法之前的,这样我们就可以在单元方法被之前之前对请求进行自定义的拦截处理了
注意:只有URL匹配到了控制单元,拦截器才能生效
package com. bjsxt. interceptor ;
import org. springframework. web. servlet. HandlerInterceptor ;
import org. springframework. web. servlet. ModelAndView ;
import javax. servlet. http. HttpServletRequest ;
import javax. servlet. http. HttpServletResponse ;
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle ( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System . out. println ( "第一个拦截器, preHandle方法, handler = " + handler + " , handler类型 : " + handler. getClass ( ) . getName ( ) ) ;
return true ;
}
@Override
public void postHandle ( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System . out. println ( "第一个拦截器,postHandle方法, handler = " + handler + " , handler 类型 : " +
handler. getClass ( ) . getName ( ) + " , modelAndView = " + modelAndView) ;
}
@Override
public void afterCompletion ( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System . out. println ( "第一个拦截器,afterCompletion方法, handler = " + handler + " , handler类型 : " + handler. getClass ( ) . getName ( )
+ " , ex = " + ex) ;
}
}
<?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
https://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"
default-autowire = " default" >
< context: component-scan base-package = " com.bjsxt.controller" > </ context: component-scan>
< mvc: annotation-driven > </ mvc: annotation-driven>
< bean id = " multipartResolver" class = " org.springframework.web.multipart.commons.CommonsMultipartResolver" > </ bean>
< mvc: interceptors>
< mvc: interceptor>
< mvc: mapping path = " /**" />
< bean class = " com.bjsxt.interceptor.ThirdInterceptor" > </ bean>
</ mvc: interceptor>
< bean class = " com.bjsxt.interceptor.FirstInterceptor" > </ bean>
< mvc: interceptor>
< mvc: mapping path = " /test" />
< mvc: exclude-mapping path = " /register" />
< bean class = " com.bjsxt.interceptor.SecondInterceptor" > </ bean>
</ mvc: interceptor>
</ mvc: interceptors>
</ beans>
【22】过滤器和拦截器区别
1. 来源不同
拦截器是SpringMVC中的技术,过滤器是Java EE中的技术
2. 生效位置不同
拦截器是进入DispatcherServlet后才能执行,过滤器是进入到Servlet容器后就可以触发
3. 目标不同
拦截器拦截的目标是HandlerMethod(控制单元,控制器方法),过滤器可以过滤所有的URL
4. 运行机制不同
拦截器是在HandlerMethod执行前后和视图处理完成后执行,分为三部分。过滤器只能在目标资源前后执行
5. 接口中方法类型不同
拦截器中的方法都是default方法,可以重写也可以不重写。过滤器中的方法都是abstract方法,如果当前类不是抽象类,必须重写
6. 上下文不同
拦截器可以获取到Spring容器中内容,但是Filter因为是被Tomcat管理,所以无法直接获取Spring容器内容,需要通过WebApplicationContextUtils.findApplicationContext(request.getServletContext())间接获取
【23】异常处理@ExceptionHandler
@Controller
public class DemoController {
@RequestMapping ( "/demo" )
@ResponseBody
public String demo2 ( ) {
Object obj = null ;
obj. toString ( ) ;
return "demo2" ;
}
@ExceptionHandler ( value = ArithmeticException . class )
public String myexception ( ) {
System . out. println ( "Demo-1" ) ;
return "forward:/exception.jsp" ;
}
@ExceptionHandler ( value = Exception . class )
public String myexception2 ( ) {
System . out. println ( "Demo-2" ) ;
return "forward:/exception2.jsp" ;
}
}
package com. bjsxt. advice ;
import org. springframework. web. bind. annotation. ControllerAdvice ;
import org. springframework. web. bind. annotation. ExceptionHandler ;
public class MyControllerAdvice {
@ExceptionHandler ( { Exception . class } )
public String handleEx ( Exception e) {
System . out. println ( e. getMessage ( ) ) ;
System . out. println ( "Exception异常处理" ) ;
return "/errors/error4.jsp" ;
}
@ExceptionHandler ( { ArrayIndexOutOfBoundsException . class } )
public String handleArrayIndexOutOfBounds ( ArrayIndexOutOfBoundsException e) {
System . out. println ( e. getMessage ( ) ) ;
System . out. println ( "ArrayIndexOutOfBoundsException异常处理" ) ;
return "/errors/error3.jsp" ;
}
@ExceptionHandler ( { ArithmeticException . class } )
public String handleArithmetic ( ArithmeticException e) {
System . out. println ( e. getMessage ( ) ) ;
System . out. println ( "ArithmeticException异常处理" ) ;
return "/errors/error2.jsp" ;
}
@ExceptionHandler ( { RuntimeException . class } )
public String handleRuntime ( RuntimeException e) {
System . out. println ( e. getMessage ( ) ) ;
System . out. println ( "运行时异常处理" ) ;
return "/errors/error1.jsp" ;
}
}
<?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
https://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"
default-autowire = " default" >
< context: component-scan base-package = " com.bjsxt.controller, com.bjsxt.advice" > </ context: component-scan>
</ beans>
【24】异常处理-配置文件配置
在Spring MVC中包含HandlerExceptionResolver组件,专门负责处理异常的。接口中只包含一个resolveException方法,程序员可以自行对接口实现,也可以使用Spring MVC提供的实现。
其中最简单好用的就是SimpleMappingExceptionResolver,里面有个全局属性exceptionMappings,表示当出现了什么类型异常时跳转到指定的页面
想要在异常出现时跳转到指定页面,只需要在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
https://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"
default-autowire = " default" >
< context: component-scan base-package = " com.bjsxt.controller, com.bjsxt.advice" > </ context: component-scan>
< mvc: annotation-driven> </ mvc: annotation-driven>
< bean id = " multipartResolver" class = " org.springframework.web.multipart.commons.CommonsMultipartResolver" > </ bean>
< bean class = " org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" >
< property name = " exceptionMappin0gs" >
< props>
< prop key = " java.lang.Exception" > /errors/error4.jsp</ prop>
< prop key = " java.lang.ArrayIndexOutOfBoundsException" > /errors/error3.jsp</ prop>
< prop key = " java.lang.ArithmeticException" > /errors/error2.jsp</ prop>
< prop key = " java.lang.RuntimeException" > /errors/error1.jsp</ prop>
</ props>
</ property>
</ bean>
</ beans>
上面的方式只有在Spring MVC中出现异常时才会触发,也可以使用Java EE中的配置方式。在web.xml中配置error-page即可
这种在web.xml配置的方式是针对整个项目出现的异常。而在springmvc.xml配置文件的配置方式只是针对Spring MVC框架出现的异常
在Spring MVC框架中没有提供根据状态码跳转到特定的视图。想要实现根据状态码跳转到指定页面可以使用Java EE中提供的实现方案。在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" >
< filter>
< filter-name> charset</ 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> charset</ filter-name>
< url-pattern> /*</ url-pattern>
</ filter-mapping>
< servlet>
< servlet-name> mvc</ servlet-name>
< servlet-class> org.springframework.web.servlet.DispatcherServlet</ servlet-class>
< init-param>
< param-name> contextConfigLocation</ param-name>
< param-value> classpath:applicationContext-mvc.xml</ param-value>
</ init-param>
< load-on-startup> 1</ load-on-startup>
</ servlet>
< servlet-mapping>
< servlet-name> mvc</ servlet-name>
< url-pattern> /</ url-pattern>
</ servlet-mapping>
< error-page>
< error-code> 500</ error-code>
< location> /errors/error4.jsp</ location>
</ error-page>
</ web-app>
【25】JSR
JSR
JCP(Java Community Process)是一个开发的国际组织,里面包含了一些Java开发者和其他被允许加入的成员。JCP组织主要负责对Java社区进行发展和更新。维护的规范包含:J2ME、J2SE、J2EE、XML等相关规范。组织成员可以提交JSR(Java Specification Requests,Java 规范提案),待组织成员通过提案后会把相关内容加入到下一个版本的规范中
JSR 303
JSR每个提案都带有数字名称。例如JSR 107、JSR 303等。一定要注意的是,对于JSR提案并不是数字越大就需要包含前面内容。例如JSR 107主要是对缓存的提案、JSR 303是对数据校验的提案,这两个提案不存在包含和被包含的关系,也不存在版本先后的关系。
JSR 303是Java EE 6规范的子规范。叫做Bean Validation。这些规范都是注解。各大公司可以针对这些规范做具体实现。在Java开发中使用的最多的JSR 303具体实现就是Hibernate框架中Hibernate-Validator。它对JSR 303的所有约定(constraint)都做了实现,同时还进行了一定的扩充。
Hibernate Validator对JSR 303具体实现
注解 含义 @AssertFalse 类型必须是布尔,取值必须为false @AssertTrue 类型必须是布尔,取值必须为true @DecimalMax(“3”) 最大值为3,value属性是String类型。 @DecimalMin(“1”) 最小值为1,value属性是String类型。 @Digits(integer = 10,fraction = 3) integer:整数位最大长度,fraction小数位最大长度 @Email 必须是邮箱地址。只要中间包含@,且@前后都具有超过1位的字符就能通过校验。字符可以是数字字母下划线 @Future 类型必须是时间类型,允许为null,如果设置值必须是一个将来的时间 @FutureOrPresent 类型必须是时间类型,允许为null,如果设置值必须是一个将来或现在的时间(精确到秒) @Max(5) 最大值为5,value属性是long类型 @Min(1) 最小值为1,value属性是long类型。 @Negative 必须是负数,对数据类型没有要求。 @NegativeOrZero 必须是负数或零,对数据类型没有要求。 @NotBlank 用在String类型。不能是空白(null和"") @NotEmpty 用在String类型。不能是空白(null和"") @NotNull 不能为null,可以是""。可以用在所有类型中。对于八大基本数据类型来说,永远不为null。 @Null 必须为Null。可以用在所有类型中。对于八大基本数据类型来说,永远不可能为null。 @Past 类型必须是时间类型,必须是一个过去的时间。精确到秒。 @PastOrPresent 类型必须是时间类型,必须是一个过去的时间或现在的时间。精确到秒。· @Pattern(regexp = “\w{1,6}”) 必须满足正则表达式。regexp是必有属性。 @Positive 必须是正数,对数据类型没有要求。 @PositiveOrZero 必须是正数或零,对数据类型没有要求。 @Size(min = 1,max = 10) 用在String类型。个数必须在1和10之间
Hibernate-Validator额外补充
注解 含义 @Length(min = 1,max = 10) 用在String类型。长度需要在1和10之间 @Range(min = 1,max = 10) 数据类型没有要求。取值范围需要在1和10之间 @URL(port = 8080,host = “127.0.0.1”,protocol = “https”) 需要是一个合法的URL。默认情况下只要是以http:开头即可。可以通过port限制端口、host限制主机名、protocol限制协议
【26】数据校验
MVC中数据校验包含两种:(1)基于注解方式(2)自定义校验类的方式
除了项目正常的依赖以外,额外需要导入Hibernate-validator依赖。
注意:对于Tomcat8插件来说,最高支持到6.1.x版本,对于更高的6.2.x或7.x版本是不支持的。导入后启动会报异常。如果希望使用更高版本的依赖,可以使用更高版本Tomcat(本机Tomcat)
<?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" >
< parent>
< artifactId> sj125_springmvc</ artifactId>
< groupId> com.bjsxt</ groupId>
< version> 1.0-SNAPSHOT</ version>
</ parent>
< modelVersion> 4.0.0</ modelVersion>
< artifactId> sj125_springmvc_4</ artifactId>
< packaging> war</ packaging>
< dependencies>
< dependency>
< groupId> javax.servlet</ groupId>
< artifactId> javax.servlet-api</ artifactId>
< version> 4.0.1</ version>
< scope> provided</ scope>
</ dependency>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-webmvc</ artifactId>
< version> 5.3.20</ version>
</ dependency>
< dependency>
< groupId> org.aspectj</ groupId>
< artifactId> aspectjweaver</ artifactId>
< version> 1.9.9.1</ version>
< scope> runtime</ scope>
</ dependency>
< dependency>
< groupId> com.fasterxml.jackson.core</ groupId>
< artifactId> jackson-databind</ artifactId>
< version> 2.9.10.8</ version>
</ dependency>
< dependency>
< groupId> commons-fileupload</ groupId>
< artifactId> commons-fileupload</ artifactId>
< version> 1.4</ version>
</ dependency>
< dependency>
< groupId> org.hibernate.validator</ groupId>
< artifactId> hibernate-validator</ artifactId>
< version> 6.1.7.Final</ version>
</ dependency>
</ dependencies>
< pluginRepositories>
< pluginRepository>
< id> mvnrepository</ id>
< url> https://artifacts.alfresco.com/nexus/content/repositories/public/</ url>
</ pluginRepository>
</ pluginRepositories>
< build>
< plugins>
< plugin>
< groupId> org.apache.tomcat.maven</ groupId>
< artifactId> tomcat8-maven-plugin</ artifactId>
< version> 3.0-r1756463</ version>
< configuration>
< port> 80</ port>
< path> /</ path>
</ configuration>
</ plugin>
</ plugins>
</ build>
</ project>
package com. bjsxt. pojo ;
import org. hibernate. validator. constraints. Range ;
import javax. validation. constraints. Email ;
import javax. validation. constraints. NotBlank ;
import javax. validation. constraints. NotNull ;
import java. util. Objects ;
public class User {
@NotNull ( message = "主键必须存在" )
private Integer id;
@NotBlank
private String name;
@Range ( min = 0L , max = 160L )
private int age;
@Email
private String email;
public User ( ) {
}
@Override
public String toString ( ) {
return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", email='" + email + '\'' + '}' ;
}
@Override
public boolean equals ( Object o) {
if ( this == o) return true ;
if ( o == null || getClass ( ) != o. getClass ( ) ) return false ;
User user = ( User ) o;
return age == user. age && Objects . equals ( id, user. id) && Objects . equals ( name, user. name) && Objects . equals ( email, user. email) ;
}
@Override
public int hashCode ( ) {
return Objects . hash ( id, name, age, email) ;
}
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 int getAge ( ) {
return age;
}
public void setAge ( int age) {
this . age = age;
}
public String getEmail ( ) {
return email;
}
public void setEmail ( String email) {
this . email = email;
}
}
package com. bjsxt. controller ;
import com. bjsxt. pojo. User ;
import org. springframework. web. bind. annotation. GetMapping ;
import org. springframework. web. bind. annotation. RestController ;
import javax. validation. Valid ;
@RestController
public class UserController {
@GetMapping ( "/addUser" )
public User addUser ( @Valid User user) {
System . out. println ( user) ;
return user;
}
}
package com. bjsxt. pojo ;
import org. hibernate. validator. constraints. Range ;
import javax. validation. constraints. Email ;
import javax. validation. constraints. NotBlank ;
import javax. validation. constraints. NotNull ;
import java. util. Objects ;
public class People {
private Integer id;
private String name;
private int age;
private String email;
public People ( ) {
}
@Override
public String toString ( ) {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
'}' ;
}
@Override
public boolean equals ( Object o) {
if ( this == o) return true ;
if ( o == null || getClass ( ) != o. getClass ( ) ) return false ;
People user = ( People ) o;
return age == user. age &&
Objects . equals ( id, user. id) &&
Objects . equals ( name, user. name) &&
Objects . equals ( email, user. email) ;
}
@Override
public int hashCode ( ) {
return Objects . hash ( id, name, age, email) ;
}
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 int getAge ( ) {
return age;
}
public void setAge ( int age) {
this . age = age;
}
public String getEmail ( ) {
return email;
}
public void setEmail ( String email) {
this . email = email;
}
}
package com. bjsxt. controller ;
import com. bjsxt. pojo. People ;
import org. springframework. web. bind. annotation. RequestMapping ;
import org. springframework. web. bind. annotation. RestController ;
import javax. validation. Valid ;
@RestController
public class PeopleController {
@RequestMapping ( "/addPeople" )
public People addPeople ( @Valid People people) {
System . out. println ( people) ;
return people;
}
}
package com. bjsxt. valid ;
import com. bjsxt. pojo. People ;
import org. springframework. validation. Errors ;
import org. springframework. validation. ValidationUtils ;
import org. springframework. validation. Validator ;
public class MyValidator implements Validator {
@Override
public boolean supports ( Class < ? > clazz) {
if ( People . class == clazz) {
return true ;
}
return false ;
}
@Override
public void validate ( Object target, Errors errors) {
ValidationUtils . rejectIfEmpty ( errors, "name" , "名字不能为空" ) ;
Object idObj = errors. getFieldValue ( "id" ) ;
if ( idObj == null ) {
errors. rejectValue ( "id" , "null" , "主键非空" ) ;
}
Object ageObj = errors. getFieldValue ( "age" ) ;
if ( ageObj != null ) {
int age = Integer . parseInt ( ageObj. toString ( ) ) ;
if ( age < 0 || age > 160 ) {
errors. rejectValue ( "age" , "range" , "年龄在0~160之间" ) ;
}
}
}
}
<?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
https://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"
default-autowire = " default" >
< context: component-scan base-package = " com.bjsxt.controller, com.bjsxt.advice" > </ context: component-scan>
< bean id = " myValidator" class = " com.bjsxt.valid.MyValidator" > </ bean>
< mvc: annotation-driven validator = " myValidator" > </ mvc: annotation-driven>
< bean id = " multipartResolver" class = " org.springframework.web.multipart.commons.CommonsMultipartResolver" > </ bean>
</ beans>
【27】国际化
SpringMVC中对view的支持。
SpringMVC中的国际化处理
1. 在classpath下,任意目录中定义国际化属性配置文件 properties。
文件的命名规则是: 任意名字_语言_国家简写.properties
文件可以有若干同名不同语言国家的配置。
配置内容是: key=value。 key是视图层要显示对应value的变量名。 value是视图层要显示的文本。
注意:如果属性配置文件中,包含非ISO-8859-1字符集内的字符,必须设置文件保存字符集为UTF-8。 通过IDEA -> settings实现配置
native-to-ascii 勾选。 IDEA自动转译成Unicode编码。
2. 在springmvc配置文件中,增加2个bean对象配置。
包括读取国际化属性配置文件的bean对象
实现基于请求头,识别语言国际化的bean对象
3. 在JSP页面中,使用springmvc框架提供的标签库,读取国际化属性配置文件内容。
使用标签:
<%@ taglib prefix="spring" uri=""%>
<spring:message code="属性配置文件中的key" text="如果key在属性配置文件中不存在,使用当前文本作为默认值"/>
< bean id = " messageSource" class = " org.springframework.context.support.ResourceBundleMessageSource" >
< property name = " basename" value = " suiyi" > </ property>
</ bean>
< bean id = " localeResovler" class = " org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver" > </ bean>
# 在src/main/resources中新建属性文件。属性文件语法:`任意名_语言_国家.properties`。例如:中文是zh、英文是en。
# 如果为了更加精确是哪国使用的这个语言,可以在后面添加国家,因为美式英语和英式英语是不一样的。中国:CN、美国是US,国家缩写都是大写的
# 新建 suiyi_zh_CN.properties
bjsxt.username=用户名
bjsxt.password=密码
bjsxt.submit=登录
# 新建suiyi_en_US.properties
bjsxt.username=username
bjsxt.password=password
bjsxt.submit=login
<!-- 在上面使用taglib执行引入标签库 -->
<!-- `<spring:message code="属性文件的key"></spring:message>`根据语言环境负责加载属性文件中key的值 -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="" method="post">
<spring:message code="bjsxt.username"></spring:message> <input type="text" name="username"/><br/>
<spring:message code="bjsxt.password"></spring:message> <input type="text" name="password"/><br/>
<input type="submit" value="<spring:message code="bjsxt.submit"></spring:message>"/>
</form>
</body>
</html>
【28】TLD文件
TLD文件: 自定义标签库描述文件。描述标签名称,属性名称,各种使用方案的文件。
如: JSTL中的c标签库。
查看TLD文件的方式是,ctl+鼠标左键,点击taglib标签的uri属性。
重点内容:
1. <short-name> taglib prefix属性值。
2. <uri> taglib uri属性值。
3. <tag>标签,一个标签对应一个JSP中可使用的标签。
3.1 tag <name>子标签, 标签名称
3.2 tag <attribute>, 对应一个标签的属性
3.2.1 tag attribute <name> , 属性的名字
3.2.2 tag attribute <required> , 属性是否是必须存在的。
3.2.3 tag attribute <rtexprvalue>, 属性是否可以使用表达式赋值
3.2.4 tag attribute <type>, 属性的类型。
3.3 tag <tag-class> 标签的实现Java类型。 每个标签对应一个Java类型。 Java类型识别标签,并显示具体视图或处理具体逻辑。