程序源代码下载网站wordpress调用当前页面链接
程序源代码下载网站,wordpress调用当前页面链接,建立网站需要注意事项,建站模板网站设计往期热门文章#xff1a;1、年少不知自增好#xff0c;错把UUID当个宝#xff01;#xff01;#xff01;2、长期当程序员会失去什么#xff1f;3、支付宝#xff1a;多线程事务怎么回滚#xff1f;说用Transactional可以回去等通知了#xff01;4、效率拉爆#xff…往期热门文章1、年少不知自增好错把UUID当个宝2、长期当程序员会失去什么3、支付宝多线程事务怎么回滚说用Transactional可以回去等通知了4、效率拉爆IntelliJ IDEA 中的这几款 AI 编程插件你都用过吗5、Spring6.0Boot3.0秒级启动、万级并发的开发新姿势来源juejin.cn/post/7575017581036765222兄弟们咱做 Spring 项目的时候是不是总遇到这些破事每个 Controller 里都要写Autowired UserService userService注入一大堆 Service代码又乱又冗余想统一加个日志/异常处理得在每个 Service 方法里写一遍改起来要疯偶尔还会手滑把Service 类名/方法名写错编译不报错跑起来才出问题排查半天。今天给大家分享个我自己写的ServiceManager组件用 Lambda 搞定这些破事 —— 不用手动注入 Service调用方法像写公式一样简单还能自动缓存、统一处理异常新手也能秒懂秒用先说说这组件能解决啥实际问题举个栗子以前咱调用用户查询接口得这么写// 1. 先注入Service Autowired private UserService userService; // 2. 再调用方法 public SerResultUserDTO getUser(Long userId) { try { log.info(开始查用户ID{}, userId); UserDTO user userService.queryUser(userId); log.info(查询成功结果{}, user); return SerResult.success(user); } catch (Exception e) { log.error(查询失败, e); return SerResult.fail(查用户出错了); } }又是注入又是日志又是try-catch重复代码一堆。用了ServiceManager之后直接写成这样public SerResultUserDTO getUser(Long userId) { // 一行搞定传方法参数其他全帮你做 return ServiceManager.call(UserService::queryUser, userId); }注入没了。日志组件自动打。异常组件自动处理。爽不爽组件核心逻辑大白话拆解其实这组件就干了 3 件事你传个 Lambda比如UserService::queryUser它帮你找到对应的 Service 实例把找到的实例和方法缓存起来下次调用更快统一执行方法顺便把日志、异常处理都包了。下面咱一步步来代码都给你贴好复制过去改改就能用。第一步先搭基础 —— 需要的依赖和工具类首先得有几个小工具不用自己写直接复制1. 统一返回结果类SerResult不管调用成功还是失败都返回同一个格式前端好处理package org.pro.wwcx.ledger.common.dto; import lombok.Data; // 服务调用的统一返回结果前端拿到就知道是成功还是失败 Data publicclass SerResultT { privateint code; // 200成功500失败前端一看就懂 private String msg; // 提示信息比如“操作成功”“查不到用户” private T data; // 成功时返回的数据比如用户信息 // 成功的时候调用这个方法把数据传进去 publicstatic T SerResultT success(T data) { SerResultT result new SerResult(); result.setCode(200); result.setMsg(操作成功); result.setData(data); return result; } // 失败的时候调用这个方法传错误信息 publicstatic T SerResultT fail(String msg) { SerResultT result new SerResult(); result.setCode(500); result.setMsg(msg); result.setData(null); return result; } }2. Lambda 解析工具LambdaUtil这工具是核心帮咱从 Lambda 里 “扣” 出 Service 类名和方法名不用懂原理复制用就行package org.pro.wwcx.ledger.common.util; import java.io.Serializable; import java.lang.reflect.Method; import java.lang.invoke.SerializedLambda; // 从Lambda表达式里拿Service信息的工具 publicclass LambdaUtil { // 传个Lambda进来返回它对应的“元数据”比如哪个Service哪个方法 public static SerializedLambda valueOf(Serializable lambda) { if (lambda null) { thrownew IllegalArgumentException(Lambda不能传空); } try { // 反射拿到Lambda里的隐藏方法不用管这行是咋回事 Method writeReplaceMethod lambda.getClass().getDeclaredMethod(writeReplace); writeReplaceMethod.setAccessible(true); return (SerializedLambda) writeReplaceMethod.invoke(lambda); } catch (Exception e) { thrownew RuntimeException(解析Lambda出错了, e); } } }3. Spring 工具类SpringUtil帮咱从 Spring 里拿 Service 实例不用手动Autowired就是靠它package org.pro.wwcx.ledger.common.util; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; // 从Spring里拿Bean的工具不用自己注入Service Component publicclass SpringUtil implements ApplicationContextAware { // Spring的上下文相当于“Bean仓库” privatestatic ApplicationContext applicationContext; // 从仓库里按类型拿Bean比如拿UserService类型的实例 publicstatic T T getBean(ClassT requiredType) { if (applicationContext null) { thrownew RuntimeException(Spring还没初始化好呢); } return applicationContext.getBean(requiredType); } // 下面这行是Spring自动调用的不用管 Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringUtil.applicationContext applicationContext; } }4. 函数接口SerialBiFunction这个是 Lambda 的 “规矩”规定传参和返回值的格式复制就行package org.pro.wwcx.ledger.common.resolver.anno; import java.io.Serializable; // 支持序列化的双参数函数接口Lambda要符合这个格式 public interface SerialBiFunctionT, U, R extends Serializable { // 方法格式传入TService实例和U参数返回R结果 R apply(T t, U u); }5. 实例构建器InstBuilder帮咱快速创建对象的小工具不用写一堆set方法package org.pro.wwcx.ledger.common.resolver; // 快速创建对象的工具比如new ServiceExecutor后不用一个个set值 publicclass InstBuilderT { privatefinal T target; // 初始化要创建的对象 private InstBuilder(ClassT clazz) { try { this.target clazz.getDeclaredConstructor().newInstance(); } catch (Exception e) { thrownew RuntimeException(创建对象失败, e); } } // 静态方法入口InstBuilder.of(ServiceExecutor.class) publicstatic T InstBuilderT of(ClassT clazz) { returnnew InstBuilder(clazz); } // 链式set值比如.set(ServiceExecutor::setParam, param) public V InstBuilderT set(SetterT, V setter, V value) { setter.set(target, value); returnthis; } // 最后调用build()拿到对象 public T build() { return target; } // 定义setter的格式 FunctionalInterface publicinterface SetterT, V { void set(T target, V value); } }第二步核心组件 ——ServiceManager这是咱的主角所有逻辑都在这我一行行给你讲明白package org.pro.wwcx.ledger.common.servicer; import lombok.extern.slf4j.Slf4j; import org.pro.wwcx.ledger.common.dto.SerResult; import org.pro.wwcx.ledger.common.resolver.InstBuilder; import org.pro.wwcx.ledger.common.resolver.anno.SerialBiFunction; import org.pro.wwcx.ledger.common.util.LambdaUtil; import org.pro.wwcx.ledger.common.util.SpringUtil; import java.lang.invoke.SerializedLambda; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; // 日志注解能打日志 Slf4j publicclass ServiceManager { // 缓存初始化大小6666够咱用了不够再改 privatestaticfinalint INIT_COUNT 6666; // 缓存Lambda对应的Service信息key是Lambdavalue是Service元数据 privatestaticfinal MapSerialBiFunction?,?,?, LambdaMeta? CACHE_LAMBDA; // 静态代码块项目启动时就初始化缓存 static { CACHE_LAMBDA new ConcurrentHashMap(INIT_COUNT); } // 对外提供的调用方法传Lambda比如UserService::queryUser和参数返回结果 SuppressWarnings(unchecked) publicstatic T,U,R SerResultR call(SerialBiFunctionT,U,R fn, U param){ // 先检查Lambda不能传空 if (fn null) { return SerResult.fail(服务函数不能为空); } // 1. 从缓存拿Service信息有就直接用没有就解析并缓存 LambdaMetaT lambdaMeta (LambdaMetaT) CACHE_LAMBDA.computeIfAbsent(fn, k- { // 解析Lambda拿到Service实例、类名这些信息 LambdaMetaT meta parseSerialFunction(fn); log.debug(缓存Service信息{}, meta.getServiceName()); return meta; }); // 2. 创建执行器把Lambda、参数、Service信息传进去 ServiceExecutorT,U,R executor InstBuilder.of(ServiceExecutor.class) .set(ServiceExecutor::setServiceFn, fn) // 传Lambda方法 .set(ServiceExecutor::setParam, param) // 传参数 .set(ServiceExecutor::setLambdaMeta, lambdaMeta) // 传Service信息 .build(); // 构建执行器 // 3. 执行方法返回结果 return executor.callService(); } // 解析Lambda从Lambda里拿到Service类名、实例、方法名 SuppressWarnings(unchecked) privatestatic T, U, R LambdaMetaT parseSerialFunction(SerialBiFunctionT,U,R fn) { // 用LambdaUtil拿到Lambda的元数据 SerializedLambda lambda LambdaUtil.valueOf(fn); // 封装Service信息的对象 LambdaMetaT lambdaMeta new LambdaMeta(); // 1. 解析Service类名Lambda里的类名是“com/example/UserService”要改成“com.example.UserService” String tClassName lambda.getImplClass().replaceAll(/, .); try { // 2. 拿到Service的Class对象比如UserService.class ClassT aClass (ClassT) Class.forName(tClassName); // 3. 从Spring里拿Service实例不用Autowired就是靠这行 T inst SpringUtil.getBean(aClass); // 4. 把信息存到lambdaMeta里 lambdaMeta.setClazz(aClass); // 存Service的Class lambdaMeta.setInst(inst); // 存Service实例 lambdaMeta.setServiceName(lambda.getImplMethodName()); // 存方法名比如queryUser } catch (ClassNotFoundException e) { // 找不到类就抛异常 thrownew RuntimeException(没找到Service类 tClassName, e); } return lambdaMeta; } // 封装Service信息的内部类存Class、实例、方法名 lombok.Data privatestaticclass LambdaMetaT { private ClassT clazz; // Service的Class比如UserService.class private T inst; // Service实例Spring里的Bean private String serviceName; // 方法名比如queryUser } }第三步执行器 ——ServiceExecutor这是帮咱统一执行方法、打日志、处理异常的 “打工人”package org.pro.wwcx.ledger.common.servicer; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.pro.wwcx.ledger.common.dto.SerResult; import org.pro.wwcx.ledger.common.resolver.anno.SerialBiFunction; // 执行Service方法的类统一打日志、处理异常 Slf4j Setter publicclass ServiceExecutorT, U, R { private SerialBiFunctionT, U, R serviceFn; // 要执行的Lambda方法 private U param; // 方法参数 private ServiceManager.LambdaMetaT lambdaMeta; // Service信息 // 执行方法的核心逻辑 public SerResultR callService() { // 记录开始时间方便算耗时 long startTime System.currentTimeMillis(); String serviceName lambdaMeta.getClazz().getSimpleName(); // 比如UserService String methodName lambdaMeta.getServiceName(); // 比如queryUser log.info(开始调用{}的{}方法参数{}, serviceName, methodName, param); try { // 真正执行方法用Service实例调用Lambda方法 R result serviceFn.apply(lambdaMeta.getInst(), param); // 算耗时打成功日志 long costTime System.currentTimeMillis() - startTime; log.info(调用成功{}的{}方法耗时{}ms结果{}, serviceName, methodName, costTime, result); // 返回成功结果 return SerResult.success(result); } catch (Exception e) { // 出错了就打错误日志返回失败结果 long costTime System.currentTimeMillis() - startTime; log.error(调用失败{}的{}方法耗时{}ms, serviceName, methodName, costTime, e); return SerResult.fail(调用 serviceName 的 methodName 方法失败 e.getMessage()); } } }第四步怎么用举个实际例子咱以用户查询和更新为例看 Controller 里怎么写1. 先写个 Service正常写不用改package org.pro.wwcx.ledger.service; import org.pro.wwcx.ledger.dto.UserDTO; import org.pro.wwcx.ledger.dto.UserUpdateDTO; import org.springframework.stereotype.Service; // 正常的Service该咋写咋写 Service publicclass UserService { // 查用户根据ID查 public UserDTO queryUser(Long userId) { // 这里模拟查数据库实际项目里换JDBC/MyBatis UserDTO user new UserDTO(); user.setUserId(userId); user.setUserName(张三); user.setAge(25); return user; } // 更新用户传ID和更新参数 public Boolean updateUser(Long userId, UserUpdateDTO updateDTO) { // 这里模拟更新数据库 log.info(更新用户{}的信息{}, userId, updateDTO); returntrue; // 返回更新成功 } }2. Controller 里调用重点看变化package org.pro.wwcx.ledger.controller; import org.pro.wwcx.ledger.common.dto.SerResult; import org.pro.wwcx.ledger.common.servicer.ServiceManager; import org.pro.wwcx.ledger.dto.UserDTO; import org.pro.wwcx.ledger.dto.UserUpdateDTO; import org.pro.wwcx.ledger.service.UserService; import org.springframework.web.bind.annotation.*; RestController RequestMapping(/user) publicclass UserController { // 查用户不用注入UserService一行搞定 GetMapping(/{userId}) public SerResultUserDTO getUser(PathVariable Long userId) { // 直接传LambdaUserService::queryUser和参数userId return ServiceManager.call(UserService::queryUser, userId); } // 更新用户同样不用注入 PutMapping(/{userId}) public SerResultBoolean updateUser( PathVariable Long userId, RequestBody UserUpdateDTO updateDTO) { // 这里要注意因为updateUser有两个参数所以要显式指定Lambda类型 return ServiceManager.call( (UserService service, UserUpdateDTO dto) - service.updateUser(userId, dto), updateDTO ); } }3. 跑起来看看效果查用户的时候日志会自动打开始调用UserService的queryUser方法参数1001 调用成功UserService的queryUser方法耗时5ms结果UserDTO(userId1001, userName张三, age25)要是出错了比如传个不存在的用户 ID假设数据库查不到会抛异常日志会打错误信息返回给前端的结果是{ code: 500, msg: 调用UserService的queryUser方法失败用户不存在, data: null }这组件的好处总结一下不用再写 AutowiredController 里干干净净再也不用注入一堆 Service统一日志 / 异常想改日志格式、加权限校验只需要改ServiceExecutor不用改每个方法缓存优化解析过的 Service 信息会缓存下次调用更快类型安全写 Lambda 的时候方法名错了编译就报错不用等到运行才发现。注意事项避坑指南JDK 版本用 JDK8 及以上Lambda 表达式是 JDK8 才有的Service 要加 ServiceSpring 才能扫描到不然SpringUtil拿不到实例多实现类的情况如果一个接口有多个实现比如UserService有UserServiceImpl1和UserServiceImpl2需要在SpringUtil里加按名称拿 Bean 的方法。往期热门文章1、IDEA 2025.3 正式发布骚操作跟不上 2、干掉 VMwareProxmoxVE 真香~ 3、有哪些话一听就知道一个程序员是个水货 4、CompletableFuture的5个大坑 5、Spring 项目别再乱注入 Service 了用 Lambda 封装个统一调用组件爽到飞起 6、再见Maven官方推出全新一代Java项目构建工具性能提升2~10倍 7、程序员的伪年薪百万还能持续多久 8、索引10连问你能抗住第几问 9、趣图为什么程序员的代码不搞终身责任制? 10、我有 6 种统计线上接口耗时的方案6种