SpringBoot通过不同的策略动态调用不同的实现类
前言
经常遇到这样的一个需求,前端传的实体类型相同,后端需要根据实体类中的某一个字符串,动态地调用某一个类的方法。
在 SpringBoot 中,我们可以理解成,一个 Controller 接口对应多个ServiceImpl ,使用这种方式,如果后期需要添加一个功能,仅仅创建一个 ServiceImpl 就可以满足需求,而不用再额外创建一个 Controller 接口。
现在假设一个情景,前端传入不同的用户类型,后端返回该用户的任务。你可能问我,为什么不直接把(用户类型,用户任务)存入数据库?
现在只是一个简单的场景而已,实际中更为复杂,无法直接存入数据库。
实现
我们先定义一个接口:
public interface UserService {
/**
* 返回用户的主要任务
* @return 任务
*/
String task();
}
两个实现类:
@Service("student")
public class StudentService implements UserService{
@Override
public String task() {
return "学习";
}
}
@Service("teacher")
public class TeacherService implements UserService{
@Override
public String task() {
return "教书";
}
}
实现动态调用的核心类
@Service
public class UserContext {
@Autowired
private Map<String, UserService> userMap;
public UserService getUserService(String type) {
return userMap.get(type);
}
}
Spring会自动地将形如(@Service后面的名称,实现该接口的类)注入到该userMap中
在启动后,userMap中就存在两个元素("student",StudentService)与("teacher",TeacherService)。
getUserService方法返回userMap中key=type的UserService对象
实体类:
@Data
public class User {
/**
* 类型
*/
private String type;
/**
* 任务
*/
private String task;
}
Controller 层接口:
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserContext context;
@PostMapping("/get-task")
public String getTask(@RequestBody User user) {
UserService service = context.getUserService(user.getType());
log.info("User Service Task is {}", service.task());
return service.task();
}
}
使用 Spring 自带的 RestTemplate 来测试,先创建配置类:
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
// 超时设置
factory.setReadTimeout(60000); // ms
factory.setConnectTimeout(60000);// ms
return factory;
}
}
编写测试类:
@SpringBootTest
class SpringDynamicCallClassApplicationTests {
@Autowired
private RestTemplate restTemplate;
@Test
void restTest() throws JSONException {
HttpHeaders headers = new HttpHeaders();
// 因为 UserController 使用了 @RequestBody 注解,所以需要 POST Json
headers.setContentType(MediaType.APPLICATION_JSON);
JSONObject UserJsonObject = new JSONObject();
UserJsonObject.put("type", "student");
UserJsonObject.put("task", "学习");
HttpEntity<String> request =
new HttpEntity<>(UserJsonObject.toString(), headers);
String UserResultAsJsonStr =
restTemplate.postForObject("http://localhost:8080/user/get-task", request, String.class);
System.out.println(UserResultAsJsonStr);
}
}
运行结果:


本文参考: