Java轻量级代码工程

打印 上一主题 下一主题

主题 666|帖子 666|积分 1998

一、背景简介

最近2年,很多公司接项目开始不挑剔了,只要核算下来有收益不会亏,就会库库的做各种没头没脑的项目,都是抱着多撑一天是一天的躺平心态。
如果项目和业务稳定,自然也有动力卷架构卷计划。
然而2024年对于很多研发团队的打工人来说,普遍都是处在随时卷铺盖走人的状态中,自然就是怎么省事怎么来,做项目时间和成本是最重视的维度。
抛开什么AI和各种工具加持,节省编程时间最有效的办法就是:拿现成的,最好只改个端口号。
二、工程结构

2024年上半年各种不大不小的项目写下来,其实从代码工程上看都是差不多的,服务端无非就是前和后两个代码工程,集成基础框架就可以增删改查了。
为了后续其它项目利用相同的基础工程,在第一个项目中,预留了代码工程的初期基础计划,方便那什么循环利用,在这篇文章简单分享一下。

基础的代码工程就这几块,实际上就是前后台两个单体服务,不涉及微服务和复杂架构,就是拿来应付各种希奇的内部项目的快速开辟;两个门面服务分别依赖frame和shared和third三层代码包,然后运行启动类即可。
既然是单体服务,自然也不涉及数据库的拆分,能安稳运行就可以了。
  1. <modules>
  2.   
  3.   <module>bm-facade</module>
  4.   
  5.   <module>bm-admin</module>
  6.   
  7.   <module>bm-shared</module>
  8.   
  9.   <module>bm-frame</module>
  10.   
  11.   <module>bm-third</module>
  12. </modules>
复制代码
三、模块化功能

3.1 框架模块

主要管理代码工程核心组件依赖,好比SpringBoot框架,MySQL数据库,MybatisPlus持久层,Swagger接口等,而且添加了一个公共过滤器。
  1. @Slf4j
  2. @Component
  3. public class CommonFilter extends OncePerRequestFilter implements Ordered {
  4.     @Override
  5.     protected void doFilterInternal(HttpServletRequest request,
  6.                                     HttpServletResponse response,
  7.                                     FilterChain chain)
  8.     throws ServletException, IOException {
  9.         log.info("CommonFilter...doFilterInternal");
  10.         // 请求向下转发
  11.         chain.doFilter(request, response);
  12.     }
  13.     @Override
  14.     public int getOrder() {
  15.         return 999 ;
  16.     }
  17. }
复制代码
对于一些须要的配置类和二次封装,也放在了这一层,别的为了简化工程的复杂性,利用AOP的方式包装了日志记录和令牌核验;
AOP切面编程就不说了,这个在项目中常常利用;Token令牌的封装方式可以自行扩展,权限校验拿数据的记录对比一下即可。
  1. @Component
  2. public class BaseToken {
  3.   @Getter
  4.   @Setter
  5.   private Long userId;
  6.   @Getter
  7.   @Setter
  8.   private String userName;
  9.   @Getter
  10.   @Setter
  11.   private String appName;
  12.   @Getter
  13.   @Setter
  14.   private Long expireTime;
  15.   private static final byte[] AES_KEY = Arrays.copyOf(MD5.create().digest(BaseToken.class.getPackage().getName()), 16);
  16.   @Getter
  17.   private final String currentType = BaseToken.class.getTypeName();
  18.   public void expireTime(int effective) {
  19.     expireTime = System.currentTimeMillis()/1000 + effective ;
  20.   }
  21.   public boolean expired() {
  22.     return expireTime < (System.currentTimeMillis() / 1000);
  23.   }
  24.   public String toToken() {
  25.     String data = JSONUtil.toJsonStr(this);
  26.     return SecureUtil.aes(AES_KEY).encryptBase64(data);
  27.   }
  28.   public static BaseToken parseToken(String token) {
  29.     String dataStr = SecureUtil.aes(AES_KEY).decryptStr(token);
  30.     return JSONUtil.toBean(dataStr, BaseToken.class);
  31.   }
  32.   public boolean checkPermission (String... permissionCode) {
  33.     AuthCheck authService = SpringUtil.getBean(AuthCheck.class);
  34.     return authService.hasPermission(this.getUserId(), permissionCode);
  35.   }
  36. }
复制代码
利用AOP切面编程拦截要鉴权的方法即可。
  1. @Component
  2. @Aspect
  3. @RequiredArgsConstructor
  4. public class AuthAop {
  5.     /**
  6.      * 切入点
  7.      */
  8.     @Pointcut("@annotation(com.butte.mound.frame.security.Auth)")
  9.     public void logPointCut() {
  10.     }
  11.     @Around("logPointCut()")
  12.     public Object around (ProceedingJoinPoint point) throws Throwable {
  13.         try{
  14.             // 检查权限
  15.             checkAuth(point);
  16.             // 执行方法
  17.             Object result = point.proceed();
  18.             return result;
  19.         } catch (Exception e){
  20.             e.printStackTrace();
  21.             throw e ;
  22.         }
  23.     }
  24.     private void checkAuth (ProceedingJoinPoint point){
  25.         try{
  26.             MethodSignature signature = (MethodSignature) point.getSignature();
  27.             Method method = signature.getMethod();
  28.             Auth auth = method.getAnnotation(Auth.class);
  29.             BaseToken token = TokenContext.getToken();
  30.             token.checkPermission(auth.authCode());
  31.         } catch (Exception e){
  32.             e.printStackTrace();
  33.         }
  34.     }
  35. }
复制代码
3.2 业务共享模块

主要管理业务代码,数据库相关的持久层文件,如果在服务层前后台业务差异过大的话,也可以考虑分2层管理即可,在体量小的项目中,持久层代码险些差异不大,最多只是一些自界说查询。

3.3 前后台模块

前后台两个模块,主要就是API接入层,通常就是用户访问和系统管理的两个服务,在逻辑上并没有什么本质差异,为了方便不同角色的请求管理,在两个工程内各添加了一个拦截器。
  1. @Slf4j
  2. @Component
  3. public class FacadeInterceptor implements HandlerInterceptor {
  4.   @Override
  5.   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  6.     log.info("req uri : {}",request.getRequestURI());
  7.     String facadeToken = "令牌";
  8.     BaseToken token = BaseToken.parseToken(facadeToken);
  9.     TokenContext.setToken(token);
  10.     return Boolean.TRUE ;
  11.   }
  12. }
复制代码
3.4 第三方模块

至于常见的第三方API对接,好比短信服务,OSS文件存储,第三方登录等,如果考虑多个项目多次复用的话,可以单独拎一层出来,简单封装一层工具类,方便之后随时更换,当然也可以在业务工程中直接调用第三方的封装类。
四、源码地址
  1. 文档仓库:
  2. https://gitee.com/cicadasmile/butte-java-note
  3. 源码仓库:
  4. https://gitee.com/cicadasmile/butte-mound
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

李优秀

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表