Spring-MVC
一.基础配置
- 引入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.14</version>
</dependency>
- 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">
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置Spring环境初始化文件的位置-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<!-- 容器启动的时候自动创建并初始化dispatcherServlet实例-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!-- /:代表拦截所有请求 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- applicationContext.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"
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
https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 包扫描-->
<context:component-scan base-package="pers.zhou"/>
<!-- 开启SpringMVC的注解开发模式-->
<mvc:annotation-driven/>
<!-- 对静态资源的处理进行优化,让DispatcherServlet不进行拦截-->
<mvc:default-servlet-handler/>
</beans>
二.SpringMVC
相关组件
SpringMVC
提供了DispatcherServlet
作为前端控制器,用来分发请求
SpringMVC
有很多组件,为了做不同的分工,控制器,验证器,模型对象每个功能的实现由专门的组件完成
SpringMVC
可以对用户的输入做一个自动绑定
,能够对数据进行一个数据转换
SpringMVC
默认有一个叫做视图解析器的组件,默认情况下可以对jsp
进行解析;如果要对其他的模板引擎解析,则需要引入额外的依赖
SpringMVC重要组件
key-value形式
左边是组件的接口,右边是组件的实现类
# i18n国际化组件(本地化解析器)
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
# 主题解析器
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
# 处理器/映射器
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
org.springframework.web.servlet.function.support.RouterFunctionMapping
# 处理器适配器
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
org.springframework.web.servlet.function.support.HandlerFunctionAdapter
# 异常处理器
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
# 视图名称解析器
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
# 视图解析器
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
# FlashMap映射管理器
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
// 初始化SpringMVC其他的组件的策略
protected void initStrategies(ApplicationContext context) {
//初始化上传文件相关的解析器,默认为null
initMultipartResolver(context);
// 初始化本地化解析器
initLocaleResolver(context);
// 初始化主题解析器
initThemeResolver(context);
// 初始化处理器映射器
initHandlerMappings(context);
// 初始化处理器适配器
initHandlerAdapters(context);
// 初始化异常处理器
initHandlerExceptionResolvers(context);
// 初始化请求到视图名的解析器
initRequestToViewNameTranslator(context);
// 初始化视图解析器
initViewResolvers(context);
// 初始化flish映射的解析器
initFlashMapManager(context);
}
三.处理请求
3.1 第一个请求
@Controller
@RequestMapping("/login")
public class LoginController {
@RequestMapping(value = "/firstLogin",method = {RequestMethod.GET,RequestMethod.POST})
@ResponseBody
public String firstLogin(){
return "index.html";
}
}
@RequestMapping
该注解的原属性除了value
和path
之外(这两个原属性的配置的是等效的),还有一个是method
比较重要,用来赛选该方法只能处理那些HTTP方法的请求
RequestMethod[] method() default {};
而
RequestMethod
是一个枚举,里面列举了所有HTTP方法类型
public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}
如果没有指定
method
属性,则当前方法可以处理任意HTTP
请求方法类型
其实Spring后期,在基于
RequestMapping
注解之上做了一些派生注解
@RequestMapping(method = RequestMethod.POST)
public @interface PostMapping {
@RequestMapping(method = RequestMethod.GET)
public @interface GetMapping {
点开源码,实际就是对
@RequestMapping
做了一个派生
默认情况下@RequestMapping
能够处理content-type
为application/x-www-form-urlencoded
3.2 请求参数绑定
- 什么注解都不加:直接在参数列表里面写上前端传过来的参数名,或者使用包装类
直接传参
@Controller
@RequestMapping("/login")
public class LoginController {
@RequestMapping(value = "/firstLogin",method = {RequestMethod.GET,RequestMethod.POST})
@ResponseBody
// --> http://localhost:8080/login/firstLogin?username=admin
public String firstLogin(String username){
System.out.println("请求的username为"+username);
//--> 请求的username为admin
return "index.html";
}
}
传包装类
@Controller
@RequestMapping("/login")
public class LoginController {
@RequestMapping(value = "/firstLogin",method = {RequestMethod.GET,RequestMethod.POST})
@ResponseBody
// --> http://localhost:8080/login/firstLogin?username=admin&password=123
public String firstLogin(User user){
System.out.println("请求的user为"+user);
//--> 请求的user为User{username='admin', password='123'}
return "index.html";
}
}
前端与后端参数命名不一致 使用注解
@RequestParam
可以为名称不匹配的参数做绑定,可以设置该参数是否必传,也可以为该参数设置默认值,如果前端没有传,则默认值生效
@AliasFor("name")
String value() default "";
//The name of the request parameter to bind to. 要绑定到的请求参数的名称。
@AliasFor("value")
String name() default "";
//Whether the parameter is required. 参数是否为必填项 默认为true
boolean required() default true;
// 默认值 --应用场景 不登录试玩
String defaultValue() default ValueConstants.DEFAULT_NONE;
@Controller
@RequestMapping("/login")
public class LoginController {
@RequestMapping(value = "/firstLogin",method = {RequestMethod.GET,RequestMethod.POST})
@ResponseBody
// --> http://localhost:8080/login/firstLogin?user_name=admin
public String firstLogin(@RequestParam("user_name") String username){
System.out.println("请求的username为"+username);
//--> 请求的username为admin
return "index.html";
}
}
还可以看出来,SpringMVC之前一直是基于Servlet,那么其实在方法的参数上还是可以加上原生的
HttpServletRequest
和HttpServletResponse
@Controller
@RequestMapping("/login")
public class LoginController {
@RequestMapping(value = "/firstLogin",method = {RequestMethod.GET,RequestMethod.POST})
@ResponseBody
// --> http://localhost:8080/login/firstLogin?user_name=admin
public String firstLogin(@RequestParam("user_name") String username, HttpServletRequest request, HttpServletResponse response){
String user_name = request.getParameter("user_name");
System.out.println("httpRequest获得的参数"+user_name);
//httpRequest获得的参数admin
System.out.println("MVC请求的username为"+username);
//--> MVC请求的username为admin
return "index.html";
}
}
@PathVaruable
//http://localhost:8080/login/firstLogin/20
@RequestMapping(value = "/fr/{myage}")
@ResponseBody
public String firstRequest(@PathVariable("myage") Integer age) {
System.out.println("====>age"+age);
// -->age 20
//默认情况返回字符串,SpringMVC会根据返回值查找对应的模板引擎的名字
return "index.html";
}
@RequestBody
用来接收请求体中的数据,特别是GET请求没有请求体
@CookieValue
用来绑定请求包中的Cookie的值
/**
* 通过MVC拿到Cookie
* @param sessionId
* @return
*/
@GetMapping("/cookieReq")
@ResponseBody
public String cookieRequest(@CookieValue("JSESSIONID") String sessionId){
System.out.println("拿到的Cookie的值为:"+sessionId);
return sessionId;
}
3.3 接收各种类型的数据
用数组接收前端传过来的数组
/**
* 用数组接收前端传过来的数组
*/
@PostMapping("/getcomplexdata")
@ResponseBody
// @RequestParam 当使用List集合需要加上当前注解
public String getComplexDara(String username,String lady,int[] reason){
return "success";
}
用集合接收前端传过来的数组
@PostMapping("/getcomplexdata")
@ResponseBody
// Map 如果是数组那么只能拿到第一个
public String getComplexDara(@RequestParam Map map){
System.out.println(map);
return "success";
}
@RequestParam
当使用集合需要加上当前注解
用对象接收前端传过来的参数
@PostMapping("/getcomplexdata")
@ResponseBody
public String getComplexDara(Form form){
System.out.println(form);
return "success";
}
对象接受级联数据
/**
* @author : Jack_Zhou
*/
public class Form {
private String username;
private String lady;
private List<Integer> reason;
/**
* 收货地址(对象级联参数赋值)
*/
private EmsInfo emsInfo;
public EmsInfo getEmsInfo() {
return emsInfo;
}
<form action="/form/getcomplexdata" method="post">
<h3>您的名字</h3>
<!--输入框传值 -->
<p><input type="text" name="username"></p>
<h3>您中意的女神是谁</h3>
<!--单选框传值 -->
<select name="lady" id="">
<option value="bing">范冰冰</option>
<option value="mi">杨幂</option>
<option value="yun">林允儿</option>
<option value="xiu">郑秀妍</option>
</select>
<!--多选框传值 -->
<div>
<h3>您为什么喜欢她?</h3>
<input type="checkbox" name="reason" value="1">长相甜美
<input type="checkbox" name="reason" value="2">为了学习
<input type="checkbox" name="reason" value="3">魔鬼身材
<input type="checkbox" name="reason" value="4">其他
</div>
<div>
<h3>填写调差问卷有礼品相送,请填写您的地址和联系方式</h3>
<h4>地址:</h4>
+ <input type="text" name="emsInfo.address">
<h4>联系方式:</h4>
+ <input type="text" name="emsInfo.mobile">
</div>
<p><input type="submit" value="提交"></p>
</form>
四.SpringMVC中解决乱码问题
4.1 中文乱码原因
因为默认的字符集是
ISO-8859-1
,属于西欧字符集,只有数字,符号,英文,拉丁文…所以解决乱码的核心就是将
ISO-8859-1
转换为UTF-8
4.2 乱码分类
-
GET请求乱码
如果你的Tomcat的版本比较高(Tomcat8.0及以上),则不会出现GET请求乱码
如果
Tomcat
版本比较低,如果在不更换版本的前提下,避免GET请求中文乱码问题,则需要修改Tomcat配置文件在
tomcat
安装目录–conf
–server.xml
–Connector
添加URIEncoding="UTF-8"
-
POST请求乱码
通过设置
过滤器
解决中文乱码问题<!-- 编码过滤器--> <filter> <filter-name>character-filter</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>character-filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
/* :可以拦截所有包括带后缀的请求
/ : 可以拦截所有不带后缀的请求
-
响应乱码
绝大多数响应数据乱码,在SpringMVC中都加了
@ResponseBody
注解,而这个注解受StringHttpMessageConverter
转换器的影响<!-- 开启SpringMVC的注解开发模式--> <mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=utf-8</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
也可以单独配置HeadlerAdapter
,实际不推荐使用,只是为了理解
五.SpringMVC响应和数据模型
5.1 @ResponseBody
- 可以是标准的字符串,也可以是数据化结构(xml/
json
/ProtoBuf
)- 直接响应数据,不涉及到视图
- 会被
StringHttpMessageConverter
影响
5.2 数据模型
SpringMVC提供的数据模型,主要是为了解决
特定作用域内封装数据
的组件
前面由于
HTTP
的无状态性
,我们想去实现购物车保存数据的功能是很难的,所以之前学习的Servlet为我们提供了3种作用域:
- 请求作用域:
HttpServletRequest
组件中存储的数据,可以在一次请求的生命周期存在- 会话作用域:
HttpSession
组件中存储的数据,可以在一次会话的生命周期存在- 应用程序:
ServletContext
组件保存的数据可以在整个应用程序生命周期内存在
ps: 无状态性-指的是每一次请求都是独立的没有关系的
在SpringMVC中提供的数据模型的组件:
- Model
- ModelMap
- ModelAndView
本质其实就是对
HttpServletRequest
对象中的存储数据的Map集合做的引用
原生HttpServletRequest绑定数据
@RequestMapping("/getcomplexdata")
public String getComplexData(Form form, HttpServletRequest request) {
request.setAttribute("username", "地雷");
System.out.println(form);
return "/success.jsp";
}
1. Model
/**
* 默认是请求作用域,只对数据做存储
*/
@RequestMapping("/getcomplexdata")
public String getComplexData(Form form, Model model) {
model.addAttribute("username", "地雷2");
System.out.println(form);
return "/success.jsp";
}
2.ModelMap
/**
* 默认是请求作用域,只对数据做存储
*/
@RequestMapping("/getcomplexdata")
public String getComplexData(Form form, ModelMap model) {
model.addAttribute("username", "地雷2");
System.out.println(form);
return "/success.jsp";
}
ModelAndView
@RequestMapping("/getcomplexdata")
public ModelAndView getComplexData(Form form, ModelMap model) {
model.addAttribute("username", "地雷2");
System.out.println(form);
ModelAndView modelAndView = new ModelAndView("/success.jsp");
// 设置响应地址
//modelAndView.setViewName("/success.jsp");
// 设置绑定数据
modelAndView.addObject("username","地雷么么哒");
return modelAndView;
}
默认都是转发,如果需要重定向那么就需要添加前缀
redirect:success.jsp
/转发就是forword
@RequestMapping("/getcomplexdata")
public ModelAndView getComplexData(Form form, ModelMap model) {
model.addAttribute("username", "地雷2");
System.out.println(form);
ModelAndView modelAndView = new ModelAndView("redirect/success.jsp");
// 设置响应地址
//modelAndView.setViewName("/success.jsp");
// 设置绑定数据
modelAndView.addObject("username","地雷么么哒");
return modelAndView;
}
public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered {
// 重定向前缀
public static final String REDIRECT_URL_PREFIX = "redirect:";
// 转发前缀(默认)
public static final String FORWARD_URL_PREFIX = "forward:";
5.3 作用域
默认情况下,
Model
,ModelMap
,ModelAndView
数据模型组件,其保存的元素都是在请求作用域
中如果想提升数据的作用域,在SpringMVC中可以使用
@SessionAttributes
@Controller
@RequestMapping("/mav")
@SessionAttributes("username")
public class ModelAndViewController {
5.4 SpringMVC整合模板引擎
- 对默认的视图解析器进行优化
<!-- 显示的配置视图解析器 必须叫:viewResolver-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置视图名字的前缀:一般设置为存放模板引擎文件的公共目录-->
<property name="prefix" value="/WEB/INF/jsp/"/>
<!-- 配置视图名字的后缀,一般是模板引擎的格式-->
<property name="suffix" value=".jsp"/>
<!-- 响应类型 避免中文乱码-->
<property name="contentType" value="text/html;charset=utf-8"/>
</bean>
/**
* 默认是请求作用域,只对数据做存储
*/
@RequestMapping("/getcomplexdata")
public String getComplexData(Form form, ModelMap model) {
model.addAttribute("username", "地雷2");
System.out.println(form);
return "success";
// 如果不需要使用前后缀的配置
+ return "forword:/success.jsp"
}
整合freemarker
-
引入依赖
<!-- freemarker --> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.28</version> </dependency> <!-- spring-context-support 不仅仅可以帮Spring整合第三方模板引擎,当Spring整合缓存,定时任务的时候也需要它--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring-version}</version> </dependency>
-
配置freemarker视图解析器
FreeMarkerViewResolver
<!-- 配置freemarker--> <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver" id="viewResolver"> <!-- 配置视图名字的后缀--> <property name="suffix" value=".ftl"/> </bean> <!-- freemarker配置--> <bean id="configurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <!-- 这里配置了模板引擎放置的位置,就不需要配置视图解析器的前缀了--> <property name="templateLoaderPath" value="/WEB-INF/ftl/"/> <!-- 设置编码--> <property name="defaultEncoding" value="UTF-8"/> </bean>
-
FreeMarkerController
@GetMapping("/first") public ModelAndView test() { ModelAndView modelAndView = new ModelAndView("first"); modelAndView.addObject("username", "地雷"); return modelAndView; }
-
first.ftl
<body> <h1 align="center">用户名:${username}</h1> </body>
六.Resuful开发风格
6.1 简介
REST
(REpresentional State Transfer)
表现层状态转换–>所有的资源都是通过URL来识别和定位的,对资源的操作(CRUD)是通过HTTP的方法来定义
6.2 Restful开发风格
基于REST理念的一种开发风格,最典型的例子就是
前后端分离
在Restful
开发风格里面:
- 使用URL来定位用户的入口,代表对资源文件具体的操作
HTTP方法要明确
,(GET,POST,PUT,DELETE)- 接口只返回数据(一般指的结构化数据)
- 在URL中不能出现动词 (!
/getCourses
)
URI | 说明 |
---|---|
GET/courses | 查询所有的课程信息 |
GET/course/1(@PathVariable) | 查询id为1的课程信息 |
POST /course | 新增课程 |
PUT/PATCH/course/1 | 修改id为1的课程信息 |
DELETE/course/1 | 删除id为1的课程信息 |
案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="static/js/jquery-3.6.0.min.js"></script>
<script>
$(function () {
$('#do-get').click(function () {
$.ajax({
url: "rest/request",
type: "GET",
//前端希望后端返回的数据类型为json
dataType: "json",
// contentType:发送请求的数据类型
// 回调函数拿到后端返回的数据
success: function (res) {
console.log(res)
}
})
});
$('#do-Post').click(function () {
$.ajax({
url: "rest/request",
type: "POST",
// 如果需要加参数,那么就使用data
//data:"username='木子'&age=18",
//前端希望后端返回的数据类型为json
dataType: "json",
// contentType:发送请求的数据类型
// 回调函数拿到后端返回的数据
success: function (res) {
console.log(res)
for (let i = 0; i < res.length; i++) {
let stu = res[i];
// 返回数据显示到页面中
$('#rest-response').append("学生信息:"+stu.id+"学生姓名"+stu.name);
}
}
})
});
$('#do-Put').click(function () {
$.ajax({
url: "rest/request",
type: "Put",
//前端希望后端返回的数据类型为json
dataType: "json",
data:"username='木子'",
// contentType:发送请求的数据类型
// 回调函数拿到后端返回的数据
success: function (res) {
console.log(res)
}
})
});
$('#do-Delete').click(function () {
$.ajax({
url: "rest/request",
type: "Delete",
//前端希望后端返回的数据类型为json
dataType: "json",
// contentType:发送请求的数据类型
// 回调函数拿到后端返回的数据
success: function (res) {
console.log(res)
}
})
});
})
</script>
</head>
<body>
<input type="button" value="RESTFUL-Get" id="do-get">
<input type="button" value="RESTFUL-Post" id="do-Post">
<input type="button" value="RESTFUL-Put" id="do-Put">
<input type="button" value="RESTFUL-Delete" id="do-Delete">
<p id="rest-response"></p>
</body>
</html>
@PutMapping("/request")
public String putRequest(){
return "Put成功";
}
@DeleteMapping("/request")
public String deleteRequest(){
return "Delete成功";
}
<!-- 开启MVC注解开发模式-->
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=utf-8</value>
<value>application/json;charset=utf-8</value>
<!-- 返回JSON可能乱码,所以加上配置-->
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
6.3 简单请求和非简单请求
如果让页面发送
PUT/DELETE
请求,携带参数的话,SpringMVC的接口拿不到请求中的数据
$('#do-Put').click(function () {
$.ajax({
url: "rest/request",
type: "Put",
//前端希望后端返回的数据类型为json
dataType: "json",
data:"username='木子'",
// contentType:发送请求的数据类型
// 回调函数拿到后端返回的数据
success: function (res) {
console.log(res)
}
})
});
但是
GET/POST
没有这种问题SpringMVC在设计之初,只是为了解决表达数据的解析,而表单只支持
GET/POST
因为
Restful
的流行,以及客户端的多样性,SpringMVC
通过加入过滤器来解决的从Spring5.1开始加入
FormContentFilter
来解析PUT/DELETE/PATCH
请求参数中的问题
<!-- 响应表单解析过滤器-->
<filter>
<filter-name>formContent</filter-name>
<filter-class>org.springframework.web.filter.FormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>formContent</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
老版本里面也是通过过滤器,但是是
HiddenHttpMethodFilter
简单请求和非简单请求区别
- 简单请求是标准结构的HTTP请求
- 非简单请求时相对复杂的请求,其实是对简单请求的扩展
- 非简单请求在正式调用接口之前会调用一次
预检请求
七.跨域问题
7.1 同源策略
是浏览器自带的安全策略,用来阻止从一个域加载另外一个域的资源
js,css
图片不会触发同源策略— 如果需要触发可以使用防盗链
7.2 什么叫不同的域
协议|域名|端口 三者必须完全一致,才叫同一个域,只要有一个不同就叫做不同的域此时相互之间做资源的调用就会触发同源策略
7.3 解决跨域问题
在后端主流的是
CORS
(Cross-origin resource sharing) 跨域资源共享还有一种
JSONP
也可以解决,但是有一个限制,只支持GET请求跨域资源访问
-
全局解决方案
path: 允许跨域访问的资源路径 allowed-origins:允许跨域访问指定path的域的列表,默认为*,代表所有域 allowed-methods:允许跨域访问指定path的HTTP方法的列表,默认为*,代表所有方法 max-age: 预检请求结果的缓存时间,单位为秒,默认为1800(半小时)
<mvc:cors> <mvc:mapping path="/rest/*" allowed-origins="*" allowed-methods="" max-age="3600"/> </mvc:cors>
-
局部注解解决
@CrossOrigin(origin = {"http://localhost:8080"},method= {RequestMethod.GET,RequestMethod.POST})
如果使用注解,
@CrossOrigin
可以放到类上,也可以放到方法上,都放采取就近原则
八…拦截器Interceptor
在
Servlet
阶段接触过过滤器
,他和拦截器作用是一样的,但是底层实现不一样
拦截器:
Interceptor
,他是Spring
框架的一部分,天然运行在IOC容器中,底层是基于代理模式
,也是AOP的一个具体实现
过滤器;是j2ee的标准,由不同的第三方容器厂商实现的,过滤器属于容器,基于
函数回调机制
MyInterceptor
/**
* @author : Jack_Zhou
* 自定义拦截器
*/
public class MyInterceptor implements HandlerInterceptor {
/**
* 前置处理
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(request.getRequestURL()+"这个URL在preHandle被拦截了");
return HandlerInterceptor.super.preHandle(request, response, handler);
}
/**
* 目标资源已经被SpringMVC处理之后(Controller里面的方法return之后)
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println(request.getRequestURL()+"这个URL在postHandle被拦截了");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
/**
* 产生响应文本之后(数据和模板引擎绑定了之后,数据被json序列化了之后 )
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println(request.getRequestURL()+"这个URL在afterCompletion被拦截了");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
<!-- 拦截器配置-->
<mvc:interceptors>
<!-- 配置单个拦截器的作用 -->
<mvc:interceptor>
<!--所有的栏 -->
<mvc:mapping path="/**"/>
<!--对那些资源不进行拦截 -->
<mvc:exclude-mapping path="/**.js"/>
<mvc:exclude-mapping path="/**.css"/>
<mvc:exclude-mapping path="/**.ico"/>
<!--对static文件夹下面所有资源不拦截-->
<mvc:exclude-mapping path="/static/**"/>
<bean class="pers.zhou.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>