前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JAVA泛型类的使用

JAVA泛型类的使用

作者头像
小小明童鞋
发布2019-03-12 15:37:56
1.7K0
发布2019-03-12 15:37:56
举报
文章被收录于专栏:java系列博客java系列博客

首先说说我用到的应用场景:

需求描述:

在工作流(workflow)中,存在着各种各样的工作流程,这些流程呢有一些特征——1.流程基本信息相同 2.流程内容不同

在给前端写接口请求实体的时候,在我接手功能之前是将流程内容实体作为流程属性放在请求实体内,导致不同的流程要写不同的请求实体,违背了开闭原则。

我第一个想到的方案是泛型。

下面是方案——————————————————

流程实体(ApplyEntity ):

/**
 * Created by xmtx on 2018/9/8.
 */
public class ApplyEntity {
    /**
     * 流程id
     */
    private String applyId;
    /**
     * 流程名称
     */
    private String applyName;
    /**
     * 流程类型
     */
    private Integer applyType;
    /**
     * 流程基本信息
     */
    private String applyBaicInfo;


    public String getApplyId() {
        return applyId;
    }

    public void setApplyId(String applyId) {
        this.applyId = applyId;
    }

    public String getApplyName() {
        return applyName;
    }

    public void setApplyName(String applyName) {
        this.applyName = applyName;
    }

    public String getApplyBaicInfo() {
        return applyBaicInfo;
    }

    public void setApplyBaicInfo(String applyBaicInfo) {
        this.applyBaicInfo = applyBaicInfo;
    }

    public Integer getApplyType() {
        return applyType;
    }

    public void setApplyType(Integer applyType) {
        this.applyType = applyType;
    }

    @Override
    public String toString() {
        return "ApplyEntity{" +
                "applyId='" + applyId + '\'' +
                ", applyName='" + applyName + '\'' +
                ", applyType=" + applyType +
                ", applyBaicInfo='" + applyBaicInfo + '\'' +
                '}';
    }

流程内容 类型一(职位):

/**
 * 岗位信息
 * Created by xmtxon 2018/9/3.
 */
public class PostInfo extends BaseEntity{
    // 岗位编码
    private String postCode;
    // 岗位名称
    private String postName;

    public String getPostCode() {
        return postCode;
    }

    public void setPostCode(String postCode) {
        this.postCode = postCode;
    }

    public String getPostName() {
        return postName;
    }

    public void setPostName(String postName) {
        this.postName = postName;
    }

    @Override
    public String toString() {
        return "PostInfo{" +
                "postCode='" + postCode + '\'' +
                ", postName='" + postName + '\'' +
                '}';
    }

流程内容 类型二 (报表):

/**
 * @Author: xmtx
 * @Description: report
 * @Date: Created by xmtxon 2018/9/8.
 */
public class RptBaseDto {

    //报表Id
    private String reportId;
    //报表版本id
    private String versionId;

    public RptBaseDto() {
        // this is a construct
    }

    public RptBaseDto(String reportId, String versionId) {
        this.reportId = reportId;
        this.versionId = versionId;
    }

    public String getReportId() {
        return reportId;
    }

    public void setReportId(String reportId) {
        this.reportId = reportId;
    }

    public String getVersionId() {
        return versionId;
    }

    public void setVersionId(String versionId) {
        this.versionId = versionId;
    }

    /*@Override
    public String toString() {
        return reportId + '_' + versionId;
    }*/

}

请求参数 泛型类:

/**
 * Created by xmtx on 2018/9/8.
 */
public class ApplyRequest<T> extends ApplyEntity{

    /**
     * 泛型属性,作为流程内容
     */
    private T  applyContent;

    public T getApplyContent() {
        return applyContent;
    }

    public void setApplyContent(T applyContent) {
        this.applyContent = applyContent;
    }

    @Override
    public String toString() {
        return "ApplyRequest{" +
                "applyContent=" + applyContent +
                '}';
    }

到此为止,请求参数泛型类已经满足功能需求,我们有新增的流程,只需要创建新的流程内容实体即可。

下面要解决的是前后台参数序列化的问题:

我们先构造两种类型的请求参数:

