一、@RequestMapping 定义请求规则
1. 指定模块名称
通过@RequestMapping 注解可以定义处理器对于请求的映射规则
该注解可以注解在方法上,也可以注解在类上,但意义是不同的
value 属性值常以“/”开始
一个@Controller 所注解的类中,可以定义多个处理器方法。当然,不同的处理器方法所匹配的 URI 是不同的
这些不同的 URI 被指定在注解于方法之上的@RequestMapping 的value 属性中
但若这些请求具有相同的 URI 部分,则这些相同的 URI,可以被抽取到注解在类之上的@RequestMapping 的 value 属性中,此时的这个 URI 表示模块的名称
URI 的请求是相对于 Web 的根目录
下面的例子还是在第一个程序的上面进行改写
/**
*@RequestMapping:
* value:所有请求地址的公共部分,叫做模块名称
* 位置:放在类的上面
*/
@Controller
@RequestMapping(value = "/test")
public class MyController {
@RequestMapping(value = "/some.do")
public ModelAndView doSome(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","欢迎使用springmvc");
mv.addObject("fun","执行的是doSome方法");
mv.setViewName("show");
return mv;
}
@RequestMapping(value = "/other.do")
public ModelAndView doOther(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","执行的是doOther方法");
mv.setViewName("show");
return mv;
}
}
此时在index.jsp中
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>第一个springmvc项目</p>
<p> <a href="test/some.do">发起test/some.do的请求</a> </p>
<p> <a href="test/other.do">发起test/other.do的请求</a> </p>
</body>
</html>
也就是把请求这些请求中相同的部分添加到了类的上面,添加了@RequestMapping(value = "/test")
2. 对请求提交方式的定义
对于@RequestMapping,其有一个属性 method,用于对被注解方法所处理请求的提交方式进行限制,即只有满足该method属性指定的提交方式的请求,才会执行该被注解方法
Method 属性的取值为 RequestMethod 枚举常量。常用的为 RequestMethod.GET 与RequestMethod.POST,分别表示提交方式的匹配规则为 GET 与 POST 提交
只要指定了处理器方法匹配的请求提交方式为 POST,则相当于指定了请求发送的方式:要么使用表单请求,要么使用 AJAX 请求。其它请求方式被禁用
当然,若不指定 method 属性,则无论是 GET 还是 POST 提交方式,均可匹配。即对于请求的提交方式无要求
例子如下:
@Controller
@RequestMapping(value = "/test")
public class MyController {
/**
*@RequestMapping:请求映射
* 属性:method:请求的方式,它的值是RequestMethod类枚举值
*/
@RequestMapping(value = "/some.do",method = RequestMethod.GET)
public ModelAndView doSome(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","执行的是doSome方法");
mv.setViewName("show");
return mv;
}
/**
*
* 获取到请求参数
*/
@RequestMapping(value = "/other.do",method = RequestMethod.POST)
public ModelAndView doOther(HttpServletRequest request,HttpServletResponse response,HttpSession session){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","欢迎使用springmvc,获取请求的参数:"+request.getParameter("name"));
mv.addObject("fun","执行的是doOther方法");
mv.setViewName("show");
return mv;
}
}
在index.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>第一个springmvc项目</p>
<p> <a href="test/some.do">发起test/some.do的get请求</a> </p>
<form action="test/other.do" method="post">
name:<input type="text" name="name">
<input type="submit" value="post请求other.do">
</form>
</body>
</html>
二、处理器方法的参数
处理器方法可以包含以下四类参数,这些参数会在系统调用时由系统自动赋值,即程序员可在方法内直接使用
- HttpServletRequest
- HttpServletResponse
- HttpSession
- 请求中所携带的请求参数
1. 逐个参数
只要保证请求参数名与该请求处理方法的参数名相同即可
<h1>提交参数给Controller</h1>
<form action="test/receive.do" method="post">
姓名:<input type="text" name="name"><br>
年龄:<input type="text" name="age"><br>
<input type="submit">
</form>
然后修改处理器类
@Controller
@RequestMapping(value = "/test")
public class MyController {
/**
* 逐个接收请求参数:
* 要求: 处理器(控制器)方法的形参名和请求中参数名必须一致。
* 同名的请求参数赋值给同名的形参
*
* 框架接收请求参数
* 1. 使用request对象接收请求参数
* String strName = request.getParameter("name");
* String strAge = request.getParameter("age");
* 2. springmvc框架通过 DispatcherServlet 调用 MyController的doOther()方法
* 调用方法时,按名称对应,把接收的参数赋值给形参
* doOther(strName,Integer.valueOf(strAge))
* 框架会提供类型转换的功能,能把String转为 int ,long , float, double等类型。
*
* 400状态码是客户端错误, 表示提交请求参数过程中,发生了问题。
*/
@RequestMapping(value = "/receive.do")
public ModelAndView doOther(String name,Integer age){
// 可以直接使用name和age
ModelAndView mv = new ModelAndView();
// 获取到表单中的数据
mv.addObject("myname",name);
mv.addObject("myage",age);
mv.setViewName("show");
return mv;
}
}
此时在show页面就可以的到数据了
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>show.jsp</h1>
这些都是从request作用域获取到的数据
<h2>姓名:${myname}</h2>
<h2>年龄: ${myage}</h2>
</body>
</html>
2. 校正请求参数名@RequestParam
请求中参数名和处理器方法的形参名不一样
在index.jsp页面
<p>请求参数名和处理器方法的形参名不一致</p>
<form action="test/receiveparam.do" method="post">
姓名:<input type="text" name="username"><br>
年龄:<input type="text" name="rage"><br>
<input type="submit">
</form>
主要就是处理器中方法的名字和请求参数的名字不一样,这个时候需要添加注解
/**
*请求中参数名和处理器方法的形参名不一样
* @RequestParam:逐个解决请求中参数名和形参名不一致的问题
* 属性:
* 1. value,请求中参数的名称
* 2. required 是一个boolean,默认是true
* true表示请求中必须包含此参数
* 作为:在处理器方法的形参前面定义
*/
@RequestMapping(value = "/receiveparam.do")
public ModelAndView receiveParam(@RequestParam(value = "username") String name,@RequestParam(value = "rage") Integer age){
ModelAndView mv = new ModelAndView();
// 获取到表单中的数据
mv.addObject("myname",age);
mv.setViewName("show");
return mv;
}
这样就可以在show页面接收到数据了
3. 请求参数中文乱码问题
对于前面所接收的post请求,若含有中文,则会出现中文乱码问题
Spring 对于请求参数中的中文乱码问题,给出了专门的字符集过滤器,解决方法:
注意:最好将该过滤器注册在其它过滤器之前。因为过滤器的执行是按照其注册顺序进行的
<?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>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!--声明过滤器,解决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>
<!--强制请求对象(HttpServletRequest)使用encoding编码-->
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<!--强制请求对象(HttpServletResponse)使用encoding编码-->
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<!--
/* : 所有的请求都会先通过这个过滤器
-->
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--这个过滤器基本上每个项目都有使用,直接用即可-->
</web-app>
4. 对象参数接收
1. 定义一个Student类
package com.md.vo;
/**
* @author MD
* @create 2020-08-12 15:33
*/
// 用于保存请求的参数的
public class Student {
// 属性名和请求参数名一样
private String name;
private Integer age;
public Student() {
}
public Student(String name,Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
",age=" + age +
'}';
}
}
2. 在index.jsp中
<p>使用java对象来接收请求参数</p>
<form action="test/receiveobject.do" method="post">
姓名:<input type="text" name="name"><br>
年龄:<input type="text" name="age"><br>
<input type="submit">
</form>
3. 在处理器类
package com.md.controller;
@Controller
@RequestMapping(value = "/test")
public class MyController {
/**
* 处理器方法形参是java对象,这个对象的属性名和请求中参数名一样
* 框架会创建形参的java对象,给属性赋值,请求中的参数是name,框架会调用setName()
*
*/
@RequestMapping(value = "/receiveobject.do")
public ModelAndView receiveObject(Student student){
ModelAndView mv = new ModelAndView();
// 获取到表单中的数据
mv.addObject("myname",student.getName());
mv.addObject("myage",student.getAge());
mv.setViewName("show");
return mv;
}
}
此时show页面也是可以接收到数据的
三、处理器方法的返回值
使用@Controller 注解的处理器的处理器方法,其返回值常用的有四种类型:
- 第一种:ModelAndView
- 第二种:String
- 第三种:无返回值 void
- 第四种:返回自定义类型对象
1. 返回 ModelAndView
若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据,此时处理器方法返回 ModelAndView 比较好。当然,若要返回 ModelAndView,则处理器方法中需要定义 ModelAndView 对象。
在使用时,若该处理器方法只是进行跳转而不传递数据,或只是传递数据而并不向任何资源跳转(如对页面的 Ajax 异步响应),此时若返回 ModelAndView,则将总是有一部分多余:要么 Model 多余,要么 View 多余。即此时返回 ModelAndView 将不合适
之前的例子中一直用的就是这个
2. 返回 String
处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器解析可以将其转换为物理视图地址
例如:
在index.jsp页面中
<h1>处理器方法返回String表示视图名称</h1>
<form action="return-view.do" method="post">
姓名:<input type="text" name="name"><br>
年龄:<input type="text" name="age"><br>
<input type="submit">
</form>
在springmvc.xml中配置视图解析器
<!--声明springmvc框架中的视图解析器,帮助开发人员设置视图文件路径-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀:视图文件的路径-->
<property name="prefix" value="/WEB-INF/view/" />
<!--后缀:视图文件的扩展名-->
<property name="suffix" value=".jsp"/>
</bean>
在处理器中,
@Controller
public class MyController {
/**
* 处理器方法返回String--表示逻辑视图名称,需要配置视图解析器
*/
@RequestMapping(value = "/return-view.do")
public String doReturnView(HttpServletRequest request,String name,Integer age){
System.out.println("doReturnView,name="+name+" "+"age="+age);
// 这个时候可以自己手动的添加数据到request作用域
request.setAttribute("myname",name);
request.setAttribute("myage",age);
// show,是逻辑视图名称,项目中已经配置了视图解析器
// 在这里,框架对视图执行的是转发操作
return "show";
}
}
由于配置了视图解析器,此时返回字符串show,这个字符串与视图解析器中的 prefix、suffix 相结合,即可形成要访问的 URI
当然,也可以直接返回资源的物理视图名。不过,此时就不需要再在视图解析器中再配置前辍与后辍了
// 处理器方法返回的String,表示完整的视图路径,
// 此时不能配置视图解析器
@RequestMapping(value = "/return-view2.do")
public String doReturnView2(HttpServletRequest request,Integer age){
System.out.println("---------doReturnView2---------,是逻辑视图名称,项目中已经配置了视图解析器
// 在这里,框架对视图执行的是转发操作
return "/WEB-INF/view/show.jsp";
}
四、返回对象Object
处理器方法也可以返回 Object 对象。这个 Object 可以是 Integer,String,自定义对象,Map,List 等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的
返回对象,需要使用@ResponseBody 注解,将转换后的 JSON 数据放入到响应体中
1. 环境搭建
由于返回 Object 数据,一般都是将数据转化为了 JSON 对象后传递给浏览器页面的。而这个由 Object 转换为 JSON,是由 Jackson 工具完成的。所以需要导入 Jackson 的相关 Jar 包
1. 在pom.xml中
<!--jackson依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
2. 声明注解驱动
将 Object 数据转化为 JSON 数据,需要由消息转换器 HttpMessageConverter 完成。而转换器的开启,需要由<mvc:annotation-driven/>来完成。
SpringMVC 使用消息转换器实现请求数据和对象,处理器方法返回对象和响应输出之间的自动转换
在springmvc.xml中添加
<!-- 加入注解驱动 -->
<!--注意:找到结尾为mvc的driven-->
<mvc:annotation-driven />
2. 返回自定义类型对象
返回自定义类型对象时,不能以对象的形式直接返回给客户端浏览器,而是将对象转换为 JSON 格式的数据发送给浏览器的
由于转换器底层使用了Jackson转换方式将对象转换为JSON数据,所以需要导入Jackson的相关 Jar 包
1. 定义数据类
package com.md.vo;
public class Student {
// 属性名和请求参数名一样
private String name;
private Integer age;
public Student() {
}
public Student(String name,Integer age) {
this.name = name;
this.age = age;
}
// set和get方法,
}
修改处理器
重点看注释
package com.md.controller;
@Controller
public class MyController {
/**
* 处理器方法返回一个Student,通过框架转为json,响应ajax请求
* @ResponseBody
* 作用:把处理器方法返回对象转为json后,通过HttpServletResponse输出给浏览器
* 位置:方法定义的上面
* 返回对象框架的处理流程:
* 1. 框架会把返回Student类型,调用框架的中ArrayList<HttpMessageConverter>中每个类的canWrite()方法
* 检查那个HttpMessageConverter接口的实现类能处理Student类型的数据--MappingJackson2HttpMessageConverter
*
* 2.框架会调用实现类的write(), MappingJackson2HttpMessageConverter的write()方法
* 把林动的student对象转为json, 调用Jackson的ObjectMapper实现转为json
* contentType: application/json;charset=utf-8
*
* 3.框架会调用@ResponseBody把2的结果数据输出到浏览器, ajax请求处理完成
*/
@RequestMapping(value = "/returnStudentJson.do")
@ResponseBody
public Student doStudentJson(String name,Integer age){
// 调用service , 获取请求结果数据,Student对象表示结果数据
Student student = new Student("林动",20);
// 会被框架转为json
return student;
}
}
在index.jsp页面
首先把jQuery导入进来,在webapp下建立js目录,jQuery复制进来就行了
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function(){
$("button").click(function(){
$.ajax({
url:"returnStudentJson.do",data:{
name:"pony",age:20
},type:"post",dataType:"json",success:function(resp){
//resp从服务器端返回的是json格式的字符串 {"name":"林动","age":20}
//jquery会把字符串转为json对象, 赋值给resp形参。
alert(resp.name + " "+resp.age);
}
})
})
})
</script>
</head>
<body>
<button id="btn">发起Ajax请求</button>
</body>
</html>
3. 返回List集合
还是在上面的基础上,修改处理器MyController
package com.md.controller;
@Controller
public class MyController {
/**
* 处理器方法返回的是List<Student>
* 处理的方式和上面的一样,
*/
@RequestMapping(value = "/returnStudentJsonArray.do")
@ResponseBody
public List<Student> doStudentJsonArray(String name,Integer age){
List<Student> list = new ArrayList<>();
// 调用service , 获取请求结果数据,Student对象表示结果数据
Student student = new Student("林动",20);
Student student1 = new Student("唐三",20);
Student student2 = new Student("白昊天",10);
list.add(student);
list.add(student1);
list.add(student2);
// 会被框架转为json的数组
return list;
}
}
此时在index.jsp页面上
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function(){
$("button").click(function(){
$.ajax({
url:"returnStudentJsonArray.do",success:function(resp){
[{"name":"林动","age":20},{"name":"唐三",{"name":"白昊天","age":10}]
$.each(resp,function(i,n){
alert(n.name+" "+n.age)
})
}
})
})
})
</script>
</head>
<body>
<button id="btn">发起Ajax请求</button>
</body>
</html>
这样点击按钮就可以获取到数据了
3. 返回字符串对象
若要返回非中文字符串,将前面返回数值型数据的返回值直接修改为字符串即可。
但若返回的字符串中带有中文字符 ,则接收方页面将会出现乱码 。此时需要使用@RequestMapping 的 produces 属性指定字符集
还是修改处理器
package com.md.controller;
@Controller
public class MyController {
/**
* 处理器方法返回的是String , String表示数据的,不是视图。
* 区分返回值String是数据,还是视图,看有没有@ResponseBody注解
*
* 如果有@ResponseBody注解,返回String就是数据,反之就是视图
*
*
* 默认使用“text/plain;charset=ISO-8859-1”作为contentType,导致中文有乱码,
* 解决方案:给RequestMapping增加一个属性 produces,使用这个属性指定新的contentType.
*
*
* 返回对象框架的处理流程:
* 1. 框架会把返回String类型,调用框架的中ArtrayList<HtpMessageConverter>中每个类的canWrite()方法
* 检查那个HttpMessageConverter接口的实现类能处理String类型的数据--StringHttpMessageConverter
*
* 2.框架会调用实现类的write(), StringHttpMessageConverter的write()方法
* 把字符按照指定的编码处理 text/plain;charset=ISO-8859-1
*
* 3.框架会调用@ResponseBody把2的结果数据输出到浏览器, ajax请求处理完成
*/
// 返回的是字符串,直接输出ajax请求,并不走过滤器,必须加属性才能解决乱码问题
@RequestMapping(value = "/returnStringData.do",produces = "text/plain;charset=utf-8")
@ResponseBody
public String doStringData(String name,Integer age){
return "我是返回的数据";
}
}
在index.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function(){
$("button").click(function(){
$.ajax({
url:"returnStringData.do",// 返回文本数据
dataType:"text",success:function(resp){
alert("返回的是文本数据:"+resp);
}
})
})
})
</script>
</head>
<body>
<button id="btn">发起Ajax请求</button>
</body>
</html>
五、 解读url-pattern
1. *.do
在没有特殊要求的情况下,SpringMVC 的中央调度器 DispatcherServlet 的<url-pattern/>常使用后辍匹配方式,如写为*.do 或者 *.action,*.mvc
等
2. /
可以写为/,因为 DispatcherServlet 会将向静态资源的获取请求,例如.css、.js、.jpg、.png等资源的获取请求,当作是一个普通的 Controller 请求。中央调度器会调用处理器映射器为其查找相应的处理器,当然也是找不到的,
例如:
在index.jsp页面中存在一个访问图片的链接,演示将<url-pattern/>写为*.do可以访问到该图片,而写为/,则无法访问,还是在第一个例子中
1. 首先在Webapp下建立img目录,然后放一张图片
2. 然后在web.xml中
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--
使用框架时,url-pattern可以有两种值
1. 扩展名 *.xxx , xxx是扩展名,例如:*.do,*.action等
2. 使用 "/"
当你的项目中使用了 / ,它会替代Tomcat中的default
导致所有的静态资源都给DispatcherServlet处理,而默认情况下DispatcherServlet没有处理静态资源的能力
没有控制器对象能处理静态资源的访问,静态资源(html、js、img、css)都404
静态资源访问不成,但动态资源可以访问,因为我们的程序写了MyController控制器对象,能处理some.do
-->
<!--<url-pattern>*.do</url-pattern>-->
<url-pattern>/</url-pattern>
</servlet-mapping>
<img src="img/time.jpg" alt="我是静态资源">
3. 静态资源的访问
<url-pattern/>的值并不是说写为/后,静态资源就无法访问了。经过一些配置后,该问题也是可以解决的
1. 使用<mvc:default-servlet-handler/>
声 明 了 <mvc:default-servlet-handler /> 后 , springmvc 框 架 会 在 容 器 中 创 建
DefaultServletHttpRequestHandler 处理器对象。它会像一个检查员,对进入 DispatcherServlet的 URL 进行筛查,如果发现是静态资源的请求,就将该请求转由 Web 应用服务器默认的Servlet 处理。一般的服务器都有默认的 Servlet
在 Tomcat 中,有一个专门用于处理静态资源访问的 Servlet 名叫 DefaultServlet
所以,只需要在springmvc.xml中加入这个标签即可
<!-- default-servlet-handler 和 @RequestMapping注解 有冲突, 需要加入annotation-driven 解决问题-->
<mvc:annotation-driven />
<!--第一种处理静态资源的方式:
需要在springmvc配置文件加入 <mvc:default-servlet-handler>
原理是: 加入这个标签后,框架会创健控制器对象DefaultServletHttpRequestHandler(类似我们自己创建的MyController).
DefaultServletHttpRequestHandler这个对象可以把接收的请求转发给 tomcat的default这个servlet。
-->
<mvc:default-servlet-handler />
2. 使用<mvc:resources/>
在 Spring3.0 版本后,Spring 定义了专门用于处理静态资源访问请求的处理器ResourceHttpRequestHandler。并且添加了<mvc:resources/>标签,专门用于解决静态资源无法访问问题。需要在 springmvc 配置文件中添加如下形式的配置 :
<!--第二种处理静态资源的方式
mvc:resources 加入后框架会创建 ResourceHttpRequestHandler这个处理器对象。
让这个对象处理静态资源的访问,不依赖tomcat服务器。
mapping:访问静态资源的uri地址, 使用通配符 **
location:静态资源在你的项目中的目录位置,目录不要使用/WEB-INF/及其子目录
images/**:表示 images/time.jpg,images/user/logo.gif,images/order/history/list.png
-->
<mvc:resources mapping="/img/**" location="/img/" />
<mvc:resources mapping="/html/**" location="/html/" />
<mvc:resources mapping="/js/**" location="/js/" />
<!--mvc:resources和@RequestMapping有一定的冲突-->
<mvc:annotation-driven />
<!--通常在webapp目录下建立static目录,把使用的静态资源都放进来,这样一句话搞定-->
<!--使用一个配置语句,指定多种静态资源的访问-->
<!--<mvc:resources mapping="/static/**" location="/static/" />-->