Java 中待总结工具类学习(自定义注解,读取配置,字面List)
1、使用 MessageFormat 格式化文本
int planet = 7; String event = "a disturbance in the Force"; String result = MessageFormat.format( "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.", planet, new Date(), event);
The output is:
At 12:30 PM on Jul 3, 2053, there was a disturbance in the Force on planet 7.
2、自定义注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @Target (ElementType.METHOD) @Retention (RetentionPolicy.RUNTIME) @Documented public @interface OperateLog { /** * 模块名称 * @return */ String moudleName() default "" ; /** * 操作名称 * @return */ String optName() default "" ; /** * 业务类型描述 * @return */ String description() default "" ; } |
通过 aop 做拦截处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | @Aspect @Component public class OperateLogAspect { @Autowired private OperateLogService operateLogService; @Pointcut ( "@annotation(com.youngcms.core.annotation.OperateLog)" ) public void operateLogCut(){ } @Around ( "operateLogCut()" ) public Object around(ProceedingJoinPoint point) throws Throwable { long beginTime = System.currentTimeMillis(); //执行方法 Object result = point.proceed(); //执行时长(毫秒) long time = System.currentTimeMillis() - beginTime; //保存日志 saveOperateLog(point, time); return result; } private void saveOperateLog(ProceedingJoinPoint joinPoint, long time) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); RequestMapping classRequestMapping=method.getDeclaringClass().getAnnotation(RequestMapping. class ); OperateLog operateLog=method.getAnnotation(OperateLog. class ); RequestMapping mothodRequestMapping= method.getAnnotation(RequestMapping. class ); com.youngcms.bean.OperateLog operateLogBean= new com.youngcms.bean.OperateLog(); if (operateLog!= null ){ operateLogBean.setModuleName(operateLog.moudleName()); operateLogBean.setOptName(operateLog.optName()); operateLogBean.setDescription(operateLog.description()); } //请求的类名 String className = joinPoint.getTarget().getClass().getName(); //请求的方法名 String methodName = signature.getName(); //请求的参数 //Object[] args = joinPoint.getArgs(); operateLogBean.setIp(IPUtils.getIpAddr(HttpKit.getRequest())); operateLogBean.setTime(time); operateLogBean.setMethod(className+ "." +methodName+ "()" ); operateLogBean.setUrl(classRequestMapping.value()[ 0 ]+mothodRequestMapping.value()[ 0 ]); String username = ((SysUser) SecurityUtils.getSubject().getPrincipal()).getRealName(); operateLogBean.setAuthor(username); operateLogBean.setCreateTime(DateUtil.dateToStr( new Date(), 12 )); operateLogService.insert(operateLogBean); } } |
3、条件判断注解
ConditionalOnProperty 的意思是,当 usemysql.local 属性配置存在并且不为 false,则创建这个 bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @Bean @ConditionalOnProperty ( name = "usemysql" , havingValue = "local" ) @ConditionalOnMissingBean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName( "com.mysql.cj.jdbc.Driver" ); dataSource.setUrl( "jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true" ); dataSource.setUsername( "mysqluser" ); dataSource.setPassword( "mysqlpass" ); return dataSource; } |
4.获取 ip 地址工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ublic class IPUtils { private static Logger logger = LoggerFactory.getLogger(IPUtils. class ); /** * 获取IP地址 * * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址 * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址 */ public static String getIpAddr(HttpServletRequest request) { String ip = null ; try { ip = request.getHeader( "x-forwarded-for" ); if (StringUtils.isEmpty(ip) || "unknown" .equalsIgnoreCase(ip)) { ip = request.getHeader( "Proxy-Client-IP" ); } if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown" .equalsIgnoreCase(ip)) { ip = request.getHeader( "WL-Proxy-Client-IP" ); } if (StringUtils.isEmpty(ip) || "unknown" .equalsIgnoreCase(ip)) { ip = request.getHeader( "HTTP_CLIENT_IP" ); } if (StringUtils.isEmpty(ip) || "unknown" .equalsIgnoreCase(ip)) { ip = request.getHeader( "HTTP_X_FORWARDED_FOR" ); } if (StringUtils.isEmpty(ip) || "unknown" .equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } } catch (Exception e) { logger.error( "IPUtils ERROR " , e); } return ip; } } |
5.读取配置文件
1 2 3 4 5 | // 获取 config/constant.properties 文件中的配置内容 private static ResourceBundle bundle = ResourceBundle.getBundle( "config/constant" ); public static String fileUploadPath =bundle.getString( "file-upload.dir" ); |
6.字面量形式构建 list
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class DefaultSqlInjector extends AbstractSqlInjector { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass) { return Stream.of( new Insert(), new Delete(), new DeleteByMap(), new DeleteById(), new DeleteBatchByIds(), new Update(), new UpdateById(), new SelectById(), new SelectBatchByIds(), new SelectByMap(), new SelectOne(), new SelectCount(), new SelectMaps(), new SelectMapsPage(), new SelectObjs(), new SelectList(), new SelectPage() ).collect(toList()); } } |
7.版本序列化防止反序列化失败
实现序列化接口添加
1 | private static final long serialVersionUID = 1L; |
反序列化的时候,虚拟机同样会先读取该变量值,然后再当前读取的类中寻找同样的变量值,如果找到,那么反序列话成功,找不到即会报异常。
默认 serialVersionUID 由虚拟机计算,然而如果对象结构发生变化,该值也会变化,因此我们显示声明,虚拟机就不会再进行计算了,可以保证向后兼容性。
233
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix