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>

三、项目结构图

springboot根据参数,调用不同的service接口(策略模式)

四、项目具体内容

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】

 

上一篇:分布式部署(不同服务存放不同服务器)


下一篇:C++运行外部exe并判断exe返回值