springboot根据参数,调用不同的service接口(策略模式)
一、前言
什么是策略模式?它的应用场景是什么?
https://www.cnblogs.com/mylqm/p/15080706.html
二、引入依赖
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.6</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency>
三、项目结构图
四、项目具体内容
1.bean
/** * @author *** * @title: AbstractRequestBean * @projectName strategy * @description TODO * @date 2022/2/28 13:22 */ @Data public abstract class AbstractRequestBean implements Serializable,VerifyModel { @NotBlank(message = "service不能为空") protected String service; @NotBlank(message = "param1不能为空") protected String param1; @NotBlank(message = "param2不能为空") protected String param2; }
/** * @author *** * @title: RequestBean * @projectName strategy * @description 请求参数 * @date 2022/2/28 13:30 */ public class RequestDto extends AbstractRequestBean implements Serializable { }
/** * @author *** * @title: VerifyModle * @projectName strategy * @description TODO * @date 2022/2/28 13:20 */ public interface VerifyModel { String getParam1(); String getParam2(); }
2.common
/** * @author *** * @title: ResponseData * @projectName strategy * @description TODO * @date 2022/2/28 13:11 */ public class ResponseData<T> { private String code = "200"; private String message = "成功"; private T data; public static <T> ResponseData<T> ok(T data) { return new ResponseData<T>(data); } public static <T> ResponseData<T> ok() { return new ResponseData<>(); } public static <T> ResponseData<T> fail() { return fail("500",null); } public static <T> ResponseData<T> fail(String message) { return fail("500",message); } public static <T> ResponseData<T> fail(String code,String message) { return new ResponseData<>(code,message); } public static <T> ResponseData<T> fail(String code,String message,T data) { return new ResponseData<T>(code,message,data); } public static <T> ResponseData<T> failByParam(String message) { return fail("500",message); } public ResponseData(T data) { super(); this.data = data; } public ResponseData(String message) { super(); this.message = message; } public ResponseData(String code,String message) { super(); this.message = message; this.code = code; } public ResponseData(String code,String message,T data) { super(); this.message = message; this.code = code; this.data = data; } public ResponseData() { super(); } public boolean success(){ return this.code.equals("200"); } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
3.constant
/** * @author *** * @title: ServiceConstant * @projectName strategy * @description TODO * @date 2022/2/28 13:15 */ public interface ServiceConstant { String VERSION = "1.0.0"; String TEST_ONE = "test.one"; }
/** * 校验结果 */ public class ValidationResult { //校验结果是否有错 private boolean hasErrors; //校验错误信息 private Map<String,String> errorMsg; public boolean isHasErrors() { return hasErrors; } public void setHasErrors(boolean hasErrors) { this.hasErrors = hasErrors; } public Map<String, String> getErrorMsg() { return errorMsg; } public void setErrorMsg(Map<String, String> errorMsg) { this.errorMsg = errorMsg; } @Override public String toString() { return "ValidationResult [hasErrors=" + hasErrors + ", errorMsg=" + errorMsg + "]"; } }
4.controller
/** * @author *** * @title: RequestController * @projectName strategy * @description TODO * @date 2022/2/28 13:03 */ @RestController @RequestMapping("/test") public class RequestController { @Resource private Map<String, AbstractService<?, ?>> serviceMap; @RequestMapping(value = "/service", method = RequestMethod.POST) public ResponseData<?> converge(@RequestBody JSONObject jsonObject) throws Exception { String service = jsonObject.getString("service"); AbstractService abstractService = serviceMap.get(service); if (abstractService == null) { return new ResponseData("500", "Please check your service param"); } AbstractRequestBean request = JSONObject.toJavaObject(jsonObject, (Class<AbstractRequestBean>) abstractService.getType()); //给上下文对象注入值 Context context = ContextUtil.getContext(); context.setService(request.getService()); //参数校验 ValidationResult result = ValidationUtil.validateEntity(request); if (result.isHasErrors()) { StringBuilder sbd = new StringBuilder(); result.getErrorMsg().forEach((k, v) -> { sbd.append(v).append("&"); }); return ResponseData.fail(sbd.deleteCharAt(sbd.length()-1).toString()); } return abstractService.req(request); } }
5.service
/** * @param <S> 初始请求参数 * @param <T> 业务请求参数 * @author *** * @title: AbstractService * @projectName strategy * @description 抽象服务类 * @date 2022/2/28 13:08 */ public abstract class AbstractService<S, T> { protected final Type type; protected AbstractService() { Type superClass = getClass().getGenericSuperclass(); type = ((ParameterizedType) superClass).getActualTypeArguments()[0]; } public Type getType() { return type; } @Autowired private RequestService requestService; /** * 业务逻辑处理 * * @param request 业务请求参数 * @return 业务响应参数 * @throws Exception */ public abstract ResponseData<?> handle(T request) throws Exception; /** * 交易接口统一入口 * * @param request 初始请求参数 * @return 签名响应参数 * @throws Exception */ public ResponseData<?> req(S request) throws Exception { try { T tarReq = convert(request); verify(request); return handle(tarReq); } finally { ContextUtil.clear(); } } /** * 入参校验 * * @param request */ private void verify(S request) { if (request != null) { VerifyModel verify = (VerifyModel) request; RequestDto requestDto = new RequestDto(); requestDto.setParam1(verify.getParam1()); requestDto.setParam2(verify.getParam2()); ResponseData responseData = requestService.verify(requestDto); if (!"200".equals(responseData.getCode())) { throw new RuntimeException(responseData.getMessage()); } } } /** * 转化初始请求参数为业务请求参数 * * @param s 初始请求参数 * @return 业务请求参数 */ private T convert(S s) { Type superClass = getClass().getGenericSuperclass(); Type targetType = ((ParameterizedType) superClass).getActualTypeArguments()[1]; // 传入类型,与转化类型相同 if (type == targetType) { return (T) s; } return null; } }
/** * @author *** * @title: RequestService * @projectName strategy * @description TODO * @date 2022/2/28 12:36 */ @Service public class RequestService { public ResponseData verify(RequestDto requestDto) { String param1 = requestDto.getParam1(); String param2 = requestDto.getParam2(); if("1".equals(param1) && "2".equals(param2)){ return ResponseData.fail("500"); } return ResponseData.ok(); } public ResponseData testOne(RequestDto request){ String param1 = request.getParam1(); String param2 = request.getParam2(); System.out.println("param1:"+param1); System.out.println("param2:"+param2); return ResponseData.ok(request); } }
/** * @author *** * @title: TestOneService * @projectName strategy * @description TODO * @date 2022/2/28 13:12 */ @Service(ServiceConstant.TEST_ONE) public class TestOneService extends AbstractService<RequestDto,RequestDto>{ @Resource private RequestService requestService; @Override public ResponseData<?> handle(RequestDto request) throws Exception { return requestService.testOne(request); } }
6.util
/** * @author *** * @title: Context * @projectName strategy * @description TODO * @date 2022/2/28 12:47 */ @Data public class Context { /** * 版本号 */ private String version; /** * 服务类型 */ private String service; }
/** * @author *** * @title: ContextUtil * @projectName strategy * @description TODO * @date 2022/2/28 12:46 */ public class ContextUtil { private ContextUtil() { } private static final Logger LOGGER = LoggerFactory.getLogger(ContextUtil.class); private static final ThreadLocal<Context> THREAD_LOCAL = ThreadLocal.withInitial(() -> new Context()); public static Context getContext() { Context context = THREAD_LOCAL.get(); LOGGER.info("getContext:{}", context); return context; } public static void clear() { LOGGER.info("clear:{}", THREAD_LOCAL.get()); THREAD_LOCAL.remove(); } }
/** * 实体校验工具类 * */ public class ValidationUtil { private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); /** * 校验实体 * * @param obj * @param <T> * @return */ public static <T> ValidationResult validateEntity(T obj) { ValidationResult result = new ValidationResult(); Set<ConstraintViolation<T>> set = validator.validate(obj, Default.class); if (!CollectionUtils.isEmpty(set)) { result.setHasErrors(true); Map<String, String> errorMsg = new HashMap<String, String>(); for (ConstraintViolation<T> cv : set) { errorMsg.put(cv.getPropertyPath().toString(), cv.getMessage()); } result.setErrorMsg(errorMsg); } return result; } /** * 校验属性 * * @param obj * @param propertyName * @param <T> * @return */ public static <T> ValidationResult validateProperty(T obj, String propertyName) { ValidationResult result = new ValidationResult(); Set<ConstraintViolation<T>> set = validator.validateProperty(obj, propertyName, Default.class); if (!CollectionUtils.isEmpty(set)) { result.setHasErrors(true); Map<String, String> errorMsg = new HashMap<String, String>(); for (ConstraintViolation<T> cv : set) { errorMsg.put(propertyName, cv.getMessage()); } result.setErrorMsg(errorMsg); } return result; } }
7.写在最后
关于springboot中@NotBlank注解使用不生效问题
1)@NotBlank注解只能写在String类型
2)入参的时候是否加了@Valid注解
public String getUsername(@Valid User user){}
3)如果使用的是validation-api ,还需要依赖 hibernate-validator 库
<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.13.Final</version> </dependency>
4)使用JSON接收参数则需要自定义检验规则,详见【6.util.ValidationUtil 】,【4.controller.RequestController】