  public static void main(String[] args) {

        //流程基本信息
        ApplyRequest applyRequest = new ApplyRequest();
        applyRequest.setApplyId("2333");
        applyRequest.setApplyName("applyName");
        applyRequest.setApplyType(1);
        applyRequest.setApplyBaicInfo("basic infomation");

        /**
         * 流程内容 类型一:岗位信息
         */
        PostInfo postInfo = new PostInfo();
        postInfo.setPostCode("postCode");
        postInfo.setPostName("postName");

        applyRequest.setApplyContent(postInfo);
        System.out.println("=============流程内容一:岗位================");
        System.out.println(JSON.toJSONString(applyRequest));

        /**
         * 流程内容 类型二 :报表信息
         */
        RptBaseDto reportEntity = new RptBaseDto();
        reportEntity.setReportId("reportId");
        reportEntity.setVersionId("versionid");
        applyRequest.setApplyType(2);
        applyRequest.setApplyContent(reportEntity);
        System.out.println("=============流程内容二:报表================");

        System.out.println(JSON.toJSONString(applyRequest));


    }

得到的结果如下:

=============流程内容一:岗位================
{"applyBaicInfo":"basic infomation","applyContent":{"id":0,"postCode":"postCode","postName":"postName"},"applyId":"2333","applyName":"applyName","applyType":1}
=============流程内容二:报表================
{"applyBaicInfo":"basic infomation","applyContent":{"reportId":"reportId","versionId":"versionid"},"applyId":"2333","applyName":"applyName","applyType":2}

编写post请求方法,在wagger或者postman中模拟post请求。

 @RequestMapping(value = "/testFX", method = RequestMethod.POST)
    public ResponseObject testFX(@RequestBody ApplyRequest applyRequest) {
        System.out.println(JSON.toJSONString(applyRequest));
        Integer applyType = applyRequest.getApplyType();
        String instance = JSON.toJSONString(applyRequest);
        switch (applyType){
            case 1:
                ApplyRequest<PostInfo> applyRequest1 = applyRequest;
                PostInfo postInfo = applyRequest1.getApplyContent();
                return new ResponseObject(JSON.toJSONString(postInfo));
            case 2:
                ApplyRequest<RptBaseDto> applyRequest2 = applyRequest;
                RptBaseDto rptBaseDto = applyRequest2.getApplyContent();
                return new ResponseObject(JSON.toJSONString(rptBaseDto));
            default:
                return null;
        }
    }

测试方法,于是我们得到了如下异常:

{
  "statusCode": "100000",
  "msg": "系统未知异常",
  "error": "java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.suning.drp.common.applicationcenter.bean.PostInfo"
}

于是乎,我们进入debug模式:

我们看到参数被序列化成LinkedHashMap[],看来Spring MVC 的 @RequestBody 并不能将泛型参数反序列化。

我们于是找google爸爸(Casting LinkedHashMap to Complex Object)。

解决方案如下:

POJO pojo = mapper.convertValue(singleObject, POJO.class);
// or:
List<POJO> pojos = mapper.convertValue(listOfObjects, new TypeReference<List<POJO>>() { });

于是改变代码为:

 @RequestMapping(value = "/testFX", method = RequestMethod.POST)
    public ResponseObject testFX(@RequestBody ApplyRequest applyRequest) {
        System.out.println(JSON.toJSONString(applyRequest));
        Integer applyType = applyRequest.getApplyType();
        String instance = JSON.toJSONString(applyRequest);
        switch (applyType){
            case 1:
                PostInfo postInfo = mapper.convertValue(applyRequest.getApplyContent(), PostInfo.class);
                return new ResponseObject(JSON.toJSONString(postInfo));
            case 2:
                ApplyRequest<RptBaseDto> applyRequest2 = applyRequest;
                RptBaseDto rptBaseDto = applyRequest2.getApplyContent();
                return new ResponseObject(JSON.toJSONString(rptBaseDto));
            default:
                return null;
        }
    }

但得到的结果却不是我们想要的:

问题在哪里呢,我们稍后再分析,先给出解决方案:

我们先把请求参数转换为JSONString ,然后再转换为泛型对实体(这样就完美解决了fastjson的不足):

@RequestMapping(value = "/testFX", method = RequestMethod.POST)
public ResponseObject testFX(@RequestBody ApplyRequest applyRequest) {
    Integer applyType = applyRequest.getApplyType();
    String instance = JSON.toJSONString(applyRequest);

    switch (applyType) {
        case 1:
            ApplyRequest<PostInfo> postInfo1 = JSON.parseObject(instance, ApplyRequest.class);
            //do something
            return new ResponseObject(JSON.toJSONString(postInfo1));
        case 2:
            ApplyRequest<RptBaseDto> applyRequest2 = JSON.parseObject(instance, ApplyRequest.class);
            //do something
            return new ResponseObject(JSON.toJSONString(applyRequest2));
        default:
           return new ResponseObject("error");
    }
}

关于泛型的其它应用场景可参考csdn的这篇(https://blog.csdn.net/u011240877/article/details/53545041),谢谢您的阅读。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018/09/08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云 BI
腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档