1.Spring-MVC基础原理

[TOC]

1.概念

优秀的Web框架,具有松散耦合,拔插组件结构,注解驱动,REST风格支持等特性,比其他web框架更具有扩展性和灵活性

数据绑定,视图解析,本地化处理,静态资源处理上有不俗的表现,远超Struts2,WebWork等MVC框架

springmvc

2.MVC框架

MVC全称 Model veiw Controller(模型视图控制器) 软件级的解耦分离

  • M:主要包含service(核心业务逻辑)和dao(数据库访问)
  • V:静态资源,如HTML5,JS,CSS
  • C:servlet(主要处理页面的转发和重定向,数据的接收,域对象的操作,)和jsp(本身也是servlet)

MVC 分层有助于管理复杂的应用程序,因为您可以在一个时间内专门关注一个方面。例如,您可以在不依赖业务逻辑的情况下专注于视图设计。同时也让应用程序的测试更加容易

MVC 分层同时也简化了分组开发。不同的开发人员可同时开发视图控制器逻辑业务逻辑

(扩展)Spring MVC是基于 Model 2实现的技术框架,Model 2是经典的MVC(model,view,control)模型在WEB应用中的变体.这个改变主要源于HTTP协议的无状态性,Model 2 的目的和MVC一样,也是利用处理器分离模型,视图和控制,达到不同技术层级间松散层耦合的效果,提高系统灵活性,复用性和可维护性.大多情况下,可以将Model 2 与 MVC等同起来.

(扩展)三层架构基础

  • 物理三层架构:客户端(如浏览器)/Web服务器/数据库服务器

  • 逻辑三层架构:表现层/业务逻辑层/数据库访问层

3.Spring MVC体系概述

Spring-MVC围绕着DispatcherServlet(前段控制器)这个核心展开,所有的前端请求都会拦截经过这里分发到Spring MVC的各个处理器中处理,(扩展)如注解驱动控制器,请求及响应的信息处理,视图解析,本地化解析,上传文件解析,异常处理及表单标签绑定内容等…

4.Spring MVC核心组件

  • DispatcherServlet:作为前端控制器,整个流程控制的中心,控制其它组件执行,统一调度,降低组件之间的耦合性,提高每个组件的扩展性。
  • HandlerMapping:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
  • HandlAdapter:通过扩展处理器适配器,支持更多类型的处理器,调用处理器传递参数等工作!
  • ViewResolver:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel等。

5.Spring MVC执行流程

mvc流程

5-1.Controller和Handler关系

Controller指的是类

Handler指的是Controller中的方法,每次URL访问Handler都是访问的@RequestMapper所标注的方法

6.DispatcherServlet

1.核心

  1. DispatcherServlet 是Spring-MVC的核心构成,负责协调所有mvc的处理器,
  2. DispatcherServlet可以和Spring-IoC无缝集成,获得Spring的所有好处
  3. 使用时需要在web.xml中对DispatcherServlet进行配置

2.DispatcherServlet继承关系图

继承关系图

3.DispatcherServlet的责任

主要负责调度Spring-mvc的工作,并控制MVC的流程

  1. 文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析;
  2. 通过HandlerMapping,将请求映射到处理器(返回一个HandlerExecutionChain,它包括一个处理器、多个HandlerInterceptor拦截器);
  3. 通过HandlerAdapter支持多种类型的处理器(HandlerExecutionChain中的处理器);
  4. 通过ViewResolver解析逻辑视图名到具体视图实现;
  5. 本地化解析;
  6. 渲染具体的视图等;
  7. 如果执行过程中遇到异常将交给HandlerExceptionResolver来解析。

4.DispatcherServlet核心代码

5.DispatcherServlet辅助类

传送门:https://xuzhongcn.github.io/#top

7.常用注解(实用重点)

1.@RequestMapping 请求方式

写在类或者方法上,表示请求该类或方法的路径

1.value method

value: 请求路径

指定为普通具体值(如”/dologin”)

指定为某一变量

