開發(fā)環(huán)境
- IDEA 2017
- JDK 1.8
- Spring 4.2.2.RELEASE
- Jackson 2.8.5
項(xiàng)目結(jié)構(gòu)
└─main
├─java
│ └─com
│ └─smart
│ ├─controller
│ │ JSONController.java
│ │
│ └─domain
│ User.java
│
├─resources
│ smart-context.xml
│
└─webapp
└─WEB-INF
web.xml
因?yàn)槭且粋€(gè)小 demo,所以代碼盡量簡單,只有一個(gè) Controller 和 Domain 對象
依賴
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.smart</groupId>
<artifactId>chapter2</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<spring.version>4.2.2.RELEASE</spring.version>
<jackson.version>2.8.5</jackson.version>
<tomcat7-maven-plugin>2.2</tomcat7-maven-plugin>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>${tomcat7-maven-plugin}</version>
<configuration>
<path>/${project.artifactId}</path>
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
只需要 SpringMVC 和 Jackson 依賴即可
Domain
package com.smart.domain;
public class User {
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Controller
package com.smart.controller;
import com.smart.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@Controller
public class JSONController {
@RequestMapping("/testJavaBean")
@ResponseBody
public User test(@RequestParam("name") String name) {
User user = new User();
user.setUserName(name);
user.setPassword("123456");
return user;
}
@RequestMapping("/testMap")
@ResponseBody
public Map test2(@RequestParam("name") String name) {
Map<String, Object> map = new HashMap<>();
map.put("name", name);
map.put("test", 123);
map.put("array", new String[]{"a", "b", "c"});
return map;
}
}
別忘了給 Controller 的方法添加上 @ResponseBody 注解,這樣才能返回 JSON
ApplicationContext.xml
smart-context.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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.smart.controller"/>
<mvc:annotation-driven/>
</beans>
Spring 的配置文件也是很簡單,關(guān)鍵在于要加上 <mvc:annotation-driven/>
web.xml
<web-app version="3.0" 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">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:smart-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>smart</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:smart-context.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>smart</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
在 web.xml 指定 ApplicationContext 的文件位置即可
運(yùn)行結(jié)果
URL http://localhost:8080/chapter2/testJavaBean?name=我是中文

進(jìn)階
一般在真實(shí)開發(fā)的時(shí)候,JSON 數(shù)據(jù)一般是這樣的
- 請求成功的時(shí)
{
"code": 200,
"data": {
"userId": 1,
"userName": "Admin",
"credits": 160,
"lastIp": "0:0:0:0:0:0:0:1",
"lastVisit": 1514968628552
}
}
- 請求失敗時(shí)
{
"code": 404,
"message": "賬號或密碼錯誤"
}
從上面可以看到,服務(wù)器傳回來的 JSON 格式是這樣
{
"code": xx,
"message": xx,
"data": xxx
}
而且,如果 JSON 數(shù)據(jù)中的值為 null 的話,就不傳回來。對于這樣的需求要怎么實(shí)現(xiàn)呢?
APIResult
首先按照服務(wù)器的 JSON 格式,定義一個(gè) JavaBean,至于 data 部分用 Object 表示
package com.smart.domain;
import com.smart.constant.ApiConstant;
public class APIResult {
private int code;
private String message;
private Object data;
public static APIResult createOk(Object data) {
return createWithCodeAndData(ApiConstant.Code.OK, null, data);
}
public static APIResult createOKMessage(String message) {
APIResult result = new APIResult();
result.setCode(ApiConstant.Code.OK);
result.setMessage(message);
return result;
}
public static APIResult createNg(String message) {
return createWithCodeAndData(ApiConstant.Code.NG, message, null);
}
private static APIResult createWithCodeAndData(int code, String message, Object data) {
APIResult result = new APIResult();
result.setCode(code);
result.setMessage(message);
result.setData(data);
return result;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
對于 null 字段不顯示的需求,只需要在 ApplicationContext 配置文件定義即可。注意了,這個(gè)定義是全局生效的
<bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="serializationInclusion" value="NON_NULL"/>
</bean>
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="objectMapper" />
<property name="prettyPrint" value="true"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
最后就是修改一下 Controller 的代碼,使用 APIResult 將數(shù)據(jù)包裝起來
package com.smart.controller;
import com.smart.domain.APIResult;
import com.smart.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@Controller
public class JSONController {
@RequestMapping("/testJavaBean")
@ResponseBody
public APIResult test(@RequestParam("name") String name) {
User user = new User();
user.setUserName(name);
user.setPassword("123456");
return APIResult.createOk(user);
}
@RequestMapping("/testMap")
@ResponseBody
public APIResult test2(@RequestParam("name") String name) {
Map<String, Object> map = new HashMap<>();
map.put("name", name);
map.put("test", 123);
map.put("array", new String[]{"a", "b", "c"});
return APIResult.createOk(map);
}
@RequestMapping("/testNg")
@ResponseBody
public APIResult testNg() {
return APIResult.createNg("用戶名或密碼錯誤");
}
}
URL: http://localhost:8080/chapter2/testNg
返回
{
"code": 404,
"message": "用戶名或密碼錯誤"
}
URL http://localhost:8080/chapter2/testMap?name=Admin
返回
{
"code": 200,
"data": {
"test": 123,
"array": [
"a",
"b",
"c"
],
"name": "Admin"
}
}
URL http://localhost:8080/chapter2/testJavaBean?name=Admin
返回
{
"code": 200,
"data": {
"userId": 0,
"userName": "Admin",
"password": "123456",
"credits": 0
}
}
對應(yīng)SpringBoot框架的做法
如果是 SpringBoot 框架來開發(fā)的話,更簡單了,不需要寫一堆的配置文件。
Application
package com.smart;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder) {
return applicationBuilder.sources(Application.class);
}
}
只需要一個(gè)使用 @SpringBootApplication 講某一個(gè)類注解為啟動類即可,不需要寫 ApplicationContext.xml 了
Controller
相反,Controller 只需要使用 @RestController 注解即可,可以將方法上的 @ResponseBody 注解去掉
package com.smart.controller;
import com.smart.domain.APIResult;
import com.smart.domain.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class JSONController {
@RequestMapping("/testJavaBean")
public APIResult test(@RequestParam("name") String name) {
User user = new User();
user.setUserName(name);
user.setPassword("123456");
return APIResult.createOk(user);
}
@RequestMapping("/testNg")
public APIResult testNg() {
return APIResult.createNg("用戶名或密碼錯誤");
}
}
對于JSON的格式要求:
- 去除 Null 字段
- 格式化打印
只需要在 src/main/resources/ 文件夾中創(chuàng)建一個(gè) application.properties 文件,添加如下內(nèi)容
spring.jackson.serialization.indent-output=true
spring.jackson.serialization-inclusion=non_null