[toc]
SpringMVC处理JSON
Gson 谷歌公司的产品
fastJson 阿里的产品
JsonLib
jackson(springmvc默认使用的)
使用jackson需要引三个包:
- jackson-annotations-2.1.5.jar
- jackson-core-2.1.5.jar
- jackson-databind-2.1.5.jar
1. SpringMVC使用
我们先看一下不适用json数据格式查找所有department信息,并返回department_list页面。如果熟悉这个流程可以跳过,还可以跟着再复习一下整个流程特别是xml的配置的具体含义。
1.1 depentment_list.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- 可选的 Bootstrap 主题文件(一般不用引入) --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> </head> <body> <div class="container"> <table class="table">
<thead> <tr> <th>Id</th> <th>DepartmentName</th> </tr> </thead>
<tbody> <c:forEach items="${list}" var="department" varStatus="index"> <tr> <td>${department.id}</td> <td>${department.departmentName}</td> </tr> </c:forEach> </tbody> </table> </div> </body> </html>
|
1.2 SpringMVC.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <?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" 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 "> <context:component-scan base-package="cn.justweb"/>
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> </bean> <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${justweb.driver}"></property> <property name="url" value="${justweb.url}"></property> <property name="username" value="${justweb.username}"></property> <property name="password" value="${justweb.password}"></property> </bean>
<bean id="template" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="datasource"></property> </bean>
</beans>
|
1.3 db.properties
1 2 3 4
| justweb.driver=com.mysql.jdbc.Driver justweb.url=jdbc:mysql://cdb-o6r75r3g.bj.tencentcdb.com:10015/springmvc_day02 justweb.username=root justweb.password=*******
|
1.4 web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <filter> <filter-name>hiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
<servlet> <servlet-name>dispatcherServlet</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>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
</web-app>
|
1.5 ☆控制层☆
传统的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Controller @RequestMapping("/department") public class DepartmentController {
@Autowired DepartmentService service;
@RequestMapping("/findAll") public String findAll(Model model){ List<Department> list = service.findAll();
model.addAttribute( "list",list );
return "department_list"; } }
|
使用@ResponseBody之后我们发现,访问得到的数据是json格式的数据,我们都知道前后端分离开发模式中,后端只需要提供数据接口(这个接口不是单指java里面的interface,而是controller,service,dao)得到json格式的数据,所以没有了跳转到jsp页面的那一步。当然使用了@ResponseBody之后也并不代表着不能进行页面跳转,我们可以使用response.sendRedirect()方法进行跳转。
1.6 service层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Service public class EmployeeService {
@Autowired DepartmentDao departmentDao;
public List<Employee> findAll() { List<Employee> list = dao.findAll();
for (Employee employee : list) { Department department = departmentDao.findById( employee.getId() ); employee.setDepartment( department ); } return list; } }
|
1.7 dao层
后面整合MyBatis,暂时使用JdbcTemplate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Repository public class DepartmentDao {
@Autowired private JdbcTemplate jt;
public List<Department> findAll(){ List<Department> list = null; try { list = jt.query( "select * from department", new BeanPropertyRowMapper<>( Department.class ) ); } catch (DataAccessException e) { e.printStackTrace(); } return list; } }
|
1.8 实体类
1 2 3 4 5 6 7 8 9 10 11
| @Data @AllArgsConstructor @NoArgsConstructor public class Department { private Integer id; private String departmentName;
List<Employee> list; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @ResponseBody @RequestMapping("/findAll") public List<Department> findAll(HttpServletResponse response) throws Exception{ List<Department> list = service.findAll();
System.out.println( "list = " + list );
return list;
|
2. @RequestBody
@RequestBody 获取一个请求的请求体,也可以接受json格式的数据,并装转成java对象。
在开发中经常使用@RestController代替@Controller,我们为什么使用@RestController呢?请看@RestController的源代码你就会一目了然。
1 2 3 4 5 6 7 8 9 10 11 12
|
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller @ResponseBody public @interface RestController {
}
|
1 2 3 4 5 6 7 8 9
| @RequestMapping("/requestBody") public String requestBody(@RequestBody String body){ System.out.println( "body = " + body ); return "success"; }
|
3. @ResponseBody
@ResponseBody:将返回的数据放在响应体中,如果是对象,jackson自动将对象转为json格式,即SpringMVC对JSON的支持。典型spring mvc应用,请求点通常返回html页面。有时我们仅需要实际数据,如使用ajax请求。
使用@ResponseBody之后我们发现,访问得到的数据是json格式的数据,我们都知道前后端分离开发模式中,后端只需要提供数据接口(这个接口不是单指java里面的interface,而是controller,service,dao)得到json格式的数据,所以没有了跳转到jsp页面的那一步。当然使用了@ResponseBody之后也并不代表着不能进行页面跳转,我们可以使用response.sendRedirect()方法进行跳转。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| @ResponseBody @RequestMapping("/findAll") public List<Department> findAll(HttpServletResponse response) throws Exception{ List<Department> list = service.findAll();
System.out.println( "list = " + list );
return list; }
|
4. HttpEntity<T>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @RequestMapping("/httpEntity") public String httpEntity(HttpEntity<String> httpEntity){
System.out.println( "httpEntity = " + httpEntity );
System.out.println( "httpEntity.getBody() = " + httpEntity.getBody() );
System.out.println( "httpEntity.getHeaders().getConnection() = " + httpEntity.getHeaders().getConnection() ); return "success"; }
|
5. ResponseEntity <T>
将返回的数据放到响应体中,这个响应体使我们可控的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @RequestMapping("/download") public ResponseEntity<byte[]> download(HttpSession session)throws Exception{
ServletContext servletContext = session.getServletContext();
String realPath = servletContext.getRealPath( "images" );
File file = new File( realPath + File.separator + "taoge.png" );
FileInputStream fileInputStream = new FileInputStream( file );
byte[] bytes = new byte[fileInputStream.available()];
fileInputStream.read(bytes);
HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.add("Content-Disposition","attachment;filename=taotao.png");
HttpStatus status = HttpStatus.OK;
return new ResponseEntity<>( bytes, httpHeaders, status );; }
|
6. HttpMessageConverter
我们通过上边几个注解的学习,你是否有这样 的疑问–是怎么把对象转成json,又怎么把json数据转成对象的?那么我们就需要了解一下–HttpMessageConverter 是 Spring3.0 新添加的一个接口,负责将请求信息转换为一个对象(类型为 T),将对象(类型为 T)输出为响应信息。
对上图的解释:
请求报文转成HttpInputMessage输入流,经过HttpMessageConverter转成java对象
java对象经HttpMessageConverter转成输出流HttpOutputMessage,根据输出流生成响应报文。
到这里你可能对HttpMessageConverter产生浓厚的兴趣–你可以根据这篇文章debug去探索一下。HttpMessageConverter是这样转换数据的
☆