参数绑定,RequestMapping、返回值处理、拦截器、RESTful支持、跨域
SpringMVC-全面了解
处理请求映射,视图解析。对servlet做了封装。
执行流程:
- 用户发送请求至前端控制器DispatcherServlet。
- DispatcherServlet收到请求调用HandlerMapping处理器映射器。
- 处理器映射器找到具体的处理器返回给DispatcherServlet。
- DispatcherServlet调用HandlerAdapter处理器适配器。
- HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
- Controller执行完成返回ModelAndView。
- HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
- ViewReslover解析后返回具体View.
- DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
- DispatcherServlet响应用户。
介绍
SpringMVC是spring-web模块的一部分。
六大组件
对外的三大组件
前端控制器、处理器、视图
内部三大组件
处理器映射器、处理器适配器、视图解析器
前后端分离只需要开发处理器。
参数绑定
接收前端传递的参数后,SpringMVC依据绑定规则转换参数后,传递给Controller的形参。
SpringMVC底层采用24种绑定解析器(ArgumentResolver)处理
介绍
请求参数格式:
请求参数数据类型
请求参数要绑定的目标类型
1
| Controller类中的方法参数,比如简单类型、POJO类型、集合类型等。
|
RequestParam注解
1 2 3
| value:参数名字,即入参的请求参数名字 required:默认是true,表示请求中一定要有相应的参数 defaultValue:请求中没有同名参数时的默认值,使用时,required失效
|
1
| public ModelAndView test(@RequestParam(value="name",required=false)String name){
|
绑定类型
简单类型数组
1
| 通过HTTP请求批量传递简单类型数组,Controller方法中可以用String[]或者pojo的String[]属性接收 (两种方式任选其一),但是不能使用List集合接收。
|
POJO类型集合或数组
1
| 批量传递的请求参数,最终要使用List<POJO>来接收,List<POJO>必须放在另一个POJO类中
|
自定义日期 参数绑定
1
| 对于springmvc无法解析的参数绑定类型,需要自定义 [参数转换器]进行参数绑定。
|
Converter代码
1 2 3 4 5 6 7 8 9 10 11 12
| public class DateConverter implements Converter<String, Date> { @Override public Date convert(String source) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); try { return simpleDateFormat.parse(source); } catch (ParseException e) { e.printStackTrace(); } return null; } }
|
Converter配置
1 2 3 4 5 6 7
| <!-- 转换器配置 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set>< bean class="com.kkb.ssm.controller.converter.DateConverter"/> </set> </property> </bean>
|
文件类型绑定
1.加入依赖 commons-fileupload
2.前端配置
1
| JSP中的form表单需要指定enctype=”multipart/form-data”
|
3.配置Multipart解析器
1 2 3 4 5
| <!-- multipart类型解析器,文件上传 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 上传文件的最大尺寸 5M--> <property name="maxUploadSize" value="5242880"/> </bean>
|
4.Cotroller类代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @RequestMapping("fileupload") public String findUserById(MultipartFile uploadFile) throws Exception { if (uploadFile != null) { System.out.println(uploadFile.getOriginalFilename()); // 原始图片名称 String originalFilename = uploadFile.getOriginalFilename(); // 如果没有图片名称,则上传不成功 if (originalFilename != null && originalFilename.length() > 0) { // 存放图片的物理路径 String picPath = "E:\\"; // 获取上传文件的扩展名 String extName = originalFilename.substring(originalFilename.lastIndexOf(".")); // 新文件的名称 String newFileName = UUID.randomUUID() + extName; // 新的文件 File newFile = new File(picPath + newFileName); // 把上传的文件保存成一个新的文件 uploadFile.transferTo(newFile); // 同时需要把新的文件名更新到数据库中 // TODO } } return "文件上传成功"; }
|
RequestMapping
value属性
1 2
| // 用于映射URL和HandlerMethod方法 @RequestMapping(value="test")
|
method属性
1 2 3
| // 限定请求URL使用指定的method请求方式 @RequestMapping(value="/test",method=RequestMethod.GET) @RequestMapping(value="/test",method={RequestMethod.GET,RequestMethod.POST})
|
params属性
1 2 3 4 5 6
| // 访问HandlerMethod 的限制 @RequestMapping(value="test",params= {"name","price>5000"}) public String test(Model model) { model.addAttribute("msg", "test方法执行了"); return "success"; }
|
返回值处理
注解
@ResponseBody
1
| 针对Controller返回值类型,使用内置的9种HttpMessageConverter进行匹配,找 到合适HttpMessageConverter进行处理。
|
@RequestBody 处理请求参数的http消息转换
1 2 3 4 5
| @ResponseBody @RequestMapping() public Message test(@RequestBody json){
}
|
非注解
1.ModelAndView
1
| public ModelAndView test(){}
|
ModelAndView 可添加model数据、指定view。
2.void
1
| public void test(HttpServletRequest request, HttpServletResponse response){}
|
request转发向页面
1
| request.getRequestDispatcher("页面路径").forward(request, response);
|
过response页面重定向
1
| response.sendRedirect("url")
|
response指定响应结果,例如响应json数据如下
1
| response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().write("json串");
|
3.String
forward转发
1
| return “forward:testForward";
|
1 2 3 4 5
| 相当于“ request.getRequestDispatcher().forward(request,response) ”
浏览器URL不发送改变
Request 域可以共享
|
拦截器
Spring MVC 的拦截器做了三次拦截。请求拦截一次,返回拦截两次。
请求拦截可做登录认证。
返回拦截中视图处理,前后端分离后不需要了
返回拦截中**,可用统一日志、统一异常处理。
定义拦截器
实现SpringMVC的HandlerIntercepter 接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class MyHandlerIntercepter implements HandlerInterceptor{
//Handler执行前调用 //应用场景:登录认证、身份授权 //返回值为true则是放行,为false是不放行 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return false; } //进入Handler开始执行,并且在返回ModelAndView之前调用 //应用场景:对ModelAndView对象操作,可以把公共模型数据传到前台,可以统一指定视图 @Override public void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } //执行完Handler之后调用 //应用场景:统一异常处理、统一日志处理 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
|
配置拦截器
SpringMVC 拦截器是绑定在 HandlerMapping 中的,即:如果某个 HandlerMapping 中配置拦截,则该HandlerMapping 映射成功的 Handler 会使用该拦截器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <!-- 配置全局mapping的拦截器 --> <mvc:interceptors> <!-- 公共拦截器可以拦截所有请求,而且可以有多个 --> <bean class="com.ssm.interceptor.MyHandlerInterceptor" /> <bean class="com.ssm.interceptor.MyHandlerInterceptor2" /> <!-- 如果有针对特定URL的拦截器,则进行以下配置 --> <mvc:interceptor> <!-- /**表示所有URL和子URL路径 --> <mvc:mapping path="/orders/**" /> <!-- 特定请求的拦截器只能有一个 --> <bean class="com.ssm.interceptor.MyHandlerInterceptor3" /> </mvc:interceptor> </mvc:interceptors>
<!-- 如果有多个拦截器,那么配置到`springmvc.xml`中最上面的拦截器,拦截优先级最高。 -->
|
Restful支持
rest介绍
REST(英文:Representational State Transfer,意思是:(资源)表述性状态转化)
rest是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。
基于rest风格设计的软件更简洁,有层次,更易于实现缓存等机制。
资源
1 2
| 网络上的一个实体,例如:一段文本、一张图片、一首歌曲、一种服务。 可以用URI(统一资源定位符)指向它,每种资源对应一个特定的URI。
|
表现层
1 2
| 把资源呈现出来的形式,叫做表现层。 格式:html、xml、json,二级制。
|
状态转化
1 2 3 4
| 每发出一个HTTP请求,就代表了客户端和服务器的一次交互过程。 HTTP协议,是一个无状态协议,即所有的【状态】 都保存在服务器端。因此,如果客户端想要操作服务器, 必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是 “ 表现层状态转化” 。
HTTP 协议里面,四个表示操作方式的动词:GET 、POST 、PUT 、DELETE 。它们分别对应四种 基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。
|
如何设计RESTful应用程序的API
1 2
| 路径设计:数据库设计完毕之后,基本上就可以确定有哪些资源要进行操作,相对于资源的路径也可以设计出来 动词设计:也就是针对资源的具体操作类型,由HTTP动词表示,常用的HTTP动词如下:POST、DELETE、PUT、GET
|
RESTful的示例:
1 2 3
| /account/1 HTTP GET : 得到 id = 1 的 account /account/1 HTTP DELETE: 删除 id = 1 的 account /account/1 HTTP PUT: 更新 id = 1 的 account
|
SpringMVC如何支持Restful
配置
1 2 3 4 5 6
| // 拦截RESTful请求 <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> // 设置为/ ,前后端不分离时,需要处理静态资源路径。
|
url与参数绑定
@PathVariable
1 2 3 4 5 6
| // 请求URL http://localhost:8080/ssm/item/1/lisi
// Controller @RequestMapping(“{id}/{name}”) @ResponseBody public Item queryItemById(@PathVariable Integer id, @PathVariable String name){}
|
资源的表现形式
SpringMVC中可以使用 ContentNegotiatingManager这个内容协商管理器来控制表现形式
1 2 3
| 扩展名:比如.json表示我要JSON格式数据、.xml表示我要XML格式数据 请求参数:默认是”format” 请求头设置Accept参数:比如设置Accept为application/json表示要JSON格式数据
|
请求方式
1 2
| @RequestMapping:通过设置method属性值 @GetMapping、@PostMapping、@PutMapping、@DeleteMapping注解等同@RequestMapping注解配置method属性。
|
跨域
介绍
浏览器为了安全有这么一个规定:同源策略,即只用同源才可以访问浏览器的数据,非同源不可访问。
同源:相同的http协议、相同的域名、相同的端口号。
前后端分离后,前端和后端不是同源。这种情况我们要实现前后的非同源访问,就是跨域访问。
解决
三种方式:基于JavaScript标签的src方式,基于JQuery的JSONP方式,基于CORS的方式。
JSONP只能解决get方式。CORS可解决GET、POST。
CORS
介绍
CORS 是一个 W3C 标准,全称是”跨域资源共享”( Cross-origin resource sharing )。
它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求。
CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能, IE 浏览器不能低于 IE10
请求信息:

响应信息:

前端设置请求头。
1
| 自动向请求头 header 中注入 Origin 。
|
后端对响应拦截,设置响应头
1
| 服务器端需要向响应头 header 中注入 Access-Control-Allow-Origin
|
CORS实现跨域
CORS通过拦截器实现
跨域不提交cookie
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class AllowOriginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception { // 跨域行为参考网址 http://www.cnblogs.com/renhaisong/p/6892341.html if (request.getHeader("Origin") != null) { response.setContentType("text/html;charset=UTF-8"); // 允许哪一个URL response.setHeader("Access-Control-Allow-Origin", "*"); // 允许那种请求方法 response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT"); response.setHeader("XDomainRequestAllowed", "1"); System.out.println("正在跨域"); } return true; } }
|
跨域提交Cookie
注意:
Access-Control-Allow-Credentials 为 true 的时候, Access-Control-Allow-Origin 不能设置为”*”,否则报错。
- 如果有多个拦截器,把处理跨域请求的拦截器放到首位
前端JQuery代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| $.ajax({ url: 'url', method:'请求方式', //GET POST PUT DELETE xhrFields:{ withCredentials:true }, success:function(data){ // do something }, error:function(){ // do something } })
|
后端JAVA代码,采用springMVC拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class AllowOriginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception { // 有跨域行为时参考网址 http://namezhou.iteye.com/blog/2384434 if (request.getHeader("Origin") != null) { response.setContentType("text/html;charset=UTF-8"); // 允许哪一个URL访问 request.getHeader("Origin") 动态获取请求来的url response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); // 允许那种请求方法 response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,HEAD"); // 本次预检请求的有效期 ("0":每次异步请求都发起预检请求,允许跨域,再发出正式请求。"3600":有效期1小时) response.setHeader("Access-Control-Max-Age", "0"); // 允许请求头里的参数列表 response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token"); // 允许对方带cookie访问 response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("XDomainRequestAllowed", "1"); System.out.println("可接待cookie跨域"); } return true; } }
|
后端JAVA代码,采用过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Component // 表示这是配置类,注入到Spring容器中。(不属于@Controller、@Services、@repository) public class CorsFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; HttpServletRequest httpRequest = (HttpServletRequest) request; httpResponse.setHeader("Access-Control-Allow-Origin", httpRequest.getHeader("Origin")!=null ? httpRequest.getHeader("Origin"):""); httpResponse.setHeader("Access-Control-Allow-Methods", httpRequest.getMethod()); httpResponse.setHeader("Access-Control-Max-Age", "3600"); httpResponse.setHeader("Access-Control-Allow-Credentials", "true"); httpResponse.setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers")); chain.doFilter(request, response); } @Override public void destroy() { } }
|
CORS通过注解方式
springMVC4.x以上: