文章目錄
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
<%@ 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/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- 可選的 Bootstrap 主題文件(一般不用引入) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/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
<?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
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
<?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>
<!-- 配置SpringMVC核心控制器:(前端控制器) -->
<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 ☆控制層☆
不適用json的情況下
//控制層
@Controller
@RequestMapping("/department")
public class DepartmentController {
//自動注入
@Autowired
DepartmentService service;
// 如果這裏添加了@ResponseBody不會跳轉department_list.jsp頁面
@RequestMapping("/findAll")
public String findAll(Model model){
//查詢所有的部門信息
List<Department> list = service.findAll();
//將查詢所有的結果封裝到request域中
model.addAttribute( "list",list );
/**
* 跳轉,這個請求會執行憑藉
* */
return "department_list";
}
}
使用@ResponseBody之後我們發現,訪問得到的數據是json格式的數據,我們都知道前後端分離開發模式中,後端只需要提供數據接口(這個接口不是單指java裏面的interface,而是controller,service,dao)得到json格式的數據,所以沒有了跳轉到jsp頁面的那一步。當然使用了@ResponseBody之後也並不代表着不能進行頁面跳轉,我們可以使用response.sendRedirect()方法進行跳轉。
1.6 service層
@Service
public class EmployeeService {
@Autowired
DepartmentDao departmentDao;
public List<Employee> findAll() {
//此處查詢出來的employee對象裏面只存在部門的id.
List<Employee> list = dao.findAll();
//遍歷list中的employee對象
for (Employee employee : list) {
//根據部門id查詢出部門對象
Department department = departmentDao.findById( employee.getId() );
//重置employee對象中department對象
employee.setDepartment( department );
}
//返回集合
return list;
}
}
1.7 dao層
後面整合MyBatis,暫時使用JdbcTemplate
@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 實體類
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Department {
//部門編號
private Integer id;
//部門名稱
private String departmentName;
List<Employee> list;
}
//
@ResponseBody
@RequestMapping("/findAll")
public List<Department> findAll(HttpServletResponse response) throws Exception{
//查詢所有的部門信息
List<Department> list = service.findAll();
System.out.println( "list = " + list );
/** 傳統的方法:
//通過工具類將list轉成json字符串
String s = JsonUtils.objectToJson( list );
我們學完springMVC之後就可以這樣使用:@Responsebody
需要在springMVC.xml中添加mvc的命名空間和添加註解驅動
<mvc:annotation-driven/>
*/
/**
* //將查詢所有的結果封裝到request域中
* model.addAttribute( "list",list );
* 跳轉,這個請求會執行憑藉
* */
return list;
2. @RequestBody
@RequestBody 獲取一個請求的請求體,也可以接受json格式的數據,並裝轉成java對象。
在開發中經常使用@RestController代替@Controller,我們爲什麼使用@RestController呢?請看@RestController的源代碼你就會一目瞭然。
/* * *Spring 4.0引入了@RestController,這是一個控制器的專用版本,它是一個方便的註釋,除了自動添加 *@Controller和@ResponseBody註釋之外沒有其他新魔法。 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller @ResponseBody public @interface RestController { }
@RequestMapping("/requestBody")
public String requestBody(@RequestBody String body){
//不加@RequestBody默認屬性匹配
//@RequestBody可以接收Post請求的所有數據
System.out.println( "body = " + body );
//body = username=taoge&desc=lihai,使用form表單post送來的數據,不能使用get請求發送
//因爲@RequestBody是在請求體中拿到數據,而get請求沒有請求體
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()方法進行跳轉。
//查找所有department信息,並返回department_list頁面。
@ResponseBody
@RequestMapping("/findAll")
public List<Department> findAll(HttpServletResponse response) throws Exception{
//查詢所有的部門信息
List<Department> list = service.findAll();
System.out.println( "list = " + list );
/** 傳統的方法:
//通過工具類將list轉成json字符串
String s = JsonUtils.objectToJson( list );
我們學完springMVC之後就可以這樣使用:@Responsebody
需要在springMVC.xml中添加mvc的命名空間和添加註解驅動
<mvc:annotation-driven/>
*/
/**
* //將查詢所有的結果封裝到request域中
* model.addAttribute( "list",list );
* 跳轉,這個請求會執行憑藉
* */
return list;
}
4. HttpEntity<T>
- HttpEntity的方式獲取請求體
@RequestMapping("/httpEntity")
public String httpEntity(HttpEntity<String> httpEntity){
/**httpEntity = <,{host=[localhost:8080],
*connection=[keep-alive],
* upgrade-insecure-requests=[1],
* user-agent=[Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 *(KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36],
* sec-fetch-mode=[navigate], sec-fetch-user=[?1],
* accept= [text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,;q=0.8,appli *cation/signed-exchange;v=b3], sec-fetch-site=[none],
* accept-encoding=[gzip, deflate, br],
* accept-language=[zh-CN,zh;q=0.9],
* cookie=[SL_G_WPT_TO=zh; SL_GWPT_Show_Hide_tmp=undefined; SL_wptGlobTipTmp=undefined;
* JSESSIONID=EECBD1FAA123518AD4CAA82BEDFCFE97]}
* */
System.out.println( "httpEntity = " + httpEntity );
System.out.println( "httpEntity.getBody() = " + httpEntity.getBody() );
/**httpEntity.getHeaders().getConnection() = [keep-alive]*/
System.out.println( "httpEntity.getHeaders().getConnection() = " + httpEntity.getHeaders().getConnection() );
return "success";
}
5. ResponseEntity <T>
將返回的數據放到響應體中,
這個響應體使我們可控的。
@RequestMapping("/download")
public ResponseEntity<byte[]> download(HttpSession session)throws Exception{
//1.獲取servlet對象
ServletContext servletContext = session.getServletContext();
//2.獲取目標資源的真實路徑
String realPath = servletContext.getRealPath( "images" );
//3.創建file對象File.separator根據操作系統自動自適應
File file = new File( realPath + File.separator + "taoge.png" );
//4. 創建輸入流
FileInputStream fileInputStream = new FileInputStream( file );
//5.創建字節數組,將輸入流的資源放到字節數組中
//fileInputStream.availiable 獲取裏面有多少流
byte[] bytes = new byte[fileInputStream.available()];
//6.將輸入流放入字節數組中
fileInputStream.read(bytes);
//7.封裝responseEntity對象
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是這樣轉換數據的