1
2
3
4
5
6
@RequestMapping(value="/user/{username}", method=RequestMethod.GET)
public String findOwner(@PathVariable String username, Model model) {
User user=userService.selectUserByUsername(username);
model.addAttribute("user", user);
return "user";
}

指定为含有正则表达式的变量(略)

method: 请求类型 GET、POST、PUT、DELETE等

RestFull

https://blog.csdn.net/gebitan505/article/details/70143901

2.consumes produces

consumes: 指定处理请求提交的内容类型(Content-Type),例如application/json, text/html;

1
2
3
4
5
6
@Controller
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")
public void addPet(@RequestBody Pet pet, Model model) {
// implementation omitted
//方法仅处理request Content-Type为“application/json”类型的请求。
}

produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;

1
2
3
4
5
6
@Controller
@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json")
@ResponseBody
public Pet getPet(@PathVariable String petId, Model model) {
// implementation omitted
}

仅处理request请求头header中包含了指定类型application/json的请求,同时暗示返回数据也是json

3.params headers

params: 指定request中必须包含某些参数才可以调用该方法

1
2
3
4
5
6
7
8
9
@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {

@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, params="myParam=myValue")
public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
// implementation omitted
}
}

仅处理请求中包含了名为“myParam”,值为“myValue”的请求;

headers:指定的request中必须包含指定的header值才可以调用该方法

1
2
3
4
5
6
7
8
9
@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {

@RequestMapping(value = "/pets", method = RequestMethod.GET, headers="Referer=http://www.ifeng.com/")
public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
// implementation omitted
}
}

仅处理request的header中包含了指定“Refer”请求头和对应值为“http://www.ifeng.com/”的请求;

2.@RequestParam 处理请求参数

3.@PathVariable 路径传参

4.@RequestBody 处理Json/xml请求

requestBody 常用来处理不是默认类型application/x-www-form-urlcoded 的请求

如application/json或者是application/xml等(一般处理json)

requestBody可以将请求体中的JSON字符串绑定到相应的bean上,也可以将其分别绑定到对应的字符串上

1
2
3
4
5
6
7
8
9
 @requestMapping("/login")
    public void login(@requestBody String userName,@requestBody String pwd){
      System.out.println(userName+" :"+pwd);
    }
---------------
 @requestMapping("/login")
    public void login(@requestBody User user){
      System.out.println(user);
    }

5.@ResponseBody 处理Json/xml 响应

responseBody:用于将数据放到response的body体中响应到前端

注意:返回的数据不是html标签页面,而是json/xml数据

如果返回String,此方法原理相当于response.write(),都不走视图解析,直接响应给页面数据,如果使用对象,才会解析为json

6.@JsonFomat格式化时间

1
2
3
4
5
6
7
8
9
/**更新时间  用户可以点击更新,保存最新更新的时间。**/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Date updateTime;

或者getter上
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
public Date getUpdateTime() {
return updateTime;
}

格式化时间

对于请求类型的适配原理

传送门:http://www.cnblogs.com/qq78292959/p/3760651.html

8.伪静态化SEO优化

请求的后缀改为.html 可以实现伪静态化,欺骗SEO搜索(对动态不友好),此处拦截也可以改为*.html,

这样静态资源也不会被拦截(不需要配置静态资源映射了)

8-1.简单优化过程

web.xml

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>e3-portal-web</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>

<!-- 解决post乱码 -->
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- springmvc的前端控制器 -->
<servlet>
<servlet-name>e3-portal-web</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>e3-portal-web</servlet-name>
<!-- 拦截指定后缀所有请求 伪静态化 -->
<url-pattern>*.html</url-pattern>
</servlet-mapping>

</web-app>

Handler

1
2
3
4
@RequestMapping("/index.html")
public String showIndex(){
return "index";
}
  1. 欢迎页改为index.html 当静态页面中没有index.html时,请求会被Spring-mvc拦截器拦截到(后缀为.html)
  2. 拦截到index请求后发送到Controller中的对应Handler中,完成伪静态优化