Springboot代码生成器V2.21版本升级——更新相关依赖版本、加入全局响应解决、使用注解控制登录和日志记录等
前言
生成器下载地址:http://www.zrxlh.top:8088/coreCode/.
源码地址:https://gitee.com/zrxjava/codeMan
因为工作和生活等多方面的影响,半年多没有升级博客,代码生成器也没有继续维护,后来不断有朋友发私信催我升级,并且提出相关的优化建议,今天终于得空把代码生成器根据朋友们的建议整体改良了一下,以后我也会尽量保持健康的升级速度,希望可以对大家有所帮助!
全局跨域配置
之前生成的代码每一个controller都会加上@CrossOrigin,现在则采用了整体的跨域配置,前者可以灵活控制,后者更加简单直接,但跨域一般都是为了前后台联调方便,所以采用了后者,由于正式环境上的前后端一般会使用nginx统一做转发解决,把跨域的接口写成调本域的接口,而后将这些接口转发到真正的请求地址,也就不存在跨域的问题。
有一点需要注意(与跨域无关),现在新版goole浏览器增强了安全方面的监控,主要是为了防止注入类攻击,假如发现访问应用的地址和应用的父级地址不同源,登录时会无法设置cookie,假如使用session控制客户的登录,就会出现获取不到seesion的问题,由于无法设置cookie,就没有了seesionId,导致登录无效。对此也有相应的处理办法:
1.打开Chrome设置,将chrome://flags/#same-site-by-default-cookies禁用,而后重启浏览器就可;
2.采用token代替cokkie做验证,也就是我们常用的使用redis保存token做验证的方式。
跨域配置的代码如下:
/** * 跨域配置 * * @author zrx */@Configurationpublic class CorsConfig { @Bean public FilterRegistrationBean<CorsFilter> corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("*"); config.addAllowedHeader("token"); config.addAllowedHeader("Content-Type"); config.addAllowedMethod("GET"); config.addAllowedMethod("POST"); config.addAllowedMethod("PUT"); config.addAllowedMethod("DELETE"); config.addAllowedMethod("OPTIONS"); config.setMaxAge(1000L * 60 * 60); source.registerCorsConfiguration("/**", config); FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source)); //过滤前会在阻拦器之前执行,就不会被阻拦器影响 bean.setOrder(0); return bean; }}增加控制登录和日志记录的注解
在实际的项目开发中,往往一个项目后端有很多api,有些api需要登录鉴权,有些则不需要,为了灵活控制,采用注解的方式来对此进行控制,原理很简单,在阻拦器中获取请求方法的注解信息,假如注解存在则进行登录验证,如不存在则直接放行,相关代码如下:
/** * 该注解用于REST API * 假如一个API需要客户客户登录,增加此注解 * * @author zrx */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Documentedpublic @interface LoginRequired {}@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new HandlerInterceptor() { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; LoginRequired loginRequired = handlerMethod.getMethodAnnotation(LoginRequired.class); if (null == loginRequired) { return true; } // 预请求 if (RequestMethod.OPTIONS.name().equals(request.getMethod())) { return true; } HttpSession session = request.getSession(); User user = (User) session.getAttribute("user"); if (user == null) { response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); response.setHeader("Access-Control-Allow-Methods", "*"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setContentType("application/json; charset=utf-8"); response.setCharacterEncoding("utf-8"); PrintWriter pw = response.getWriter(); pw.write("{\"code\":" + HttpServletResponse.SC_UNAUTHORIZED + ",\"status\":\"no\",\"msg\":\"无受权访问,请先登录\"}"); pw.flush(); pw.close(); return false; } } return true; } }).addPathPatterns("/**").excludePathPatterns("/login", "/register", "/login/doLogin", "/user/register", "/mystatic/**", "/druid/**", "/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**"); }使用方法也及其简单,直接在controller的方法上增加此注解就可,例:
/** * 查询 * * @return */ @ApiOperation(value = "查询") //增加此注解则表明调用此方法需要登录方可调用 @LoginRequired @PostMapping(value = "/select") public List<TestTableEntity> select(@RequestBody TestTableEntity entity) { return service.select(entity); }日志记录注解与登录注解同理,增加日志记录注解可以实现方法级别的日志记录,使用方法同上,代码如下:
/** * 需要记录的日志的注解 * 在需要记录日志的controller上增加该注解,可以记录日志 * * @author zrx */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface RecordLog { String value() default "";}@Aspect@Componentpublic class LogAopAspect { private static final Logger logger = LoggerFactory.getLogger(LogAopAspect.class); @Around("@annotation(bootdemo.core.annotation.RecordLog)") public Object process(ProceedingJoinPoint pjp) throws Throwable { Class<?> currentClass = pjp.getTarget().getClass(); MethodSignature signature = (MethodSignature) (pjp.getSignature()); String className = currentClass.getSimpleName(); String methodName = currentClass.getMethod(signature.getName(), signature.getParameterTypes()).getName(); logger.info("======= 开始执行:" + className + " — " + methodName + " ========"); Object obj = pjp.proceed(); logger.info("======= 执行结束:" + className + " — " + methodName + " ========"); return obj; }}响应统一解决
之前代码生成器的响应已经做了一层抽取,把返回的信息统一封装到了对象当中,但没有做到完全解耦,现在对响应做了全局的进一步封装,controller只要要书写业务代码,不需要再去new一个响应体对象,进一步降低了耦合度,对于程序异常只要要throw相应的异常就可,统一解决类会封装异常信息给予前端客户提醒,代码如下:
@Slf4j@ControllerAdvice@ResponseBodypublic class AllExceptionHandler implements ResponseBodyAdvice { @Override public boolean supports(MethodParameter returnType, Class clazz) { return null == returnType.getMethodAnnotation(NoPack.class); } /** * 响应返回之前对响应内容进行包装 */ @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if (MediaType.APPLICATION_JSON.equals(selectedContentType) || MediaType.APPLICATION_JSON_UTF8.equals(selectedContentType)) { Method method = (Method) returnType.getExecutable(); if (ResponseEntity.class.equals(method.getReturnType())) { return body; } if (null == body) { return ResponseResult.success(); } if (body instanceof ResponseResult) { return body; } return ResponseResult.success(body); } return body; } .... /** * 普通业务异常 * * @param ex * @return */ @ExceptionHandler(BusinessException.class) public ResponseResult businessExceptionHandler(HttpServletResponse response, BusinessException ex) { log.error(ex.getMessage(), ex); response.setStatus(ResponseStatus.BUSINESS_EXCEPTION.hCode); return ResponseResult.failed(ex.getCode(), ex.getMessage()); } /** * 其余错误 * * @param ex * @return */ @ExceptionHandler({Exception.class}) public ResponseResult exception(HttpServletResponse response, Exception ex) { log.error(ResponseStatus.OTHER_EXCEPTION.valueLog, ex); response.setStatus(ResponseStatus.OTHER_EXCEPTION.hCode); return ResponseResult.failed(ResponseStatus.OTHER_EXCEPTION.bCode, ResponseStatus.OTHER_EXCEPTION.valueZh); }}/** * 请求响应体 * * @author zrx */@Data@Builder@AllArgsConstructor@NoArgsConstructorpublic class ResponseResult implements Serializable { private static final long serialVersionUID = 6041766238120354185L; private int code; private String status; private String msg; private Object data; public static ResponseResult success() { return success(null); } public static ResponseResult success(Object data) { return ResponseResult.builder() .status(ResponseStatus.SUCCESS.valueEn) .msg(ResponseStatus.SUCCESS.valueZh) .code(ResponseStatus.SUCCESS.bCode) .data(data) .build(); } public static ResponseResult failed() { return failed("失败"); } public static ResponseResult failed(String msg) { return failed(ResponseStatus.FAILED.bCode, msg); } public static ResponseResult failed(int code, String msg) { return ResponseResult.builder() .status(ResponseStatus.FAILED.valueEn) .msg(msg) .code(code) .build(); }} /** * 该注解用于REST API * * 假如一个API的返回不需要被ResponseWrapper包装,增加此注解 * * @author zrx */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Documentedpublic @interface NoPack {}代码如上所示,实现ResponseBodyAdvice接口中的beforeBodyWrite方法,就可对返回的内容进行包装,spring中无时无刻都在渗透着aop的核心思想。
假如不想包装响应内容,则可以在controller的方法上增加NoPack注解来实现,原理与上面提到的登录注解一样:实现ResponseBodyAdvice的supports方法,假如不存在NoPack注解,则对响应内容做包装,spring已经帮我们实现了整体的功能,我们只要要重写方法加入相关业务就可。
swagger优化
swagger官方的样式比较丑,所以增加了新的swagger样式依赖,样式如下:
swagger
依赖如下:
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.5</version> </dependency>其余升级
除了以上升级之外,生成器还更新了mysql的版本依赖至8.0.18,springboot版本至2.2.6.RELEASE,spring版本至5.2.5.RELEASE,增加了lombok支持,修复了少量已知的bug,下一步准备加入权限配置的相关代码生成,进一步完善现有功能。
生成的代码展现
v2.21版
代码展现
结语
本次升级详情到这里就结束了,其中响应的统一解决个人认为还算是比较有意义的,也感谢大家提出的宝贵意见,工作忙,加上生活上的琐事,升级可能不会太及时,还望见谅,下次再见啦!
生成器下载地址:http://www.zrxlh.top:8088/coreCode/.
源码地址:https://gitee.com/zrxjava/codeMan
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Springboot代码生成器V2.21版本升级——更新相关依赖版本、加入全局响应解决、使用注解控制登录和日志记录等