Spring-MVC总结
1. SpringMVC的概述
Spring MVC框架是一个开源的Java平台,为开发强大的基于JavaWeb应用程序提供全面的基础架构支持,框架提供了MVC(模型 - 视图 - 控制器)架构和用于开发灵活和松散耦合的Web应用程序的组件。
模型(Model) 封装了应用程序数据,通常它们将由POJO类组成。
视图(View) 负责渲染模型数据,一般来说它生成客户端浏览器可以解释HTML输出。
控制器(Controller) 负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染。
2. 核心DispatcherServlet程序(相当于BaseServlet)
服务器交互请求响应流程图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ym82zmEV-1574917565574)(file:///C:\Users\尚硅谷\AppData\Local\Temp\ksohtml15800\wps1.jpg)]
3. 搭建Spring-MVC运行时环境
**3.**1 创建一个动态的web工程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HZ0BO73y-1574917565575)(file:///C:\Users\尚硅谷\AppData\Local\Temp\ksohtml15800\wps2.jpg)]
3.2导入SpringMVC所需的jar****包
commons-logging-1.1.3.jar
log4j-1.2.17.jar
spring-aop-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar
3.3 配置日志文件log4j
(1) log4j.properties
# Global logging configuration
log4j.rootLogger=INFO, stdout
# Console output…
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
3.4配置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 http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package=“com.atguigu”></context:component-scan>
3.5配置核心dispatcherServlet,在动态项目WEB-INF的web-xml中
springDispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
1
springDispatcherServlet
/
3.6配置xml中的mvc视图解析器
配置SpringMVC提交的视图解析器:
<bean class=“org.springframework.web.servlet.view.InternalResourceViewResolver”>
<property name=“prefix” value="/jsp/"/>
<property name=“suffix” value=".jsp"/>
视图解析器工作原理 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vTGBht1c-1574917565577)(file:///C:\Users\尚硅谷\AppData\Local\Temp\ksohtml15800\wps3.jpg)]
3.7 配置字符编码过滤器
CharacterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
CharacterEncodingFilter
/*
4. Spring-MVC处理请求及响应的方式
4.1视图页面请求(举例jsp)
//hello为请求地址,对应Controller标记类中被RequestMapping(value=”hello”)标记的方法
4.2 Controller注解类处理请求
* @Controller 表示当前类是一个控制器
@Controller
public class HelloController {
* @RequestMapping("/hello")
表示在SpringMVC中注册一个控制器,请求地址是http://ip:port/工程名/hello
@RequestMapping("/hello")
public String hello() {
System.out.println(“这是SpringMVC的hello程序”);
// “/jsp/target.jsp” 返回值表示要跳转的地址
// /,表示到http://ip:port/工程名/ 映射到WebContent目录
// “/jsp/target.jsp” 整个表示http://ip:port/工程名/jsp/target.jsp页面
// SpringMVC默认跳转使用的是转发
return “/jsp/target.jsp”;
5. RequestMapping注解详解
@RequestMapping(属性值)是给个方法配置一个访问地址,或者不同属性值.可能对应请求必要的参数或者请求方式,请求头信息等.
5.1 value属性(重点)
@RequestMapping(value="/hello")
表示映射当前这个请求方法的访问地址。
/ 表示到http://ip:port/工程名/ 映射到代码的WebContent目录
/hello 就表示到http://ip:port/工程名/hello
5.2 params属性
params是要求此请求的参数匹配
params=“username” 表示 请求地址必须带有username参数
params=“username=abc” 表示 请求参数中必须要有username,而且值还必须是abc
params=“username!=abc” 表示 1、请求参数中不能有username参数。2、有username参数,但值不能等于abc
params="!username" 表示 请求地址不能带有username参数
params= {“username!=abc”,"!password"} params可以有多个值,每个值之间是&&关系
以上条件表示要求:
( 请求地址中不能有username参数 || username参数值不能等于 abc && 不能有password参数 )
5.3 headers属性
可以限定请求头中的信息
* headers = “User-Agent=Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36”
* 表示限定浏览器必须是谷歌浏览器,而且版本还是Chrome/58.0.3029.110
@RequestMapping(value = “/header”, headers = “User-Agent=Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36”)
public String header() {}
5.4 method属性(次重点)
method=RequestMethod.GET 表示当前请求必须是GET请求才允许访问
* method=RequestMethod.POST 表示当前请求必须是POST请求才允许访问
可以在restful风格中设置不同的类型,标记增删改查方法
@RequestMapping(value="/method",method=RequestMethod.POST)
public String method() {}
5.5 RequestMapping注解标记类上
当我们在Controller控制器上添加一个@RequestMapping注解,并赋于value属性值的时候,相当于给类也加了一层访问的路径,多用来区别多个Controller类时不同类中方法地址重名,地址冲突。
比如:
@RequestMapping(value="/person")
@Controller
public class HelloController {
这个时候,HelloController中的方法都必须在原有请求地址路径前面加上/person。
5.6 通配符在RequestMapping中的使用
1、绝对匹配 value=精确的值
@RequestMapping(value = “/fun”)
public String fun() {}
2、? 问号 匹配资源路径
? 问号表示一个任意字符,只能匹配一个字符
@RequestMapping(value = “/fu?”)
public String fu?() {}
3、* 星号 匹配资源路径
* 星号 可以匹配任意个字符,可以匹配任意多个字符
@RequestMapping(value = “/fu*”)
public String fu21312312321() {}
4、? 问号 匹配一层目录
@RequestMapping(value = “/?/fun”)
public String fun3() {}
5、* 问号 匹配一层目录
@RequestMapping(value = “/*/fun”)
public String fun4() {}
6、** 星星号 匹配多层目录
@RequestMapping(value = “/**/fun”)
public String fun5() {}
6 Controller中接收请求参数(重点)
6.1原生API参数类型
6.1.1、HttpServletRequest类
@RequestMapping(value = “/param1”)
public String param1(HttpServletRequest request) {
System.out.println(“这是param1方法”);
System.out.println(request);
return “param”;
}
6.1.2、HttpSession类
@RequestMapping(value = “/param2”)
public String param2(HttpServletRequest request, HttpSession session) {
System.out.println(“这是param2方法”);
System.out.println(request);
System.out.println(session);
return “param”;
}
6.1.3、HttpServletResponse类
@RequestMapping(value = “/param3”)
public String param3(HttpServletRequest request, HttpSession session,
HttpServletResponse response) {
System.out.println(“这是param3方法”);
System.out.println(response);
System.out.println(request);
System.out.println(session);
return “param”;
}
6.2、普通类型入参
通过request对象获取(不推荐):
@RequestMapping(value="/param4")
public String param4(HttpServletRequest request) {
System.out.println(“这是param4方法”);
System.out.println(request.getParameter(“username”));
return “param”;
}
我们在Controller的目标方法上直接设置方法的参数。就可以直接传入请求参数的值。
@RequestMapping(value="/param5")
public String param5(String username) {
System.out.println(“这是param5方法”);
System.out.println(username);
return “param”;
}
要求:参数名必须和方法的参数名相匹配。
6.3 普通类型数组的参数
@RequestMapping(value = “/param6”)
public String param6(String[] hobbies) {
System.out.println(“这是param6方法”);
if (hobbies != null) {
for (String string : hobbies) {
System.out.println(string);
}
}
return “param”;
}
6.4普通类型使用@RequestParam入参
@RequestMapping(value = “/param7”)
public String param7(@RequestParam(value = “username”) String user) {
System.out.println(“这是param7方法”);
System.out.println(user);
return “param”;
}
@RequestParam(value = “username”) String user 表示SpringMVC会自动将请求过来的参数username的值。注入到方法参数user中。
默认情况下。@RequestParam(value = “username”)中要求的username参数必须要有值。否则就会报错误.
6.5 @RequestHeader获取请求头入参
@RequestMapping(value = “/param8”)
public String param8(@RequestHeader(value = “User-Agent”) String userAgent,
@RequestHeader(value = “Host”) String host) {
System.out.println(“这是param8方法”);
System.out.println(userAgent);
System.out.println(host);
return “param”;
}
6.6 @CookieValue获取Cookie值入参
@CookieValue注解获取cookie的值注入。
value中填写的是cookie的key值
@RequestMapping(value = “/param9”)
public String param9(@CookieValue(value = “JSESSIONID”) String jsessionid) {
System.out.println(“这是param9方法”);
System.out.println(jsessionid);
return “param”;
}
6.7一个Pojo对象类型的参数
要求:pojo对象自动入参的要求是客户端传递的参数名必须跟pojo对象的属性名对应上。
@RequestMapping(value="/param10")
public String param10(Person person) {
System.out.println(“这是param10方法”);
System.out.println(person);
return “param”;
}
6.8 对象中套对象(级联属性)
public class Book {
private String name;
private BigDecimal price;
public class Person {
private Integer id;
private String name;
private String phone;
private Integer age;
private Book book;
表单:
<form action="${ pageContext.request.contextPath }/param10">
id:<input type=“text” name=“id” />
name:<input type=“text” name=“name” />
phone:<input type=“text” name=“phone” />
age:<input type=“text” name=“age” />
book.name:<input type=“text” name=“book.name” />
book.price:<input type=“text” name=“book.price” />
<input type=“submit” />
@RequestMapping(value="/param10")
public String param10(Person person) {
System.out.println(“这是param10方法”);
System.out.println(person);
return “param”;
}
7 返回值的设置
7.1返回值是String时
7.1.1 默认情况
默认情况下,返回return字符串。会经过视图解析器做字符串前后缀拼接的操作,拼接完成后 默认做转发处理.
@Controller
public class ReturnController {
@RequestMapping(value = “/return1”)
public String return1() {
System.out.println(“这是return1方法”);
return “return”;
7.1.2 显式转发
显式转发的情况,在return 后面添加forward前缀,默认的视图解析器失效,/代表当前项目路径下
@RequestMapping(value = “/return2”)
public String return2() {
System.out.println(“这是return2方法”);
// 在返回的字符串前面 显示的 标注 forward:表示显示的转发
// 使用显示的转发,视图解析器就不会工作了
return “forward:/jsp/return.jsp”;
}
7.1.3 显式重定向
@RequestMapping(value = “/return3”)
public String return3() {
System.out.println(“这是return3方法”);
// 当我们在返回的字符串前面显示的加入redirect:表示强制使用重定向
// 只要是显示的声明使用转发或重定向,默认视图解析器将不在工作
return “redirect:/jsp/return.jsp”;
}
7.2 返回modelAndView
7.2.1 默认情况
默认的情况我们在ModelAndView中设置的ViewName就是默认转发的视图名。这个视图名会经过视图解析器拼接这符串后再转发。
@RequestMapping(value="/return4")
public ModelAndView return4() {
System.out.println(“这是return4方法”);
// ModelAndView 也可以设置返回的资源
ModelAndView modelAndView = new ModelAndView();
// 设置视图名
modelAndView.setViewName(“return”);
return modelAndView;
}
7.2.2显示转发
在返回的字符串前面 显示的 标注 forward:表示显示的转发,
使用显示的转发,视图解析器就不会工作了
@RequestMapping(value="/return5")
public ModelAndView return5() {
System.out.println(“这是return5方法”);
// ModelAndView 也可以设置返回的资源
ModelAndView modelAndView = new ModelAndView(“forward:/jsp/return.jsp”);
return modelAndView;
}
7.2.3显式重定向
当我们在返回的字符串前面显示的加入redirect:表示强制使用重定向,只要是显示的声明使用转发或重定向,默认视图解析器将不在工作
@RequestMapping(value="/return6")
public ModelAndView return6() {
System.out.println(“这是return6方法”);
ModelAndView modelAndView = new ModelAndView(“redirect:/jsp/return.jsp”);
return modelAndView;
}
7.3、返回void(不推荐在Controller中直接转发和重定向)(了解)
7.3.1、没有返回值的*默认情况*
一般在实际开发中。我们都是禁止使用如以上这种方式。使用默认的请求资源名做为默认转发的逻辑资源名。
如果有需要,都是使用String类型显示标明返回的逻辑名。也就是说以上代码应该写成为:
@RequestMapping(value="/return7")
public void return7() {
System.out.println(“return7方法”);
}
7.3.2、显示转发
@RequestMapping(value = “/return8”)
public void return8(HttpServletRequest request, HttpServletResponse response) {
System.out.println(“这是return8方法”);
try {
request.getRequestDispatcher("/jsp/return.jsp").forward(request,
response);
} catch (Exception e) {
e.printStackTrace();
}
7.3.3、显示重定向
@RequestMapping(value="/return9")
public void return9(HttpServletRequest request, HttpServletResponse response) {
System.out.println(“这是return9方法”);
try {
response.sendRedirect(request.getContextPath() + “/jsp/return.jsp”);
} catch (IOException e) {
e.printStackTrace();
7.3.4、直接输出响应数据
@RequestMapping(value="/return10")
public void return10(HttpServletResponse response) {
System.out.println(“这是return10方法”);
try {
response.getWriter().write(“this is the content of response!”);
} catch (IOException e) {
e.printStackTrace();
8. 数据在域中的输入保存
8.1、Request对象中保存数据(不推荐)
先在Controller的方法中添加一个HttpServletRequest对象
@RequestMapping(value="/requestScope")
public ModelAndView requestScope(HttpServletRequest request) {
System.out.println(“这是把数据保存到request域中—requestScope”);
request.setAttribute(“key1”, “value1”);
return new ModelAndView(“scope”);
8.2、Session域中保存数据
在Controller方法中,添加HttpSession对象
@RequestMapping(value="/sessionScope")
public ModelAndView sessionScope(HttpSession session) {
System.out.println(“这是把数据保存到session域中—sessionScope”);
session.setAttribute(“skey1”, “svalue1”);
return new ModelAndView(“scope”);
8.3、ServletContext域中保存数据
在Controller中的代码。在Controller的中获取SerlvetContext对象有两种方法,
一种是@Autowired注入,
一种是通过Session获取。
是通过@Autowired自动注入ServletContext对象
@Controller
public class ScopeController {
@Autowired
private ServletContext context;
通过HttpSession获取ServletContext对象
@RequestMapping(value = “/applicationScope”)
public ModelAndView applicationScope(HttpSession session) {
System.out.println(“这是把数据保存到ServletContext域中—applicationScope”);
session.getServletContext().setAttribute(“appKey1”, “appValue1”);
return new ModelAndView(“scope”);
}
8.4、Map或Model或ModelMap形式保存数据在request域中
在四个域中,我们使用最频繁的域就是request对象。往request域对象中,保存数据,还在以下的几种形式。
我们可以在Controller的方法中,添加Map类型的参数,或者是Model类型的参数。或者是ModelMap类型的参数。都可以直接用来保存域数据到Request对象中。
Map全类名是: java.util.Map
Model全类名是: org.springframework.ui.Model
ModelMap全类名是: org.springframework.ui.ModelMap
* BindingAwareModelMap 它叫隐含模型
* /\
* ||
* ExtendedModelMap -----实现>>>>>>Model接口
* /\
* ||
* ModelMap
* /\
* ||
* LinkedHashMap
* /\
* ||
* HashMap ------实现>>>>>> Map接口
@RequestMapping(value="/test")
public ModelAndView test(Map<String, Object> map,Model model,ModelMap modelMap) {
map.put(“key1”, “value1”);
model.addAttribute(“model1”, “modelValue1”);
modelMap.addAttribute(“modelMap1”, “modelMapValue1”);
System.out.println(map.getClass());
System.out.println(model.getClass());
System.out.println(modelMap.getClass());
return new ModelAndView(“scope”);
}
8.5、ModelAndView方式保存数据到request域中
把数据保存到ModelAndView中,springMVC保存到把数据保存到Request域中
@RequestMapping(value="/modelAndViewScope")
public ModelAndView modelAndViewScope() {
ModelAndView modelAndView = new ModelAndView(“scope”);
System.out.println(“这是modelAndViewScope方法”);
// 往ModelAndView中保存数据,同样SpringMVC也会保存到request域中
modelAndView.addObject(“modelAndView1”, “modelAndViewValue1”);
modelAndView.addObject(“modelAndView2”, “modelAndViewValue2”);
return modelAndView;
8.6、@SessionAttributes保存数据到****Session域中(*了解内容*,不推荐使用)
@SessionAttributes 注解可以标注在类上。它的作用是指定哪些数据可以保存到Session域中。
@SessionAttributes(value = { “key1”,“key2” }, types = { String.class, Book.class })
value属性,它表示把request域中key为key1,key2的键值对信息,也保存到Session中
types属性,它表示把request域中value类型为String.class或Book.class类型的键值对,也保存到Session中
8.7、@ModelAttribute注解
@ModelAttribute这个注解可以标注在方法和参数上。
@ModelAttribute三个常见作用:
1、被标注了@ModelAttribute的方法都会在Controller的目标方法之前执行。
2、目标方法的参数(JavaBean对象)会先从隐含模型中获取值传入。
3、@ModelAttribute被标注在目标的参数上,参数值会按照指定的key从隐含模型中获取值。
@ModelAttribute
public void abc(Map<String, Object> map) {
System.out.println(“我是@ModelAttribute标注的abc()方法”);
map.put(“book111”, new Book(“我是一个兵!”, new BigDecimal(99999999)));
}
* 目标方法中,如果有对象参数(非原生API,是那些pojo对象),它会先按照参数的类型取类名,然后首字母小写book,从隐含模型中取值注入。
@RequestMapping(value="/targetMethod")
public ModelAndView targetMethod(@ModelAttribute(“book111”)Book book) {
System.out.println(“targetMethod被调用了!”);
System.out.println(“目标方法中book的值是:” + book);
return new ModelAndView(“scope”);
}
9. Restful风格
9.1 Restful风格介绍
Restful 一种软件架构风格、设计风格,而不是标准.对于我们Web开发人员来说。就是使用一个url地址表示一个唯一的资源。然后把原来的请求参数加入到请求资源地址中。然后原来请求的增,删,改,查操作。改为使用HTTP协议中请求方式GET、POST、PUT、DELETE表示。
9.2 学习restful风格,明确2种方式
9.2.1传统的请求参数加入到请求地址
传统的方式是:
比如:http://ip:port/工程名/资源名?请求参数
举例:http://127.0.0.1:8080/springmvc/book?action=delete&id=1
restful风格是:
比如:http://ip:port/工程名/资源名/请求参数/请求参数
举例:http://127.0.0.1:8080/springmvc/book/1
请求的动作删除由请求方式delete决定
9.2.2 restful中请求方式GET、POST、PUT、DELETE分别表示查、增、改、删
GET请求 对应 查询
http://ip:port/工程名/book/1 HTTP请求GET 表示要查询id为1的图书
http://ip:port/工程名/book HTTP请求GET 表示查询全部的图书
POST请求 对应 添加
http://ip:port/工程名/book HTTP请求POST 表示要添加一个图书
PUT请求 对应 修改
http://ip:port/工程名/book/1 HTTP请求PUT 表示要修改id为1的图书信息
DELETE请求 对应 删除
http://ip:port/工程名/book/1 HTTP请求DELETE 表示要修改id为1的图书信息
9.2.3 SpringMVC中如何发送GET请求、POST请求、PUT请求、DELETE请求。
我们知道发起GET请求和POST请求,只需要在表单的form标签中,设置method=”get” 就是GET请求。
设置form标签的method=”post”。就会发起POST请求。而PUT请求和DELETE请求。要如何发起呢。
1、要有post请求的form标签
2、在form表单中,添加一个额外的隐藏域_method=”PUT”或_method=”DELETE”
3、在web.xml中配置一个Filter过滤器org.springframework.web.filter.HiddenHttpMethodFilter(注意,这个Filter一定要在处理乱码的Filter后面)
9.3 Restful的Controller实现
9.3.1在web.xml中配置HiddenHttpMethodFilter过滤器****如下:
必须放在字符过滤器下面
HiddenHttpMethodFilter
org.springframework.web.filter.HiddenHttpMethodFilter
HiddenHttpMethodFilter
/*
9.3.2 在view视图页面的配置
<input type=“hidden” name="_method" value=“DELETE” /> <input
type=“submit” value=“删除指定id的图书” />
<form action=“book/1” method=“post”>
<input type=“hidden” name="_method" value=“PUT” /> <input
type=“submit” value=“更新指定id的图书” />
9.3.3在Controller中的配置
@Controller
public class RestController {
@RequestMapping(value = “/book/1”, method = RequestMethod.DELETE)
public String deleteBook() {
System.out.println(“删除图书”);
return “redirect:/index.jsp”;
}
@RequestMapping(value = “/book/1”, method = RequestMethod.PUT)
public String updateBook() {
System.out.println(“更新图书”);
return “redirect:/index.jsp”;
}
9.3 Restful在高版本Tomcat中无法转发到jsp页面
出现4.5错误,解决方式如下:
方法一:修改jsp页面中的page指令isErrorPage=“true”,就可以访问了
<%@ page language=“java” contentType=“text/html; charset=UTF-8”
isErrorPage=“true”
pageEncoding=“UTF-8”%>
方法二:把转发改成为重定向 redirect:/
9.4 @PathVariable 路径参数获取
前面我们已经知道如何编写和配置restful风格的请求和控制器。
那么 现在的问题是。如何接收restful风格请求的参数。比如前面的id值。
第一种情况:
@RequestMapping(value = “/book/{id}”, method = RequestMethod.DELETE)
public String deleteBook(@PathVariable(value = “id”) int id) {
System.out.println(“删除图书 id ->” + id);
return “redirect:/index.jsp”;
}
/book/{id}
中{id}表示路径参数占位符
@PathVariable(value = “id”) int id
表示把请求路径book/{id} id所表示的值。注入到方法参数的int id中。
当@PathVariable注解中没有标记占位符名称的时候,默认使用对应的参数名做为路径参数的名称取值。
请记住:@PathVariable标记的路径变量,不能为空,必须有值
第二种情况:
@RequestMapping(value = “/book/{name}/{price}/”, method = RequestMethod.POST)
public String addBook(@PathVariable(“name”) String name,
@PathVariable(“price”) BigDecimal price) {
System.out.println(name);
System.out.println(price);
System.out.println(“添加图书”);
return “redirect:/index.jsp”;
}
在一次请求中,请求路径不是只能有一个路径参数。它可以有多个。
/book/{name}/{price}/
这里就表示这个book后面可以跟两个路径参数。{name}和{price}。
这两个路径参数分别注入到请求方法的 String name,和Bigdecimal price两个参数中
@PathVariable(“name”) String name,
表示把请求路径中的name路径参数注入到请求方法的name参数中。
@PathVariable(“price”) BigDecimal price
表示把请求路径中的price路径参数注入到请求方法的price参数中。
10. 了解内容
SpringMVC标签库(不常用)
自定义参数转换器
记住下面这个即可
@DateTimeFormat注解类型转换器
我们除了可以像上面一样自定义类型转换器之外。还可以使用SpringMVC提供的注解@DateTimeFormat(pattern=“yyyy-MM-dd”)
public class Person {
private Integer id;
private String name;
@DateTimeFormat(pattern = “yyyy-MM-dd”)
private Date birthDate;
private String email;
private BigDecimal salary;
我们也可以像上面。在类的Date类型的属性上标上注解。就可以自动将String类型转换成为Date数据
下面的前端都可以完成验证,了解中的了解
较验器----参数的有效性验证Validate----Hibernate(需要的时候自查)
自定义错误信息的回显(需要的时候自查)
11. 文件上传
文件上传在SpringMVC中如何实现:
1、准备一个文件上传的表单
2、导入文件上传需要的jar包
commons-fileupload-1.2.1.jar、commons-io-1.4.jar
3、配置文件上传解析器 CommonsMultipartResolver
4、配置Controller控制器的代码
11.1 准备一个文件上传的表单
Enctype=”multipart/form-data”,这个格式固定,重点
method=“post” enctype=“multipart/form-data”>
用户名:<input type=“text” name=“username”/>
头像:<input type=“file” name=“photo”/>
<input type=“submit” />
11.2导入文件上传需要的jar包
下面是文件上传专用的核心包,其他Spring和Spring-MVC的jar包不在内
commons-fileupload-1.2.1.jar
commons-io-1.4.jar
commons-logging-1.1.3.jar
11.3配置文件上传解析器
<bean id=“multipartResolver”
class=“org.springframework.web.multipart.commons.CommonsMultipartResolver”>
<property name=“defaultEncoding” value=“UTF-8” />
11.4 文件上传Controller控制器
重点在方法的形参列表加上 MultipartFile 的对象
接收从页面上传获得的数据对象
@RequestMapping(value="/upload")
public String upload(String username,MultipartFile photo) {
System.out.println(“用户名:” + username);
//说明有上传的内容
// isEmpty判断是否为空
if (photo != null && !photo.isEmpty()) {
try {
// transferTo 将文件写入到硬盘位置
// getOriginalFilenameaqb
photo.transferTo(new File(“e:\” + photo.getOriginalFilename()));
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return “forward:/index.jsp”;
}
12. 使用@ResponseBody返回数据转成json(重点)
12.1 使用的步骤如下
1、导入json相关的包到web工程中,导入以下jar包,实现无痛转换json
jackson-annotations-2.1.5.jar
jackson-core-2.1.5.jar
jackson-databind-2.1.5.jar
2、编写一个请求的方式接收请求,并返回数据对象
3、在方法上添加注解@ResponseBody自动将返回值json化
12.2 Controller中的代码
@ResponseBody
@RequestMapping(value = “/queryPersonById”)
public Person queryPersonById() {
return new Person(19, “name10”, new Date(), “azrail@126.com”,
new BigDecimal(100));
}
@ResponseBody
@RequestMapping(value = “/personList”)
public List personList() {
List list = new ArrayList();
for (int i = 0; i < 10; i++) {
list.add(new Person(i, “name” + i, new Date(), “azrail@126.com”,
new BigDecimal(100)));
}
return list;
}
12.3 使用@JsonFormat修改时间在json中的格式
第一种在属性上加注解@JsonFormat
@JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”, timezone = “GMT+8”)
private Date birthDate;
或
第二种在get方法上加注解 @JsonFormat
@JsonFormat(pattern=“yyyy-MM-dd HH:mm:ss”,timezone = “GMT+8”)
public Date getBirthDate() {
return birthDate;
}
@JsonFormat表示设置json转换格式。
pattern=“yyyy-MM-dd HH:mm:ss” 表示日期类型返回以 yyyy-MM-dd HH:mm:ss 格式 yyyy-MM-dd表示年月日,HH:mm:ss表示时分秒
timezone = “GMT+8” 表示时间为格林时间+8小时
13. 使用@RequestBody接收请求体数据
在HTTP协议中,我们知道,请求体只存在于POST请求中才有。
所以我们需要有一个表单。而且请求必须是post请求
13.1 准备一个post请求的表单
<form action="${pageContext.request.contextPath }/requestBody" method=“post”>
用户名:<input type=“text” name=“username” />
密码:<input type=“password” name=“password” />
<input type=“submit” />
13.2在Controller中添加一个方法接收请求体
* GET请求
* 1、请求行
* 2、请求头
* POST请求
* 1、请求行
* 2、请求头
* 空行
* 3、请求体(请求的参数)
// @RequestBody 它可以接收请求体的数据—请求体,只存在于post请求
@RequestMapping(value = “/requestBody”)
public String requestBody(@RequestBody String body) {
System.out.println(“请求体的全部内容:” + body);
return “forward:/index.jsp”;
}
14. 使用HttpEntity参数获取请求头和请求体**(了解)**
页面代码:
<form action="${pageContext.request.contextPath }/httpEntity" method=“post”>
用户名:<input type=“text” name=“username” />
密码:<input type=“password” name=“password” />
<input type=“submit” />
Controller代码:
@RequestMapping(value = “/httpEntity”)
public String httpEntity(HttpEntity httpEntity) {
System.out.println(“请求头:” + httpEntity.getHeaders());
System.out.println(“请求体:” + httpEntity.getBody());
return “forward:/index.jsp”;
}
15使用ResponseEntity文件下载 返回值操作 响应头和响应体
ResponseEntity返回值,设置信息返回给页面
@RequestMapping(value = “/download”)
public ResponseEntity<byte[]> download(HttpSession session) {
try {
ServletContext ctx = session.getServletContext();
// 斜杠(斜线)表示到http://ip:port/工程名/ 映射到代码的WebContent目录
InputStream is = ctx.getResourceAsStream("/imgs/e.jpg");
byte[] buffer;
buffer = new byte[is.available()];
//读文件数据
is.read(buffer);
is.close();
//获取需要下载的文件的数据类型
String mimeType = ctx.getMimeType("/imgs/e.jpg");
// 响应头
HttpHeaders httpHeaders = new HttpHeaders();
// 添加响应头,告诉客户端我回去的数据类型是什么
httpHeaders.add(“Content-Type”, mimeType);
httpHeaders.add(“Content-Disposition”, “attachment; filename=e.jpg”);
// 第一个参数是你要返回的数据–我们要实现文件下载,就需要把下载的文件字节内容都放body中
// 第二个参数是 响应头
// 第三个参数是你要返回的响应状态码和响应 状态描述 符
ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(
buffer, httpHeaders, HttpStatus.OK);
return responseEntity;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
16 HandlerInterceptor拦截器
HandlerInterceptor拦截器,可以拦截Controller控制方法
16.1 单个HandlerInterceptor拦截器的示例
1、编写一个类去实现HandlerInterceptor接口
2、到Spring的容器配置文件中去配置拦截器,让SpringMVC知道都拦截哪些目标方法
拦截器类实现代码:
public class FirstHandlerInterceptor implements HandlerInterceptor {
/**
* 在拦截到目标方法前调用
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
System.out.println(“FirstHandlerInterceptor – >>> preHandle” );
//return false不放行
//return true放行
return true;
}
/**
* 在目标方法执行之后执行。
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println(“FirstHandlerInterceptor – >>> postHandle” );
}
/**
* 在目标方法执行完。跳转页面渲染完之后
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println(“FirstHandlerInterceptor – >>> afterCompletion” );
}
}
MVC的xml文件中配置拦截的地址:
mvc:interceptors
mvc:interceptor
<mvc:mapping path="/hello"/>
<bean class=“com.atguigu.controller.FirstHandlerInterceptor” />
</mvc:interceptor>
</mvc:interceptors>
正常情况下,拦截器的执行顺序:
FirstHandlerInterceptor – >>> preHandle
目标方法执行…………
FirstHandlerInterceptor – >>> postHandle
页面渲染的代码
FirstHandlerInterceptor – >>> afterCompletion
16.2 单个拦截器异常时的执行顺序
一:目标方法前返回false的情况:
1、目标方法前执行 返回false
2、这是目标方法 不执行
3、目标方法之后 不执行
4、这是渲染页面 不执行
5、页面渲染完成! 不执行
二:目标方法前返回true的情况,目标方法异常
1、目标方法前执行 返回true
2、这是目标方法 异常
3、目标方法之后 不执行
4、这是渲染页面 渲染异常页面
5、页面渲染完成! 执行
三:目标方法前返回true的情况,目标方法后异常
1、目标方法前执行 返回true
2、这是目标方法 执行
3、目标方法之后 异常
4、这是渲染页面 渲染异常页面
5、页面渲染完成! 执行
四:目标方法前返回true的情况,渲染页面异常
1、目标方法前执行 返回true
2、这是目标方法 执行
3、目标方法之后 执行
4、这是渲染页面 异常
5、页面渲染完成! 执行
17. 异常处理
17.1 使用@ExceptionHandler注解处理异常
//@ExceptionHandler可以拦截到本Controller中的异常
@ExceptionHandler
public ModelAndView exceptionHandler(Exception e) {
System.out.println(“exceptionHandler — Exception”);
ModelAndView modelAndView = new ModelAndView(“forward:/error.jsp”);
modelAndView.addObject(“exception”, e);
return modelAndView;
}
//@ExceptionHandler可以拦截到本Controller中的异常
@ExceptionHandler
public ModelAndView exceptionHandler(RuntimeException e) {
System.out.println(“exceptionHandler — RuntimeException”);
ModelAndView modelAndView = new ModelAndView(“forward:/error.jsp”);
modelAndView.addObject(“exception”, e);
return modelAndView;
}
//@ExceptionHandler可以拦截到本Controller中的异常
@ExceptionHandler
public ModelAndView exceptionHandler(ArithmeticException e) {
System.out.println(“exceptionHandler — ArithmeticException”);
ModelAndView modelAndView = new ModelAndView(“forward:/error.jsp”);
modelAndView.addObject(“exception”, e);
return modelAndView;
}
在同一个Controller中可以有多个@ExceptionHandler标注的异常处理方法。
SpringMVC会优先选择异常信息精确的方法执行异常处理操作。
17.2 使用@ControllerAdvice注解处理异常
@ControllerAdvice它可以处理所有Controller中产生的异常
*/
@ControllerAdvice
public class ExceptionEHander2 {
@ExceptionHandler
public ModelAndView exceptionHandler(Exception e) {
System.out.println("@ControllerAdvice — Exception");
ModelAndView modelAndView = new ModelAndView(“forward:/error.jsp”);
modelAndView.addObject(“exception”, e);
return modelAndView;
}
@ExceptionHandler
public ModelAndView exceptionHandler(RuntimeException e) {
System.out.println("@ControllerAdvice — RuntimeException");
ModelAndView modelAndView = new ModelAndView(“forward:/error.jsp”);
modelAndView.addObject(“exception”, e);
return modelAndView;
}
@ExceptionHandler
public ModelAndView exceptionHandler(ArithmeticException e) {
System.out.println("@ControllerAdvice — ArithmeticException");
ModelAndView modelAndView = new ModelAndView(“forward:/error.jsp”);
modelAndView.addObject(“exception”, e);
return modelAndView;
}
17.3 异常处理优先顺序
在局部异常处理和全局异常处理同时存在的时候,优先顺序是:
本类异常处理,优先其他类异常处理,在本类中,精准异常处理优先.
17.4 使用(xml中配置异常处理) SimpleMappingExceptionResolver类映射异常跳转
<bean class=“org.springframework.web.servlet.handler.SimpleMappingExceptionResolver”>
<property name=“exceptionMappings”>
<!–
key写上异常全类名
在prop标签中填写那批的跳转地址
-->
<prop key=“java.lang.Exception”>forward:/error.jsp
<prop key=“java.lang.RuntimeException”>forward:/error.jsp
<prop key=“java.lang.ArithmeticException”>forward:/error.jsp
<prop key=“java.lang.NullPointerException”>forward:/null.jsp
ollerAdvice它可以处理所有Controller中产生的异常**
*/
@ControllerAdvice
public class ExceptionEHander2 {
@ExceptionHandler
public ModelAndView exceptionHandler(Exception e) {
System.out.println("@ControllerAdvice — Exception");
ModelAndView modelAndView = new ModelAndView(“forward:/error.jsp”);
modelAndView.addObject(“exception”, e);
return modelAndView;
}
@ExceptionHandler
public ModelAndView exceptionHandler(RuntimeException e) {
System.out.println("@ControllerAdvice — RuntimeException");
ModelAndView modelAndView = new ModelAndView(“forward:/error.jsp”);
modelAndView.addObject(“exception”, e);
return modelAndView;
}
@ExceptionHandler
public ModelAndView exceptionHandler(ArithmeticException e) {
System.out.println("@ControllerAdvice — ArithmeticException");
ModelAndView modelAndView = new ModelAndView(“forward:/error.jsp”);
modelAndView.addObject(“exception”, e);
return modelAndView;
}
17.3 异常处理优先顺序
在局部异常处理和全局异常处理同时存在的时候,优先顺序是:
本类异常处理,优先其他类异常处理,在本类中,精准异常处理优先.
17.4 使用(xml中配置异常处理) SimpleMappingExceptionResolver类映射异常跳转
<bean class=“org.springframework.web.servlet.handler.SimpleMappingExceptionResolver”>
<property name=“exceptionMappings”>
<!–
key写上异常全类名
在prop标签中填写那批的跳转地址
-->
<prop key=“java.lang.Exception”>forward:/error.jsp
<prop key=“java.lang.RuntimeException”>forward:/error.jsp
<prop key=“java.lang.ArithmeticException”>forward:/error.jsp
<prop key=“java.lang.NullPointerException”>forward:/null.jsp