Spring MVC
一个开源的轻量级Web框架,能够简化日常开发。
1. 核心组件:
-
DispatcherServlet 前置控制器
负责接收请求、分发请求
-
Handler 处理器
处理器包括了拦截器、控制器中的方法等,主要负责处理请求
-
HandlerMapping 处理器映射器
解析配置文件、扫描注解,将请求与处理器进行匹配
-
HandlerAdpter 处理器适配器
根据请求来找到匹配的处理器,这个过程称为适配
-
ViewResolver 视图解析器
处理器执行后得到的结果可能是一个视图,但这个视图属于逻辑视图(页面中存在逻辑代码,比如循环、判断),需要使用视图解析起进行处理,这个过程称为渲染视图
2. spring mvc快速搭建
2.1 pop依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!--开发版-->
<spring.mvc.dev>5.3.10</spring.mvc.dev>
</properties>
<dependencies>
<!--spring core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.mvc.dev}</version>
</dependency>
<!-- spring mvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.mvc.dev}</version>
</dependency>
<!--阿里用来处理JSON格式的数据的包,因为处理速度很快,所以叫fast json-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
2.2 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">
<!-- -->
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--在参数中说明关于springMVC的配置文件位置-->
<init-param>
<param-name>contextConfigLocation</param-name>
<!--classpath:表示在resources文件夹下-->
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!--前置控制器要接收所有的请求,因此在容器启动的时候就应该完成初始化-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encodingFilter</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>
<init-param>
<!--强制编码-->
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>methodFilter</filter-name>
<!--这个过滤器的作用就是将表单中的隐藏域表示请求方式用来替换原来发送的请求方式-->
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>methodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
2.3 spring-mvc.xml
resources文件夹下
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--设置配置文件,能够使用@Value("${ }")进行注入String值-->
<context:property-placeholder location="classpath:config.properties" />
<!--1. 视图解析器:内部资源视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
</bean>
<!--String类型HTTP消息转换器-->
<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter" />
<!--JSON格式的消息使用FastJson来处理-->
<bean id="jsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<!--支持转换的媒体类型:也就是发送数据的content-type的类型-->
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
<!--这里就是开启MVC注解支持-->
<mvc:annotation-driven>
<!--消息转换器配置:我们在接收请求的时候,需要为参数赋值,这个值需要使用消息转换器来进
行转换,还有就是我们在处理完请求后需要向页面发送数据,这个数据也需要使用消息转换器来处理-->
<mvc:message-converters>
<ref bean="stringHttpMessageConverter" />
<ref bean="jsonHttpMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
<!--mapping是访问路径,location是静态资源存放的路径-->
<!-- <mvc:resources mapping="/static/**" location="/static/" />-->
<!--
这个handler就是处理静态资源的,它的处理方式就是将请求转会到tomcat中名
为default的Servlet
-->
<mvc:default-servlet-handler />
<!--使用上下文进行组件扫描-->
<context:component-scan base-package="com.dream.spring.mvc.controller" />
</beans>
3. 常用注解:
@Controller :表示控制层
@RequestMapping:表示匹配请求
@RequestBody:用于参数,表示从请求体中获取
@ResponseBody:用于向页面传输数据
@RequestParam:用于参数,表示从请求头中注入值
@PathVariable:用于参数,表示将请求路径中获取数据并注入至参数中
@SessionAttributes :该注解只能使用在类定义上,用于从将输入放入 session 中
@RequestHeader:该注解只能应用在方法的参数上,用于从请求头中获取数据
@CookieValue:该注解只能应用在方法的参数上,用于从请求中获取cookie的值使用
4. 简单使用示例:
@Controller
@RequestMapping("/user")
public class UserController {
@ResponseBody
@RequestMapping("/login")
public User login(@RequestBody User user){
System.out.println(user.getUsername()+"---"+user.getPassword());
return user;
}
@RequestMapping(value="/{username}", method= RequestMethod.GET)
@ResponseBody
public User queryUser(@PathVariable("username") String username){
return new User(username,"111111");
}
}
5. RESTFUL风格
5.1 RESTFUL简介
REST全称为 Representational State Transfer,表示 表述性状态转移。
RESTFUL有如下特点:
- 每一个 URI 代表一种资源
- 客户端使用GET、POST、PUT、DELETE 这4 个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源
5.2 Spring MVC对于RESTFUl的支持
web.xml的配置:(使用过滤器)
<filter>
<filter-name>methodFilter</filter-name>
<!--这个过滤器的作用就是将表单中的隐藏域表示请求方式用来替换原来发送的请求方式-->
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>methodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
通过注解来使用:
@RestController
该注解只能应用于类上,相当于@Controller 和 @ResponseBody 注解的组合。表示该类中的所有方法执行完成后所返回的结果直接向页面输出
@GetMapping、@PostMapping、 @PutMapping 、@DeleteMapping
5.3 在前端通过Ajax发送
//这是封装之后的Ajax请求方法,支持RESTFUL风格。
Vue.prototype.ajax = function(method, url, data){
if(method.toLowerCase() === 'get'){
return Vue.prototype.$get(url, data);
} else {
return axios({
url: url,
method: method,
data: data || {}
}).catch(function error(xhr) {
console.log(xhr);
})
}
}
6. 静态资源处理
6.1. 静态资源无法访问的原因
前后端耦合时:静态资源包含html、js、css、图片、字体文件等。静态文件没有url-pattern,所以默认是访问不到的。之所以可以访问,是因为tomcat中有一个全局的servlet:org.apache.catalina.servlets.DefaultServlet,它的url-pattern是 “/”, 所以项目中不能匹配的静态资源请求,都由这个Servlet来处理。但在SpringMVC中DispatcherServlet也采用了"/" 作为url-pattern, 那么项目中不会再使用全局的Serlvet,这样就造成了静态资源不能完成访问。
6.2. 处理方案
6.2.1 方案一
DispathcerServlet 对应的 url-pattern 修改为 “/” 以外的其他匹配样式即可。比如 *.do, *.action。这样修改后,发送请求时,请求URL必须匹配 .do 或者 .action。
6.2.2 方案二
<!-- web.xml -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
6.2.2 方案三
<!-- spring-mvc.xml -->
<!--
这个handler就是处理静态资源的,它的处理方式就是将请求转会到tomcat中名为default的Servlet
-->
<mvc:default-servlet-handler/>
<!-- mapping是访问路径,location是静态资源存放的路径 -->
<mvc:resources mapping="/static/**" location="/static/" />
7. Spring MVC工作原理
checkMultipart(request); //检测是否是多部分请求,这个只可能在文件上传的时候为真
getHandler(processedRequest); //获取处理器 => 遍历HandlerMapping,找到匹配当前请求的执行器链
//没有找到执行器链 就直接向页面报一个404
noHandlerFound(processedRequest, response);
//找到处理当前请求的适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
//控制器之前执行的拦截器将先执行,如果拦截器不通过,则方法直接结束
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//控制器处理请求,可能会得到一个ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//控制器之后的拦截器执行
mappedHandler.applyPostHandle(processedRequest, response, mv);
//处理分发的结果:这个结果就是控制器处理后的结果
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
//拦截器在控制器给出的结果DispatcherServlet处理后执行
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);