感觉有用,先记录下来。
一.Spring Boot中使用Fastjson代替Jackson
1.1 为什么使用Fastjson代替Jackson
Jackson最主要的原因是Jackson在处理对象之前的循环嵌套关系时不便。什么是对象间的循环嵌套? 比如A有一个List,B对象里又有一个A对象,当然返回A对象的Json字符串时,如果是Jackson就会发生异常,因为Jackson天生不具备处理这种关系的能力,而Fastjson正好具备了这种能力。
1.2 使用Fastjson代替Jackson过程
1.引入依赖
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
fastjson
</artifactId>
<version>
1.2.29
</version>
</dependency>
-
三种实现方式
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);
}
}
或者
@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异常解析器
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
-
<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>
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.页面显示默认报错页面。后台报错:
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/下面。我们加上这个映射即可。
@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://mp.weixin.qq.com/s/3A7KJEvzIYfJL795HifK7w