springboot,请求model中有一个抽象成员,如何配置使其正确实例化?

背景:
接收客户端请求的model(Request)中,有一个成员变量f,对不同的业务类型(type),需要实例化成不同的实例(A or B)。

    public abstract class Father {
    }
    public class A extends Father {
        private String a1;
        private String a2;
    }
    public class B extends Father {
        private String b1;
        private String b2;
    }
    public class Request {
        private Father f;
        private String type; // 根据不通的type,将f实例化成A或B
    }

目前的解决办法是,在请求model中,直接用一个JSONObject来接收,后面再转化成具体的实例。

public class Request {
    private JSONObject f;
    private String type; // 根据不通的type,将f实例化成A或B
}

请问,springboot里需要怎样配置(或者说,要怎么做),可以省去json->A的这一段代码?我在后面的业务中,直接强制转换成具体的实例。
或者说,有没看有其他的更好的解决方案,来处理类似的问题?

感谢各位大佬不吝赐教。。

阅读 3.3k
3 个回答

springboot本身没办法处理吧,因为你这算是业务逻辑了。

如果这种情况出现很多可以考虑用拦截器intercepter,在拦截器根据type判断然后再封装model,这样在方法里就能获取到对应的A或B了

如果是根据请求参数来决定,那么可以写一个自定义的参数解析器:

@Component
public class FatherResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter (MethodParameter parameter) {
        // 看你是需要用注解来区分还是直接用 class 来判断
    }
    @Override
    public Object resolveArgument (MethodParameter parameter, ModelAndViewContainer mavContainer,
                                   NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        String type = // 解析出 type
        Father instance = JSONObject.parseObject(request.getParameter(parameter.getParameterName()), 根据 type 放置目标实现类.class);
        return instance;
    }
}
JSONObject#parseObject 使用的是 fast-json 实现。

使用时:

@ResponseBody
public ResponseData func (Father instance) {
    // ...
}

具体使用方式需要你去了解 HandlerMethodArgumentResolver 了。


那你是依靠什么来判断需要转换成哪种实现类呢?

观点和 @zzzzbw 类似,你这属于业务的逻辑框架不会支持的那么好,可以自己写逻辑处理。
其次个人想法,你这个设计有一些奇怪,如果他们是两个对象,封装成两个接口,两个实体就好了。如果是一个父类的派生类,只是 type 不同,可以直接放在一个对象使用,同时数据库也可以用一个表。
所以你可以考虑一下本身的设计问题。


小编为订阅号「码匠笔记」号主,先后就职于 ThoughtWorks、阿里巴巴等互联网公司的经验分享,包含但不限于 JAVA、并发编程、性能优化、架构设计、小程序、开源软件等。有兴趣可以关注一波,一起学习、讨论。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题