Java轻量级代码工程
一、背景简介
最近2年,很多公司接项目开始不挑剔了,只要核算下来有收益不会亏,就会库库的做各种没头没脑的项目,都是抱着多撑一天是一天的躺平心态。
如果项目和业务稳定,自然也有动力卷架构卷设计。
然而2024年对于很多研发团队的打工人来说,普遍都是处在随时卷铺盖走人的状态中,自然就是怎么省事怎么来,做项目时间和成本是最重视的维度。
抛开什么AI和各种工具加持,节省编程时间最有效的办法就是:拿现成的,最好只改个端口号。
二、工程结构
2024年上半年各种不大不小的项目写下来,其实从代码工程上看都是差不多的,服务端无非就是前和后两个代码工程,集成基础框架就可以增删改查了。
为了后续其它项目使用相同的基础工程,在第一个项目中,预留了代码工程的初期基础设计,方便那什么循环利用,在这篇文章简单分享一下。

基础的代码工程就这几块,实际上就是前后台两个单体服务,不涉及微服务和复杂架构,就是拿来应付各种奇怪的内部项目的快速开发;两个门面服务分别依赖frame和shared和third三层代码包,然后运行启动类即可。
既然是单体服务,自然也不涉及数据库的拆分,能安稳运行就可以了。
<modules>
<!-- 门面管理 -->
<module>bm-facade</module>
<!-- 后台管理 -->
<module>bm-admin</module>
<!-- 业务共享层 -->
<module>bm-shared</module>
<!-- 框架管理 -->
<module>bm-frame</module>
<!-- 第三方接入 -->
<module>bm-third</module>
</modules>
三、模块化功能
3.1 框架模块
主要管理代码工程核心组件依赖,比如SpringBoot框架,MySQL数据库,MybatisPlus持久层,Swagger接口等,并且添加了一个公共过滤器。
@Slf4j
@Component
public class CommonFilter extends OncePerRequestFilter implements Ordered {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain)
throws ServletException, IOException {
log.info("CommonFilter...doFilterInternal");
// 请求向下转发
chain.doFilter(request, response);
}
@Override
public int getOrder() {
return 999 ;
}
}
对于一些必要的配置类和二次封装,也放在了这一层,另外为了简化工程的复杂性,使用AOP的方式包装了日志记录和令牌核验;
AOP切面编程就不说了,这个在项目中经常使用;Token令牌的封装方式可以自行扩展,权限校验拿数据的记录对比一下即可。
@Component
public class BaseToken {
@Getter
@Setter
private Long userId;
@Getter
@Setter
private String userName;
@Getter
@Setter
private String appName;
@Getter
@Setter
private Long expireTime;
private static final byte[] AES_KEY = Arrays.copyOf(MD5.create().digest(BaseToken.class.getPackage().getName()), 16);
@Getter
private final String currentType = BaseToken.class.getTypeName();
public void expireTime(int effective) {
expireTime = System.currentTimeMillis()/1000 + effective ;
}
public boolean expired() {
return expireTime < (System.currentTimeMillis() / 1000);
}
public String toToken() {
String data = JSONUtil.toJsonStr(this);
return SecureUtil.aes(AES_KEY).encryptBase64(data);
}
public static BaseToken parseToken(String token) {
String dataStr = SecureUtil.aes(AES_KEY).decryptStr(token);
return JSONUtil.toBean(dataStr, BaseToken.class);
}
public boolean checkPermission (String... permissionCode) {
AuthCheck authService = SpringUtil.getBean(AuthCheck.class);
return authService.hasPermission(this.getUserId(), permissionCode);
}
}
使用AOP切面编程拦截要鉴权的方法即可。
@Component
@Aspect
@RequiredArgsConstructor
public class AuthAop {
/**
* 切入点
*/
@Pointcut("@annotation(com.butte.mound.frame.security.Auth)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around (ProceedingJoinPoint point) throws Throwable {
try{
// 检查权限
checkAuth(point);
// 执行方法
Object result = point.proceed();
return result;
} catch (Exception e){
e.printStackTrace();
throw e ;
}
}
private void checkAuth (ProceedingJoinPoint point){
try{
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
Auth auth = method.getAnnotation(Auth.class);
BaseToken token = TokenContext.getToken();
token.checkPermission(auth.authCode());
} catch (Exception e){
e.printStackTrace();
}
}
}
3.2 业务共享模块
主要管理业务代码,数据库相关的持久层文件,如果在服务层前后台业务差异过大的话,也可以考虑分2层管理即可,在体量小的项目中,持久层代码几乎差异不大,最多只是一些自定义查询。

3.3 前后台模块
前后台两个模块,主要就是API接入层,通常就是用户访问和系统管理的两个服务,在逻辑上并没有什么本质差异,为了方便不同角色的请求管理,在两个工程内各添加了一个拦截器。

