下面要给大家介绍的是和自定义封装springboot框架相关的内容,在java当中这算是比较常见的问题了,一起来看看吧。
自定义封装框架
1、对request请求,添加拦截器。
继承webMvcConfiguerAdapter,只要把自定义的拦截器注入就可以了。
这个截器主要有五个功能:
假如有OpenInterface注解,那么跳过拦截,主要用于第三方回调,或者接口直接调用;
获取前端app_name、app_version,这两个参数主要是用来验证app版本是不是需要更新,假如,是web项目这两个参数可以不要,最后将他们写到MDC去;
添加追踪信息到MDC里去;
traceId作用和springcloud的sleuth类似,能够在查询日志的时候,凭借这个关键字拉取某个请求全部日志,用uuid生成,保证每个请求的traceId不一样;
假如网页要切换语言,将下面注释的部分打开就可以了,一个做语言国际化标准;
token校验,这里的话是自己写的token校验,假如,大家用shiro或者是spring
security这个可以不用,主要的话,是判断是否登入,不需要这个功能的可以删除;@Configuration
public class GlobalRequestHandler extends WebMvcConfigurerAdapter
{
@Override
public void addInterceptors(InterceptorRegistry registry)
{
registry.addInterceptor(requestInterceptor());
}
public HandlerInterceptorAdapter requestInterceptor()
{
return new HandlerInterceptorAdapter()
{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{
//OpenInterface注释的接口不拦截
if (((HandlerMethod) handler)
.getMethod()
.isAnnotationPresent(OpenInterface.class))
{
return true;
}
interceptorHandler(request, handler);
return true;
}
};
}
private void interceptorHandler(HttpServletRequest request, Object handler)
{
//获取请求信息
String appName = request.getHeader(Constants.APP_NAME);
String appVersion = request.getHeader(Constants.APP_VERSION);
//String lang = request.getHeader(Constants.LANG);
if (StringUtils.isEmpty(appName) || StringUtils.isEmpty(appVersion))
{
throw new SystemException(ExceptionCode.HANDLER_PARAM_ERROR.getCode(), "handler param is null!");
}
//清空线程缓存
MDC.clear();
//设置请求信息
MDC.put(Constants.APP_NAME, appName);
MDC.put(Constants.APP_VERSION, appVersion);
MDC.put("traceId", UUID.randomUUID()
.toString());
//语言国际化,有需要开启
//LocaleContextHolder.setLocale(StringUtils.isEmpty(lang) ? Constants.DEFAULT_LANG : Locale.forLanguageTag(lang));
//检查token,标记UncheckToken不检查token
if (!((HandlerMethod) handler)
.getMethod()
.isAnnotationPresent(UncheckToken.class))
{
String token = "";
token = Utils.getCookieByName(request.getCookies(), Constants.COOKILE_TOKEN);
//TODO 校验token步骤
//if (StringUtils.isEmpty(token) && ){
// throw new SystemException(ExceptionCode.NEED_LOGIN.getCode(), "token is over time");
//}
}
}
}
2、封装response返回格式
这里的话修改了reponse返回格式
结果:不论是返回的是对象又或者是tring都统一格式化成code、data、msg
这里,之所以将springmvc的源码进行修改,主要是因为假如返回string类型,那么当你将它格式化之后会报错,这主要就是因为springmvc认为string类型应该用string信息解析器,可以,你却把它封装成了个对象,所以就最终造成了不能够解析了。@RestControllerAdvice
public class GlobalResponseHandler extends WebMvcRegistrationsAdapter
{
/*
* WebMvcRegistrationsAdapter通过getRequestMappingHandlerAdapter获取RequestMappingHandlerAdapter。
* RequestMappingHandlerAdapter重写ReturnValueHandlers方法
* 传入的视图解析器是jackson
* 注:ReturnValueHandlers调用视图转换器,所以在此处替换returnValue
*/
@Override
public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter()
{
RequestMappingHandlerAdapter requestMappingHandlerAdapter = new RequestMappingHandlerAdapter();
List handlerList = new ArrayList ();
handlerList.add(new RequestResponseBodyMethodProcessor(Collections.singletonList(new MappingJackson2HttpMessageConverter()))
{
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException
{
super.handleReturnValue(packageResult(returnValue), returnType, mavContainer, webRequest);
}
});
requestMappingHandlerAdapter.setReturnValueHandlers(handlerList);
return requestMappingHandlerAdapter;
}
private Object packageResult(Object data)
{
Response response = new Response();
response.setData(data);
return response;
}
}
3、全局异常拦截
作用和上面的相差不了多少,只是说上面的是对response格式化,这里的话是全局异常拦截并且格式化。@RestControllerAdvice
public class GlobalExceptionHandler
{
@ExceptionHandler(Throwable.class)
public Response handlerException(Throwable throwable)
{
Response response = new Response();
response.setMeg(throwable.getMessage());
response.setCode(ExceptionCode.SYSTEM_ERROR.getCode());
return getError(throwable, response);
}
private Response getError(Throwable throwable, Response response)
{
if (throwable instanceof ServiceException)
{
response.setCode(((ServiceException) throwable)
.getCode());
}
else if (throwable instanceof NoHandlerFoundException)
{
response.setCode(ExceptionCode.NO_HANDLER_ERROR.getCode());
}
else if (throwable instanceof HttpMessageNotReadableException)
{
response.setCode(ExceptionCode.PARAM_TYPE_ERROR.getCode());
}
return response;
}
}
4、日志
pringboot默认是用logback,logstash是对接ELK的,所以FILE-INFO用该格式化,能够直接对接ELK。def final LOCATION = "/data/log/app/"
def final SERVER_NAME = "base"
def final SAVE_TIME_RANGE = 7
String ENV = System.getProperty("env")
if (StringUtils.isEmpty(ENV))
{
appender('CONSOLE', ConsoleAppender)
{
encoder(PatternLayoutEncoder)
{
pattern = "%d{yyyy-MM-dd HH:mm:ss.SSS} %relative [%thread] %-5level %logger{36} %X{requestId} - %msg%n"
}
}
root(INFO, ['CONSOLE'])
}
else
{
appender('FILE-INFO', RollingFileAppender)
{
rollingPolicy(TimeBasedRollingPolicy)
{
fileNamePattern = String.format("%s%s/%s%s%s", LOCATION, SERVER_NAME, "logFile.", ENV, ".%d{yyyy-MM-dd}.log.gz")
maxHistory = SAVE_TIME_RANGE
}
encoder(LogstashEncoder)
{
includeMdcKeyNames = ["traceId"]
}
}
root(INFO, ['FILE-INFO'])
}
在java当中有很多的东西都是我们要去了解和掌握的,希望上面的内容能够对你有所帮助,更多java基础知识,请继续通过奇Q工具网来进行了解吧。
推荐阅读: