Spring MVC 在数据绑定的过程中,需要对传递数据的格式和类型进行转换,它既可以转换 String 类型的数据,也能够转换 JSON 等其他类型的数据。 这里介绍 String 等数据类型的转换和绑定, Spring MVC 中 JSON 类型的数据交互和 RESTful 支持进行详细讲解。
一、返回值分类
1、返回字符串
(1)Controller方法返回字符串可以指定逻辑视图的名称,根据视图解析器为物理视图的地址。
@Controller
public class HelloSpringMVC {
@RequestMapping("/testPojo")
public String testPojo(User user){
System.out.println("testPojo:" + user);
//跳转到XXX页面
return SUCCESS;
}
}
(2)具体使用场景
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 请求参数的绑定
*/
@RequestMapping(value="/initUpdate")
public String initUpdate(Model model) {
// 模拟从数据库中查询的数据
User user = new User();
user.setUsername("张三");
user.setPassword("123");
user.setMoney(100d);
user.setBirthday(new Date());
model.addAttribute("user", user);
return "update";
}
}
<h3>修改用户</h3>
${ requestScope }
<form action="user/update" method="post">
姓名:<input type="text" name="username" value="${ user.username }"><br>
密码:<input type="text" name="password" value="${ user.password }"><br>
金额:<input type="text" name="money" value="${ user.money }"><br>
<input type="submit" value="提交">
</form>
2、返回值是void
- 如果控制器的方法返回值编写成void,执行程序报404的异常,默认查找JSP页面没有找到。
- 默认会跳转到@RequestMapping(value="/initUpdate") initUpdate的页面。
- 可以使用请求转发或者重定向跳转到指定的页面
@RequestMapping(value="/initAdd")
public void initAdd(HttpServletRequest request,HttpServletResponse response) throws Exception {
System.out.println("请求转发或者重定向");
// 请求转发
//request.getRequestDispatcher("/WEB-INF/pages/add.jsp").forward(request, response);
// 重定向
//response.sendRedirect(request.getContextPath()+"/add2.jsp");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8"); // 直接响应数据
response.getWriter().print("你好");
return;
}
3、返回值是ModelAndView对象
- ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图
- 具体的代码如下
/**
* 返回ModelAndView对象
* 可以传入视图的名称(即跳转的页面),还可以传入对象。
* @return
* @throws Exception
*/
@RequestMapping(value="/findAll")
public ModelAndView findAll() throws Exception {
ModelAndView mv = new ModelAndView();
// 跳转到list.jsp的页面
mv.setViewName("list");
// 模拟从数据库中查询所有的用户信息
List<User> users = new ArrayList<>();
User user1 = new User();
user1.setUsername("张三");
user1.setPassword("123");
User user2 = new User();
user2.setUsername("赵四");
user2.setPassword("456");
users.add(user1);
users.add(user2);
// 添加对象
mv.addObject("users", users);
return mv;
}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>查询所有的数据</h3>
<c:forEach items="${ users }" var="user">
${ user.username }
</c:forEach>
</body>
</html>
二、SpringMVC框架提供的转发和重定向
1、forward请求转发
(1) controller方法返回String类型,想进行请求转发也可以编写成
/**
* 使用forward关键字进行请求转发
* @return
* @throws Exception
*/
@RequestMapping("/delete")
public String delete() throws Exception {
System.out.println("delete方法执行了...");
return "forward:/user/findAll";
}
2、redirect重定向
/**
* 使用redirect关键字进行重定向
* @return
* @throws Exception
*/
@RequestMapping("/delete")
public String delete() throws Exception {
System.out.println("delete方法执行了...");
return "redirect:/user/findAll";
}
三、ResponseBody响应json数
1、DispatcherServlet拦截资源问题
DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置
- mvc:resources标签配置不过滤
- location元素表示webapp目录下的包下的所有文件
- mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b
2、 使用@RequestBody获取请求体数据
前台ajax请求如下:
// 页面加载
$(function(){
// 绑定点击事件
$("#btn").click(function(){
$.ajax({
url:"user/testJson",
contentType:"application/json;charset=UTF-8",
data:'{"username":"aa","password":"123"}',
dataType:"json",
type:"post",
success:function(data){
alert(data);
alert(data.username);
}
});
});
});
(1)后台获取请求体数据(string):
* 获取请求体的数据
* @param body
*/
@RequestMapping("/testJson")
public void testJson(@RequestBody String body) {
System.out.println(body);
}
输出结果为一个Json字符串,{“username”:“aa”,“password”:“123”}
(2)同样的,如果使用JavaBean来接收,使用@RequestBody注解会把json的字符串转换成JavaBean的对象。如下:
* 获取请求体的数据
* @param body
*/
@RequestMapping("/testJson")
public void testJson(@RequestBody User user) {
System.out.println(user.getUsername());
System.out.println(user.getPassword());
}
SpringMVC就会自动封装到User对象的属性,就能打印出用户名及密码。
(3)使用@ResponseBody注解把JavaBean对象转换成json字符串,直接响应
要求方法返回JavaBean对象
/**
* 获取请求体的数据 并返回Json数据
* @param body
*/
@RequestMapping("/testJson")
@ResponseBody
public User testJson(@RequestBody User user) {
System.out.println(user.getUsername());
System.out.println(user.getPassword());
user.setName("许你长欢");
return user;
}
四、RESTful风格支持
Spring MVC 除了支持 JSON 数据交互外,还支持 RESTful 风格的编程。 接下来就对 Spring MVC 中 RESTful 风格的编程进行简单的讲解。
1、什么是RESTful
RESTful 也称之为 REST ( Representational State Transfer ),可以将它理解为一种软件架构风格或设计风格,而不是一个标准。
简单来说, RESTful 风格就是把请求参数变成请求路径的一种风格。 例如,传统的 URL 请 求格式为:
http://.../queryltems?id=l
而采用 RESTful 风格后,其 URL 请求为:
http://.../items/l
从上述两个请求中可以看出, RESTful 风格中的 URL 将请求参数 id=1 变成了请求路径的一 部分,并且 URL 中的 queryltems 也变成了 items ( RESTful 风格中的 URL 不存在动词形式的路径,如 queryltems 表示查询订单,是一个动词,而 items 表示订单,为名词)。
RESTful 风格在 HTIP 请求中,使用 put、 delete、 post 和 get 方式分别对应添加、删除、 修改和查询的操作。
2、应用案例
在使用RESTful风格时,首先需要配置环境
<!--配置前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加载springmvc.xml配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--启动服务器,创建该servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
本案例将采用 RESTful 风格的请求实现对用户信息的查询,同时返回 JSON 格式的数据。 其 具体实现步骤如下。
(1)在控制器类 UserController 中,编写用户查询方法 selectUser() ,代码如下所示。
/**
*接收 RESTful 风格的请求,其接收方式为 GET
*/
@RequestMapping(value="/user/{id}" ,method=RequestMethod.Get) @ResponseBody
public User selectUser(@PathVariable("id") String id)
{
//查看数据接收
System.out.println("id="+id);
User user=new User() ;
//模拟根据 id 查询出到用户对象数据
if (id.equals ("1234")){
user.setUsername("tom");
}
//返回 JSON 格式的数据 return
return user;
}
在上述代码中, @RequestMapping(value="/user/{id}",method=RequestMethod.GET)注解 用于匹配请求路径(包括参数)和方式。 其中 value="/user/{id}“表示可以匹配以 “/user/{id}” 结尾的请求, id 为请求中的动态参数; method=RequestMethod.GET 表示只接收 GET 方式的请求。 方法中的@PathVariable(“id”)注解则用于接收并绑定请求参数,它可以将请求 URL 中的变量映射到方法的形参上,如果请求路径为 “/user/{id}” ,即请求参数中的 id 和方法形参名称 id 一样,则 @PathVariable 后面的”(“id”)" 可以省略。
上述可能看不出太大差别,下面再来个PUT请求的例子:
/**
* 用户注册接口
* @param administrators
* @return
*/
@RequestMapping(value = "/webRegister",method = RequestMethod.PUT)
@ResponseBody
public String webRegister(@RequestBody Administrators administrators) throws JsonProcessingException {
Map<String,Object> returnMap = new HashMap<String,Object>();
if(webUserService.regist(administrators)){
returnMap.put("state", DormiConstants.SUCCESS);
}else {
returnMap.put("state",DormiConstants.fail);
}
return objectMapper.writeValueAsString(returnMap);
}