@Slf4j
@Component
public class FacadeInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("req uri : {}",request.getRequestURI());
String facadeToken = "令牌";
BaseToken token = BaseToken.parseToken(facadeToken);
TokenContext.setToken(token);
return Boolean.TRUE ;
}
}
3.4 第三方模块
至于常见的第三方API对接,比如短信服务,OSS文件存储,第三方登录等,如果考虑多个项目多次复用的话,可以单独拎一层出来,简单封装一层工具类,方便之后随时替换,当然也可以在业务工程中直接调用第三方的封装类。
四、源码地址
文档仓库:
https://gitee.com/cicadasmile/butte-java-note
源码仓库:
https://gitee.com/cicadasmile/butte-mound
Java轻量级代码工程的更多相关文章
- 编写Java脚本统计工程代码总行数
在新公司工作将近一年了,一直独自一人负责服务端集群的运维和代码的编写.不知不觉从一个Project发展到了七八个Project. 看着越来越多的代码,今天突然想统计一下一共写了多少代码.[这里只统计完 ...
- FastDFS搭建及java整合代码【转】
FastDFS软件介绍 1.什么是FastDFS FastDFS是用C语言编写的一款开源的分布式文件系统.FastDFS为互联网量身定制,充分考虑了冗余备份.负载均衡.线性扩容等机制,并注重高可用.高 ...
- java 轻量级同步volatile关键字简介与可见性有序性与synchronized区别 多线程中篇(十二)
概念 JMM规范解决了线程安全的问题,主要三个方面:原子性.可见性.有序性,借助于synchronized关键字体现,可以有效地保障线程安全(前提是你正确运用) 之前说过,这三个特性并不一定需要全部同 ...
- java 从一个工程action 跳转到另外一个工程action
实现功能:java 从一个工程action 跳转到另外一个工程action 在我们实际编程的过程中,大家一定遇到过这种情况,那就是在一个工程中,需要使用到另外一个工程的实体Bean和方法.那么遇到这种 ...
- Scala IDEA for Eclipse里用maven来创建scala和java项目代码环境(图文详解)
这篇博客 是在Scala IDEA for Eclipse里手动创建scala代码编写环境. Scala IDE for Eclipse的下载.安装和WordCount的初步使用(本地模式和集群模式) ...
- pagebean pagetag java 后台代码实现分页 demo 前台标签分页 后台java分页
java 后台代码实现分页 demo 实力 自己写的 标签分页 package com.cszoc.sockstore.util; import java.util.HashMap;import ja ...
- 经典KMP算法C++与Java实现代码
前言: KMP算法是一种字符串匹配算法,由Knuth,Morris和Pratt同时发现(简称KMP算法).KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.比 ...
- 常用 Java 静态代码分析工具的分析与比较
常用 Java 静态代码分析工具的分析与比较 简介: 本文首先介绍了静态代码分析的基 本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBu ...
- 分享:根据webservice WSDL地址自动生成java调用代码及JAR包
分享:根据webservice WSDL地址自动生成java调用代码及JAR包使用步骤:一.安装java 并配置JAVA_HOME 及 path二.安装ANT 并配置ANT_HOME三.解压WsdlT ...
- [原创]Java静态代码检查工具介绍
[原创]Java静态代码检查工具介绍 一 什么是静态代码检查? 静态代码分析是指无需运行被测代码,仅通过分析或检查源程序的语法.结构.过程.接口等来检查程序的正确性,找出代码隐藏的错误和缺陷,如参数 ...
随机推荐
- vue 的provide 和 inject
1.功能说明 在开发过程中,在子组件中如何获取父组件或者祖父级的数据.这个我们之前的做法是在子组件中找到父组件实例,然后使用父组件的数据.这样其实不是很自然. 在vue 中提供了 provide 和 ...
- uniapp权限判断
写法如下 // 检查是否有写入外部存储的权限 function writeExternalStoragePermission() { return new Promise((resolve, reje ...
- 基于 .NET 的 Nuget 发版工具
背景 由于 Natasha 及周边项目发版任务多,文件结构也不简单,之前一直使用基于 Github 管道脚本和 XUnit 来发版.这个方案对于发版环境与条件依赖性较强,且不够灵活,因此萌生出做一个本 ...
- vue3版本下element-plus和antd-vue选哪个更好一些?
Vue 3 发布后,各家第三方库开始陆续重构并支持 Vue 3 ,国内两大知名框架 Element Plus 和 Ant Design Vue 也相续发布新版支持 Vue 3.到底应该怎么选择呢? E ...
- DSL 和 reactive 噩梦
Kotlin 之美-DSL篇 - 掘金 像 Compose 那样写代码 :Kotlin DSL 原理与实战_fundroid_方卓的博客-CSDN博客 先找好一个靶子: val yesterday = ...
- CW信号的正交解调
1.CW信号 CW可以叫做等幅电报,它通过电键控制发信机产生短信号"."(点)和长信号"--"(划),并利用其不同组合表示不同的字符,从而组成单词和句子. ...
- Java中SPI机制原理解析
使用SPI机制前后的代码变化 加载MySQL对JDBC的Driver接口实现 在未使用SPI机制之前,使用JDBC操作数据库的时候,一般会写如下的代码: // 通过这行代码手动加载MySql对Driv ...
- Qt开发经验小技巧251-255
今天在一个头文件中,发现 #ifdef Q_OS_WIN #ifdef Q_CC_MSVC 之类的都失效了,搞得差点怀疑人生了.经历过之前类似的教训后,排查原来是没有提前引入 qglobal.h 头文 ...
- LCR 164. 破解闯关密码
破解闯关密码 闯关游戏需要破解一组密码,闯关组给出的有关密码的线索是: 一个拥有密码所有元素的非负整数数组 password 密码是 password 中所有元素拼接后得到的最小的一个数 请编写一个程 ...
- [转载]「服务」WCF中NetNamedPipeBinding的应用实例
「服务」WCF中NetNamedPipeBinding的应用实例 WCF中有很多种绑定,根据官方的说法,NetNamedPipeBinding是适用于同一台主机中不同进程之间的通信的. 今天终于实现了 ...