一、访问静态资源
在进行Spring MVC的配置时,通常我们会配置一个dispatcher servlet用于处理对应的URL
在设置url-pattern时可以设置三种形式
(1)/* :拦截所有 jsp js png .css 真的全拦截。不建议使用。
(2)/ :拦截所有,不包括jsp,包含.js .png.css 建议使用。
(3).action .do :拦截以do action 结尾的请求。
<!-- 配置SpringMVC前端控制器 -->
<servlet>
<servlet-name>mySpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定SpringMVC配置文件 -->
<!-- SpringMVC的配置文件的默认路径是/WEB-INF/${servlet-name}-servlet.xml -->
<init-param>
<!-- DispatcherServlet类的初始化参数 -->
<param-name>contextConfigLocation</param-name>
<!-- 初始化参数的值,即springmvc配置文件的路径 -->
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 表示web应用启动即加载该servlet -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mySpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
知识兔url-pattern为 / 时,访问静态资源,会被拦截,找不到静态资源
解决方法:
(1)在springmvc.xml中配置
<mvc:default-servlet-handler/>
知识兔自动的根据访问地址看下是不是静态资源,如果是直接放行,如果不是就去找 @RequestMapping
(2)在springmvc.xml中配置 mvc:resources (推荐使用)
<mvc:resources location="/img/" mapping="/img/**"/>
<mvc:resources location="/js/" mapping="/js/**"/>
<mvc:resources location="/css/" mapping="/css/**"/>
知识兔描述:
- location元素表示webapp目录下的static包下的所有文件;
- mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b;
- 该配置的作用是:DispatcherServlet不会拦截以/static开头的所有请求路径,并当作静态资源交由Servlet处理。
二、Json处理
概述
当前端使用Ajax发送请求时,服务器要以JSON的数据格式响应给浏览器。
使用方式
@ResponseBody来实现;注解方式
@ResponseBody
(1)添加 json处理 相关jar包
+ jackson 2.9.9
- jackson-annotations-2.9.9.jar
- jackson-core-2.9.9.jar
- jackson-databind-2.9.9.jar
知识兔(2)在springmvc.xml配置文件当中写上
<mvc:annotation-driven/>
知识兔(3)设置映射方法的返回值为@ResponseBody
请求发送页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
</head>
<body>
<input type="button" value="请求JSON" id="btn">
<script>
$(function () {
$('#btn').click(function () {
// 发送Ajax 请求
$.post("${pageContext.request.contextPath}/getJson",function (data) {
console.log(data);
})
});
});
</script>
</body>
</html>
知识兔方式1-直接返回一个对象
@Controller
public class MyController {
@RequestMapping("getJson")
@ResponseBody
public User show(){
User user = new User();
user.setUsername("user2");
user.setPassword("159357");
user.setAge(20);
user.setHobby(new String[]{"篮球","足球"});
return user;
}
}
知识兔方式2-返回一个List集合
@Controller
public class MyController {
@RequestMapping("getJson")
@ResponseBody
public ArrayList<User> show(){
User user1 = new User();
user1.setUsername("user2");
user1.setPassword("159357");
user1.setAge(20);
user1.setHobby(new String[]{"篮球","足球"});
User user2 = new User();
user2.setUsername("user1");
user2.setPassword("123456");
user2.setAge(18);
user2.setHobby(new String[]{"篮球","足球"});
ArrayList<User> users = new ArrayList<>();
users.add(user1);
users.add(user2);
return users;
}
}
知识兔方式3-返回一个Map集合
@Controller
public class MyController {
@RequestMapping("getJson")
@ResponseBody
public HashMap<String, Object> show(){
User user1 = new User();
user1.setUsername("user2");
user1.setPassword("159357");
user1.setAge(20);
user1.setHobby(new String[]{"篮球","足球"});
User user2 = new User();
user2.setUsername("user1");
user2.setPassword("123456");
user2.setAge(18);
user2.setHobby(new String[]{"篮球","足球"});
ArrayList<User> users = new ArrayList<>();
users.add(user1);
users.add(user2);
HashMap<String, Object> map = new HashMap<>();
map.put("name", "hashmap");
map.put("list", users);
return map;
}
}
知识兔表单序列化
serialize()
知识兔请求发送页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
</head>
<body>
<form id="myform">
<p>用户Id :<input type="text" name="id"></p>
<p>用户名 :<input type="text" name="username"></p>
<p>密码 :<input type="text" name="password"></p>
<p>性别 :
<input type="radio" name="sex" value="男">男
<input type="radio" name="sex" value="女">女
</p>
<p>年龄 :<input type="text" name="age"></p>
<p>爱好 :
<input type="checkbox" name="like" value="篮球">篮球
<input type="checkbox" name="like" value="足球">足球
<input type="checkbox" name="like" value="排球">排球
<input type="checkbox" name="like" value="乒乓球">乒乓球
</p>
</form>
<input type="button" value="发送form" id="btn">
<script>
$(function () {
$('#btn').click(function () {
// 获取表单所有参数,发送给服务器
var serialize = $('#myform').serialize();
console.log(serialize);
// output: 参数=值&参数=值&参数=值
});
});
</script>
</body>
</html>
知识兔我们希望获取的是json格式的数据:
序列化转Json
(function($){
$.fn.serializeJson=function(){
var serializeObj={};
var array=this.serializeArray();
var str=this.serialize();
$(array).each(function(){
if(serializeObj[this.name]){
if($.isArray(serializeObj[this.name])){
serializeObj[this.name].push(this.value);
}else{
serializeObj[this.name]=[serializeObj[this.name],this.value];
}
}else{
serializeObj[this.name]=this.value;
}
});
return serializeObj;
};
})(jQuery);
知识兔请求发送页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
</head>
<body>
<form id="myform">
<p>用户Id :<input type="text" name="id"></p>
<p>用户名 :<input type="text" name="username"></p>
<p>密码 :<input type="text" name="password"></p>
<p>性别 :
<input type="radio" name="gender" value="男">男
<input type="radio" name="gender" value="女">女
</p>
<p>年龄 :<input type="text" name="age"></p>
<p>爱好 :
<input type="checkbox" name="hobby" value="篮球">篮球
<input type="checkbox" name="hobby" value="足球">足球
<input type="checkbox" name="hobby" value="排球">排球
<input type="checkbox" name="hobby" value="乒乓球">乒乓球
</p>
</form>
<input type="button" value="发送form" id="btn">
<script>
(function($){
$.fn.serializeJson=function(){
var serializeObj={};
var array=this.serializeArray();
var str=this.serialize();
$(array).each(function(){
if(serializeObj[this.name]){
if($.isArray(serializeObj[this.name])){
serializeObj[this.name].push(this.value);
}else{
serializeObj[this.name]=[serializeObj[this.name],this.value];
}
}else{
serializeObj[this.name]=this.value;
}
});
return serializeObj;
};
})(jQuery);
$(function () {
$('#btn').click(function () {
// 获取表单所有参数,发送给服务器
var serialize = $('#myform').serializeJson();
console.log(serialize);
});
});
</script>
</body>
</html>
知识兔这时候的 serialize 就是以json格式的数据,我们再把数据发送给服务器
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
</head>
<body>
<form id="myform">
<p>用户Id :<input type="text" name="id"></p>
<p>用户名 :<input type="text" name="username"></p>
<p>密码 :<input type="text" name="password"></p>
<p>性别 :
<input type="radio" name="gender" value="男">男
<input type="radio" name="gender" value="女">女
</p>
<p>年龄 :<input type="text" name="age"></p>
<p>爱好 :
<input type="checkbox" name="hobby" value="篮球">篮球
<input type="checkbox" name="hobby" value="足球">足球
<input type="checkbox" name="hobby" value="排球">排球
<input type="checkbox" name="hobby" value="乒乓球">乒乓球
</p>
</form>
<input type="button" value="发送form" id="btn">
<script>
(function($){
$.fn.serializeJson=function(){
var serializeObj={};
var array=this.serializeArray();
var str=this.serialize();
$(array).each(function(){
if(serializeObj[this.name]){
if($.isArray(serializeObj[this.name])){
serializeObj[this.name].push(this.value);
}else{
serializeObj[this.name]=[serializeObj[this.name],this.value];
}
}else{
serializeObj[this.name]=this.value;
}
});
return serializeObj;
};
})(jQuery);
$(function () {
$('#btn').click(function () {
// 获取表单所有参数,发送给服务器
var serialize = $('#myform').serializeJson();
console.log(serialize);
$.post("${pageContext.request.contextPath}/formJson",serialize,function (data) {
console.log(data);
})
});
});
</script>
</body>
</html>
知识兔Controller
@Controller
public class MyController {
@RequestMapping("formJson")
@ResponseBody
public String show(User user){
System.out.println(user);
return "success";
}
}
知识兔发现问题
运行后会发现,当爱好选一个的时候可以正常运行,当选择大等于两个的时候,会报错。
当传递复杂类型的时候,服务器不能接收。
这是因为,默认情况下,在发送请求的时候 Content-Type 都是 application/x-www-form-urlencoded; 直接使用@RequestParam接收参数。 urlencoded 只能发送简单的 key-value 字符串类型。
@RequestBody
默认情况下我们发送的都是 Content-Type: application/x-www-form-urlencoded,直接使用@RequestParam接收参数。
如果不是Content-Type: application/x-www-form-urlencoded 编码的内容,例如application/json, application/xml等;使用@RequestBody接收。
解决方法
在发送的时候以 json 的形式发送,接受的时候以 json 的形式接收。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
</head>
<body>
<form id="myform">
<p>用户Id :<input type="text" name="id"></p>
<p>用户名 :<input type="text" name="username"></p>
<p>密码 :<input type="text" name="password"></p>
<p>性别 :
<input type="radio" name="gender" value="男">男
<input type="radio" name="gender" value="女">女
</p>
<p>年龄 :<input type="text" name="age"></p>
<p>爱好 :
<input type="checkbox" name="hobby" value="篮球">篮球
<input type="checkbox" name="hobby" value="足球">足球
<input type="checkbox" name="hobby" value="排球">排球
<input type="checkbox" name="hobby" value="乒乓球">乒乓球
</p>
</form>
<input type="button" value="发送form" id="btn">
<script>
(function($){
$.fn.serializeJson=function(){
var serializeObj={};
var array=this.serializeArray();
var str=this.serialize();
$(array).each(function(){
if(serializeObj[this.name]){
if($.isArray(serializeObj[this.name])){
serializeObj[this.name].push(this.value);
}else{
serializeObj[this.name]=[serializeObj[this.name],this.value];
}
}else{
serializeObj[this.name]=this.value;
}
});
return serializeObj;
};
})(jQuery);
$(function () {
$('#btn').click(function () {
// 获取表单所有参数,发送给服务器
var serialize = $('#myform').serializeJson();
console.log(serialize);
$.ajax({
type:"post",
url:"${pageContext.request.contextPath}/formJson",
data:JSON.stringify(serialize),
dataType:'json',
contentType:'application/json',
success:function (data) {
console.log(data);
}
});
});
});
</script>
</body>
</html>
知识兔Controller
@Controller
public class MyController {
@RequestMapping("formJson")
@ResponseBody
public String show(@RequestBody User user){
System.out.println(user);
return "success";
}
}
知识兔这样当爱好选择两个以上的时候就可以接收复杂类型的数据。
现在还有一个小问题:当爱好选择一个时,服务器接收不了。
原因是 当选择一个时,json串中hobby的数据为String类型,而hobby需要数组类型,Content-Type:application/x-www-form-urlencoded; 会自动帮我们解析,而 application/json 不会。所以我们要自己解析。
解决方法:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
</head>
<body>
<form id="myform">
<p>用户Id :<input type="text" name="id"></p>
<p>用户名 :<input type="text" name="username"></p>
<p>密码 :<input type="text" name="password"></p>
<p>性别 :
<input type="radio" name="gender" value="男">男
<input type="radio" name="gender" value="女">女
</p>
<p>年龄 :<input type="text" name="age"></p>
<p>爱好 :
<input type="checkbox" name="hobby" value="篮球">篮球
<input type="checkbox" name="hobby" value="足球">足球
<input type="checkbox" name="hobby" value="排球">排球
<input type="checkbox" name="hobby" value="乒乓球">乒乓球
</p>
</form>
<input type="button" value="发送form" id="btn">
<script>
(function($){
$.fn.serializeJson=function(){
var serializeObj={};
var array=this.serializeArray();
var str=this.serialize();
$(array).each(function(){
if(serializeObj[this.name]){
if($.isArray(serializeObj[this.name])){
serializeObj[this.name].push(this.value);
}else{
serializeObj[this.name]=[serializeObj[this.name],this.value];
}
}else{
serializeObj[this.name]=this.value;
}
});
return serializeObj;
};
})(jQuery);
$(function () {
$('#btn').click(function () {
// 获取表单所有参数,发送给服务器
var serialize = $('#myform').serializeJson();
console.log(serialize);
// 解析
if (typeof serialize.hobby == "string") {
serialize.hobby = new Array(serialize.hobby);
}
$.ajax({
type:"post",
url:"${pageContext.request.contextPath}/formJson",
data:JSON.stringify(serialize),
dataType:'json',
contentType:'application/json',
success:function (data) {
// alert(data.responseText)
console.log(data);
}
});
});
});
</script>
</body>
</html>
知识兔@RequestBody 获取文件信息
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
</head>
<body>
<form action="${pageContext.request.contextPath}/myfile" method="post" enctype="multipart/form-data">
<input type="file" name="myfile">
<input type="submit" value="提交">
</form>
</body>
</html>
知识兔Controller
@RequestMapping("myfile")
@ResponseBody
public String file(@RequestBody String file){
System.out.println(file);
return "success";
}
知识兔三、视图解析器
视图解析器
请求处理方法执行完成后,最终返回一个 ModelAndView 对象
对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个 ModelAndView 对象。
它包含了逻辑名和模型对象的视图,Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是 JSP 。
视图
视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户,视图对象由视图解析器负责实例化
在org.springframework.web.servlet 包中定义了一个高度抽象的 View 接口
常见实现类:InternalResourceView,将JSP或其它资源封装成一个视图,是InternalResourceViewResoler默认使用的实现类。
源码分析
执行DispatcherServlet
(1)获取mapping映射
(2)获取适配器
(3)调用处理器,执行映射方法,返回MV
(4)处理转发页面
(5)在方法内部渲染页面
(6)创建视图对象
(7)调用View对象渲染页面
(8)在render内部解析数据
(9)转发到jsp页面