在Spring Boot中,如果发现多个接口中有重复的代码,可以采用以下几种方式来提取和复用这段代码:
1、使用Service层方法
如果这段代码的逻辑与业务相关,可以将其封装到一个Service层的方法中,然后在Controller中调用这个方法。
// SysConfigService.java
public SysConfig findServerUrlConfig() {
SysConfig sysConfig = this.findSysConfigByConfigKey("server_url");
if (sysConfig == null) {
throw new ConfigNotFoundException("服务地址配置信息为空");
}
return sysConfig;
}
// Controller.java
@GetMapping("/endpoint")
public HttpResponseDto getEndpoint() {
SysConfig sysConfig = sysConfigService.findServerUrlConfig();
String serverUrl = sysConfig.getConfigValue();
// 使用serverUrl ...
}
2、使用Controller Advice
如果这段代码是与Controller相关的,比如预处理请求或后处理响应,可以使用@ControllerAdvice来创建一个全局的拦截器或处理器。
@ControllerAdvice
public class GlobalControllerAdvice {
@ModelAttribute
public void addServerUrl(Model model) {
SysConfig sysConfig = sysConfigService.findSysConfigByConfigKey("server_url");
if (sysConfig == null) {
throw new ConfigNotFoundException("服务地址配置信息为空");
}
model.addAttribute("serverUrl", sysConfig.getConfigValue());
}
}
然后在Controller中使用@ModelAttribute的值:
@GetMapping("/endpoint")
public HttpResponseDto getEndpoint(@ModelAttribute("serverUrl") String serverUrl) {
// 使用serverUrl...
}
3、使用AspectJ切面
如果这段代码是横切关注点,可以使用AspectJ切面来封装这段逻辑。
@Aspect
@Component
public class ServerUrlAspect {
@Before("execution(* com.example.controller.*.*(..))")
public void before(JoinPoint joinPoint) {
SysConfig sysConfig = sysConfigService.findSysConfigByConfigKey("server_url");
if (sysConfig == null) {
throw new ConfigNotFoundException("服务地址配置信息为空");
}
// 可以通过某种方式将sysConfig或其值传递给被切的方法
}
}
4、使用自定义注解和处理器
如果这段代码只适用于特定的场景,可以创建一个自定义注解和对应的处理器来处理这段逻辑。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoadServerUrl {}
@LoadServerUrl
@GetMapping("/endpoint")
public HttpResponseDto getEndpoint() {
// 在这里使用serverUrl
}
处理器:
@Aspect
@Component
public class LoadServerUrlAspect {
@Around("@annotation(LoadServerUrl)")
public Object loadServerUrl(ProceedingJoinPoint joinPoint) throws Throwable {
SysConfig sysConfig = sysConfigService.findSysConfigByConfigKey("server_url");
if (sysConfig == null) {
throw new ConfigNotFoundException("服务地址配置信息为空");
}
// 可以通过某种方式将sysConfig或其值传递给被切的方法
return joinPoint.proceed();
}
}
如果是纯粹的业务逻辑,推荐使用Service层方法;
如果是与请求处理紧密相关的逻辑,可以考虑使用@ControllerAdvice或自定义注解;
如果是横切关注点,使用AspectJ切面是最佳选择。