下面要给大家介绍的是和自定义封装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 < HandlerMethodReturnValueHandler > 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工具网来进行了解吧。
推荐阅读:
springboot框架的优点是什么? springboot比spring的优势如何?