Spring Boot杂谈总结(一)

× 文章目录
  1. 一.Spring Boot中使用Fastjson代替Jackson
    1. 1.1 为什么使用Fastjson代替Jackson
    2. 1.2 使用Fastjson代替Jackson过程
  2. 二.Spring Boot自定义Spring MVC异常解析器
  3. 三 Spring Boot集成swagger
    1. 3.1 Spring Boot集成swagger
    2. 3.2 遇到的问题
  4. 四.参考文章

摘要 本篇文章主要介绍在Spring Boot中使用Fastjson代替Jackson,以及实现自己的自定义异常和扩展Spring MVC全局异常解析器,以及为了给前端测试提供接口文档Spring Boot集成swagger,以及集成swagger遇到问题的处理。

一.Spring Boot中使用Fastjson代替Jackson

1.1 为什么使用Fastjson代替Jackson

Jackson最主要的原因是Jackson在处理对象之前的循环嵌套关系时不便。什么是对象间的循环嵌套?比如A有一个List,B对象里又有一个A对象,当然返回A对象的Json字符串时,如果是Jackson就会发生异常,因为Jackson天生不具备处理这种关系的能力,而Fastjson正好具备了这种能力。

如果你用的是 Jackson,可以使用相应的注解来支持对象间的循环嵌套。可以百度Jackson循环嵌套。

1.2 使用Fastjson代替Jackson过程

1.引入依赖

1
2
3
4
5
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.29</version>
</dependency>
  1. 三种实现方式
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package org.xujin.janus.admin.exception;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
/**
* Spring MVC全局一场解析器
* @author xujin
*
*/
@Configuration
@EnableWebMvc
public class ApplicationExceptionAdapter extends WebMvcConfigurerAdapter {
/**
* 配置fastJson 用于替代jackson
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
// 1.定义一个convert 转换消息的对象
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
// 2 添加fastjson 的配置信息 比如 是否要格式化 返回的json数据
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
fastConverter.setFastJsonConfig(fastJsonConfig);
// 解决乱码的问题
List<MediaType> fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastConverter.setSupportedMediaTypes(fastMediaTypes);
converters.add(fastConverter);
}
/** 用自己的全局异常解析器替换Spring MVC本身的异常解析器 **/
@Override
public void configureHandlerExceptionResolvers(
List<HandlerExceptionResolver> exceptionResolvers) {
exceptionResolvers.add(new ApplicationExceptionResolver());
super.configureHandlerExceptionResolvers(exceptionResolvers);
}
}

或者

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
@EnableWebMvc
public class JanusAdminApplication extends WebMvcConfigurerAdapter {
/**
* 配置fastJson 用于替代jackson
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
// 1.定义一个convert 转换消息的对象
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
// 2 添加fastjson 的配置信息 比如 是否要格式化 返回的json数据
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
fastConverter.setFastJsonConfig(fastJsonConfig);
// 解决乱码的问题
List<MediaType> fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastConverter.setSupportedMediaTypes(fastMediaTypes);
converters.add(fastConverter);
}
public static void main(String[] args) {
SpringApplication.run(JanusAdminApplication.class, args);
}
}

二.Spring Boot自定义Spring MVC异常解析器

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package org.xujin.janus.admin.exception;
import java.io.IOException;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.apache.shiro.authz.UnauthenticatedException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.xujin.janus.admin.base.ResultData;
import org.xujin.janus.admin.constant.Config;
import org.xujin.janus.admin.utils.FastjsonFilterUtil;
import org.xujin.janus.admin.utils.ResourcesUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
/**
* @author xujin
* @Description: 全局异常处理器
*/
public class ApplicationExceptionResolver implements HandlerExceptionResolver {
/**
* Log类
*/
private Logger logger = Logger.getLogger(getClass());
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
logger.info("异常拦截器执行开始。");
// 输出 异常信息
String msgContent = ResourcesUtil.getValue(Config.MESSAGE, ex.getMessage());
logger.error("发生异常:" + msgContent, ex);
// 将异常信息转json输出
this.writeJsonByFilter(response, this.resolveExceptionCustom(ex), null, null);
logger.info("异常拦截器执行结束。");
return new ModelAndView();
}
/**
* 异常信息解析方法
*
* @param ex
*/
private ResultData resolveExceptionCustom(Exception ex) {
ResultData model = new ResultData();
if (ex instanceof ApplicationException) {
// 抛出的是系统自定义异常
model.setMsgCode(this.getMsgCode(ex));
}
else if (ex instanceof UnauthenticatedException) {
// 没有权限的异常
model.setMsgCode("ECOMMON00002");
}
else {
// 未知错误
model.setMsgCode("ECOMMON00001");
}
return model;
}
private String getMsgCode(Exception ex) {
// 输出 异常信息
String msgCode = ex.getMessage();
// 若返回的异常不直接是自定义异常,而是经过封装的异常
if (msgCode.charAt(0) != 'E' && msgCode.charAt(0) != 'W'
&& msgCode.charAt(0) != 'I') {
msgCode = ex.getCause().getMessage();
}
return msgCode;
}
/**
* 将对象转换成JSON字符串,并响应回前台
*/
protected void writeJsonByFilter(HttpServletResponse response, Object object,
String[] includesProperties, String[] excludesProperties) {
try {
// excludes优先于includes
FastjsonFilterUtil filter = new FastjsonFilterUtil();
if (excludesProperties != null && excludesProperties.length > 0) {
filter.getExcludes().addAll(Arrays.<String> asList(excludesProperties));
}
if (includesProperties != null && includesProperties.length > 0) {
filter.getIncludes().addAll(Arrays.<String> asList(includesProperties));
}
// 使用SerializerFeature.WriteDateUseDateFormat特性来序列化日期格式的类型为yyyy-MM-dd
// hh24:mi:ss
// 使用SerializerFeature.DisableCircularReferenceDetect特性关闭引用检测和生成
String json = JSON.toJSONString(object, filter,
SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.DisableCircularReferenceDetect);
logger.info("JSON String is:" + json);
response.setContentType("text/html;charset=utf-8");
response.getWriter().write(json);
response.getWriter().flush();
response.getWriter().close();
}
catch (IOException e) {
logger.error("An error occurred when object was converted to JSON", e);
}
}
}

三 Spring Boot集成swagger

3.1 Spring Boot集成swagger

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.5.0</version>
</dependency>

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
39
package org.xujin.janus.admin.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger2 配置
* @author xujin
*
*/
@Configuration
@EnableSwagger2
// 在生产环境不开启
@Profile({ "dev", "local" })
public class Swagger2Config {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
.apis(RequestHandlerSelectors
.basePackage("org.xujin.janus.admin.controller"))
.paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("Janus网关管控平台").description("Janus网关管控平台")
.contact("Software_King@qq.com").version("1.0").build();
}
}

3.2 遇到的问题

访问http://localhost:8080/swagger-ui.html,控制台出现错误

1.页面显示默认报错页面。后台报错:

1
No handler found for GET /swagger-ui.html

2.显示Swagger空白页面

原因分析:
在访问http://localhost:8080/swagger-ui.html 时,这个swagger-ui.html相关的所有前端静态文件都在springfox-swagger-ui-2.6.1.jar里面。Spring Boot自动配置本身不会自动把/swagger-ui.html这个路径映射到对应的目录META-INF/resources/下面。我们加上这个映射即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
@EnableWebMvc
public class ApplicationExceptionAdapter extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}

四.参考文章

http://www.cnblogs.com/bingshu/p/6864131.html

http://www.jianshu.com/p/840320d431a1

如果您觉得文章不错,可以打赏我喝一杯咖啡!