七、SpringMVC概述
1、WebMVC概述
WEB开发基本模型:请求—响应模型
Web客户端发起请求,Web服务端响应
服务器推技术(Server push、websocket)
2、Web端开发发展历程
3、SpringMVC
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web 框架,即使用了MVC架构模式的思想,将web 层进行职责解耦
基于请求驱动指的就是使用请求-响应模型
前端控制器:DispatcherServlet
应用控制器:映射管理器(Handler Mapping)+视图解析器(View Resolver)
页面控制器:Controller (可以实现Controller接口,也可以是POJO)
4、Spring Web MVC架构
5、回顾Servlet的web开发
1、新建项目
- Maven javaweb项目
- Jar包依赖
2、规划请求
用户操作、url、参数、结果数据、视图
3、编写Servlet
根据url、参数、结果数据写servlet
4、配置web
Web.xml中配置servlet
5、编写JSP
6、根据结果参数和视图写jsp
7、部署测试
6、SpringMVC项目开发
1、新建maven项目,补全项目结构
2、添加SpringMVC包依赖及jetty配置
3、修改web.xml,添加springmvc控制器配置
4、在WEB-INF下添加SpringMVC的配置文件(包扫描及resolver配置)
5、规划用户请求
6、开发controller
7、开发视图(jsp)
8、clean jetty:run -Djetty.port=8088编译启动web站点
9、测试站点
7、依赖
8、SpringMVC配置文件 resources/springmvc.xml
包扫描及resolver配置
9、SpringMVC控制器配置文件 web.xml
10、控制器
11、视图 webapp/WEB-INF/jsp/hello.jsp
八、SpringMVC
1、Spring MVC框架结构
web.xml
处理类
package com.baobaotao.web;
...
@Controller ①将UserController变成一个Handler
@RequestMapping(“/user”) ②指定控制器映射的URL
public class UserController {
@RequestMapping(value = “/register”) ③处理方法对应的URL,相对于②处的URL
public String register() {
return “user/register”; ④返回逻辑视图名
}
}
2、框架的实现者
3、SpringMVC的Controller
在java类前注解@Controller,该类的方法即可用来处理用户请求
4、SpringMVC的@RequestMapping
通过URL限定:URL表达式
@RequestMapping
标注路径
Controller的注解+
方法注解拼接完整路径
路径字符串可以是多级路径
可以同时注解多个路径
5、SpringMVC的@PathVariable
通过URL限定:绑定路径参数{xxx}
URL中的{xxx}
占位符可以通过@PathVariable("xxx")
绑定到操作方法的入参中。
@RequestMapping("/{id}")
public ModelAndView showDetail(@PathVariable(“id") String userId){
ModelAndView mav = new ModelAndView();
mav.setViewName("user/showDetail");
mav.addObject("user", userService.getUserById(userId));
return mav;
}
如果@PathVariable不指定参数名,只有在编译时打开debug开关(javac -debug=no)时才可行!!(不建议)
@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
@RequestMapping("/pets/{petId}")
public void findPet(@PathVariable String ownerId,
@PathVariable String petId, Model model) {
…
}
}
6、SpringMVC的RequestMethod
通过请求方法限定:请求方法
请求方法,在HTTP中这被叫做动词(verb),除了两个大家熟知的(GET和POST)之外,标准方法集合中还包含PUT、DELETE、HEAD和OPTIONS。这些方法的含义连同行为许诺都一起定义在HTTP规范之中。一般浏览器只支持GET和POST方法。
通过请求方法限定:模拟请求方法
通过在web.xml中配置一个org.springframework.web.filter.HiddenHttpMethodFilter
通过POST请求的_method参数指定请求方法,HiddenHttpMethodFilter动态更改HTTP头信息。
7、SpringMVC的params/headers
通过请求/请求头参数限定:示例
通过请求参数限定:params
@RequestMapping(value="/delete", params="userId")
public String test1(@RequestParam("userId") String userId){
...
}
通过请求头参数限定:headers
@RequestMapping(value="/show",headers="content-type=text/*")
public String test2(@RequestParam("userId") String userId){
...
}
通过请求/请求头参数限定:更多
params和headers分别通过请求参数及报文头属性进行映射,它们支持简单的表达式,下面以params表达式为例说明,headers可以参照params进行理解之。
- “param1”:表示请求必须包含名为param1的请求参数。
- “!param1”:表示请求不能包含名为param1的请求参数。
- “param1!=value1”:表示请求包含名为param1的请求参数,但其值不能为value1。
- {“param1=value1”,“param2”}:请求必须包含名为param1和param2的两个请求参数,且param1参数的值必须为value1。
8、从http请求中获取数据
request.getParameter(“”)
能否以java对象作为参数?
如何将请求参数映射为java对象?
9、SpringMVC请求参数绑定
通过注解绑定:示意图
10、通过注解绑定:基本类型绑定
@RequestMapping(value="/handle1")
public String handle1(@RequestParam("userName") String userName,
@RequestParam("password") String password,
@RequestParam("realName") String realName){
...
}
@RequestMapping(value="/handle2")
public String handle2(@CookieValue("JSESSIONID") String sessionId,
@RequestHeader("Accept-Language") String accpetLanguage){
...
}
11、通过注解绑定:小心抛出异常
@RequestParam有以下三个参数。
- value:参数名。
- required:是否必需,默认为true,表示请求中必须包含对应的参数名,如果不存在将抛出异常。
- defaultValue:默认参数名,设置该参数时,自动将required设为false。极少情况需要使用该参数,也不推荐使用该参数。
@RequestMapping(value="/handle1")
public String handle1(@RequestParam("userName") String userName,){
...
}
上面的处理方法 ,如果HTTP请求不包含“userName”参数时,将产生异常!!
因此,如果不能保证存在”userName”的参数,必须使用:
@RequestParam(value = "userName", required = false)
12、使用命令/表单对象绑定
所谓命令/表单对象并不需要实现任何接口,仅是一个拥有若干属性的POJO。
Spring MVC按:“HTTP请求参数名 = 命令/表单对象的属性名”
的规则,自动绑定请求数据,支持“级联属性名”,自动进行基本类型数据转换。
@RequestMapping(value = "/handle14")
public String handle14(User user) {
…
}
13、使用Servlet API对象作为入参
在Spring MVC中,控制器类可以不依赖任何Servlet API对象,但是Spring MVC并不阻止我们使用Servlet API的类作为处理方法的入参。值得注意的是,如果处理方法自行使用HttpServletResponse返回响应,则处理方法的返回值设置成void即可。
@RequestMapping(value = "/handle21")
public void handle21(HttpServletRequest request,HttpServletResponse response) {
String userName = WebUtils.findParameterValue(request, "userName");
response.addCookie(new Cookie("userName", userName));
}
public String handle23(HttpSession session) {
session.setAttribute("sessionId", 1234);
return "success";
}
public String handle24(HttpServletRequest request,
@RequestParam("userName")String userName) {
…
return "success";
}
可以通过 @Autowired 将HttpServletRequest、HttpServletResponse和HttpSession对象自动注入进来
@Autowired
HttpServletRequest request;
@Autowired
HttpServletResponse response;
@RequestMapping(value = "/handle21")
public void handle21() {
String userName = WebUtils.findParameterValue(request, "userName");
response.addCookie(new Cookie("userName", userName));
}
14、JSON数据返回
15、HttpMessageConverter< T>
16、JSON数据接口
(1)pom依赖: 支持请求与响应中 json数据处理 的jar包依赖
(2)Json响应——@ResponseBody
(3)json请求——@RequestBody
(4)Xml配置(dispatcher-servlet.xml)
mvc:annotation-driven 注解的作用:
(5)json响应——方法前注解@ResponseBody
(6)请求(地址栏输入)
localhost:8080/testspringmvc/hello/getJson.html
(7)响应(浏览器显示)
(8)json请求——参数前注解@RequestBody
(9)PostMan中测试
17、Json响应的封装
18、使用HttpEntity< T>/ResponseEntity< T>
缺点:处理方法签名受限
优点:不但可以访问报文体,还能访问报文头
@RequestMapping(value = "/handle43")
public String handle43(HttpEntity<String> httpEntity){
long contentLen = httpEntity.getHeaders().getContentLength();
System.out.println(httpEntity.getBody());
return "success";
}
@RequestMapping(params = "method=login")
public ResponseEntity<String> doFirst(){
HttpHeaders headers = new HttpHeaders();
MediaType mt=new MediaType("text","html",Charset.forName(“UTF-8"));
headers.setContentType(mt);
ResponseEntity<String> re=null;
String ret = new String("test");
re=new ResponseEntity<String>(ret,headers, HttpStatus.OK);
return re;
}
对于服务端的处理方法而言,除使用@RequestBody/@ResponseBody或HttpEntity< T> /ResponseEntity< T>进行方法签名外,不需要进行任何额外的处理,借由Spring MVC中装配的HttpMessageConverter,它即拥有了处理XML及JSON的能力了。
@RequestMapping(value = "/handle51")
public ResponseEntity<User> handle51(HttpEntity<User> requestEntity){
User user = requestEntity.getBody();
user.setUserId("1000");
return new ResponseEntity<User>(user,HttpStatus.OK);
}
19、数据绑定机理
20、数据类型转换
低版本的Spring 只支持标准的PropertyEditor类型体系,不过PropertyEditor存在以下缺陷:
(1)只能用于字符串和Java对象的转换,不适用于任意两个Java类型之间的转换;
(2)对源对象及目标对象所在的上下文信息(如注解、所在宿主类的结构等)不敏感,在类型转换时不能利用这些上下文信息实施高级转换逻辑。
有鉴于此,Spring 3.0在核心模型中添加了一个通用的类型转换模块, ConversionService是Spring类型转换体系的核心接口。
Spring 3.0同时支持PropertyEditor和ConversionService 进行类型转换,在Bean配置、Spring MVC处理方法入参绑定中使用类型转换体系进行工作。
21、强大的ConversionService->注解转换
由于ConversionService在进行类型转换时,可以使用到Bean所在宿主类的上下文信息(包括类结构,注解信息),所以可以实施更加高级的类型转换,如注解驱动的格式化等功能。
public class User {
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birthday;
}
以上User类,通过一个@DateTimeFormat注解,为类型转换提供了一些“额外”的信息,即代表日期的“源字符器”格式是“yyyy-MM-dd”
还有@NumberFormat
22、数据校验框架
Spring 拥有自己独立的数据校验框架,同时支持JSR 303标准的校验框架。Spring 的DataBinder在进行数据绑定时,可同时调用校验框架完成数据校验工作。在Spring MVC中,则可直接通过注解驱动的方式进行数据校验。
Spring的org.springframework.validation是校验框架所在的包
23、JSR 303
JSR 303是Java为Bean数据合法性校验所提供的标准框架,它已经包含在Java EE 6.0中。JSR 303通过在Bean属性上标注类似于@NotNull、@Max等标准的注解指定校验规则,并通过标准的验证接口对Bean进行验证。
你可以通过http://jcp.org/en/jsr/detail?id=303了解JSR 303的详细内容。
24、数据校验框架
< mvc:annotation-driven/>会默认装配好一个LocalValidatorFactoryBean
在命令对象类的定义中的属性前添加校验注解
在处理方法的命令对象前标注 @Valid注解 即可开启数据校验。
public class User {
@Pattern(regexp="w{4,30}")
private String userName;
@Length(min=2,max=100)
private String realName;
@Past
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birthday;
@DecimalMin(value="1000.00")
@DecimalMax(value="100000.00")
@NumberFormat(pattern="#,###.##")
private long salary;
}
注意:Spring本身没有提供JSR 303的实现,所以必须将JSR 303的实现者(如Hibernate Validator)的jar文件放到类路径下,Spring将自动加载并装配好JSR 303的实现者。
25、如何使用注解驱动的校验
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(value = "/handle91")
public String handle91(@Valid User user,
BindingResult bindingResult){
if(bindingResult.hasErrors()){
return "/user/register3";
}else{
return "/user/showUser";
}
}
}
在已经标注了JSR 303注解的表单/命令对象前标注一个@Valid,Spring MVC框架在将请求数据绑定到该入参对象后,就会调用校验框架根据注解声明的校验规则实施校验。
26、使用校验功能时,处理方法要如何签名?
Spring MVC是通过对处理方法签名的规约来保存校验结果的:前一个表单/命令对象的校验结果保存在其后的入参中,这个保存校验结果的入参必须是BindingResult或Errors类型,这两个类都位于org.springframework.validation包中。
27、校验错误信息存放在什么地方??
Spring MVC将HttpServletRequest对象数据绑定到处理方法的入参对象中(表单/命令对象);
将绑定错误信息、检验错误信息都保存到隐含模型中;
本次请求的对应隐含模型数据存放到HttpServletRequest的属性列表中,暴露给视图对象。
28、页面如何显示错误信息
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<title>注册用户</title>
<style>.errorClass{color:red}</style>
</head>
<body>
<form:form modelAttribute="user" action="user/handle91.html">
<form:errors path="*"/>
<table>
<tr>
<td>用户名:</td>
<td>
<form:errors path="userName" cssClass="errorClass"/>
<form:input path="userName" />
</td>
</tr>
…
</table>
</form:form>
</body>
</html>
29、如何对错误信息进行国际化
一个属性发生校验错误时,Spring MVC会产生一系列对应的错误码键:
public class User {
@Pattern(regexp=“w{4,30}”) // 假设发生错误
private String userName;
}
如果userName的 @Pattern校验规则未通过,则会在“隐含模型”中产生如下的错误键,这些错误键可以作为“国际化消息”的属性键。
- Pattern.user.userName
- Pattern.userName
- Pattern.String
- Pattern
我们在conf/i18n/下添加基名为messages的国际化资源,一个是默认的messages. properties,另一个是对应中国大陆的messages_zh_CN.properties。来看一下messages_zh_ CN.properties资源文件的内容:
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource"
p:basename="conf/i18n/messages"/>
30、Spring MVC如何解析视图
Controller的请求处理方法返回值类型
31、Model,ModelMap,以及ModelAndView之间的区别
32、在视图中显示模型中的数据
1、在pom中添加jstl和servlet依赖
2、在jsp中添加taglib<%@taglib uri=“http://java.sun.com/jsp/jstl/core” prefix=“c”%>
3、在Controller中添加返回数据
(1)返回值为String时:利用HttpServletRequest返回数据
(2)返回值为ModelAndView
4、
九、SSH整合开发
1、整合的目标
- 集成SpringMVC+Spring+Mybatis/JPA开发java web应用
- 利用SpringMVC处理用户的请求和响应
- 利用Spring容器管理各类bean并处理业务和依赖
- 利用JPA/hibernate/MyBatis提供数据服务
2、组件分层
(1)Web层(controller):处理用户请求并予以响应,需要业务层bean提供业务支持
(2)业务层:为web层的controller方法提供业务方法支持,需要数据层bean提供数据支持
(3)数据层:为业务层bean的方法提供数据支持,需要提供sessionFactory来管理和使用映射对象
3、整合点——都往Spring中整
1、SpringMVC与Spring天然整合
2、JPA/Hibernate整合到Spring
(1)关键是entityManagerFactory
(2)将datasource和entityManagerFactory作为bean配置到Spring中
(3)在Dao中注入entityManagerFactory
(4)将Dao通过@Repository加入Spring容器
3、MyBatis整合到Spring
(1)关键是整合sessionFactory
(2)将datasource和sqlSessionFactory作为bean配置到Spring中
(3)配置Mapper扫描将Mapper加入Spring容器
4、整合步骤
1、在web中启动Spring容器
(1)配置监听器
2、将所有业务bean通过注解部署到容器中
(1)包扫描
- Controller用@Controller注解
- Service用@Service和@Transactional注解
- Dao用@Repository注解
(2)Bean配置(datasource、 entityManagerFactory(JPA)、sessionFactory(MyBatis))
5、Swagger
Swagger 是一个规范和完整的框架,用于生成、描述、测试和可视化 RESTful 风格的 Web 服务。
6、Swagger配置
(1)Jar包依赖
(2)SpringMVC配置文件
(3)Swagger配置类
(4)Controller注解
(5)Controller方法参数/返回值对象注解
(6)运行主程序
访问http://localhost:8080/swagger-ui.html
7、SSH的java web项目中的容器
spring的容器:由listener启动,为父容器
SpringMVC容器:由dispatchservlet启动,为子容器
spring mvc里在配置controller时,可以直接引用在spring中配置的service类;
在web.xml配置中,要先配置spring的配置,然后配置spring mvc的配置,否则spring mvc的子容器无法使用父容器中的资源
父容器中的bean不能引用子容器中的bean
8、整合示例——联系人管理