1. 程式人生 > 其它 >spring boot 基於jackson 多型資料型別處理簡化rest api 開發

spring boot 基於jackson 多型資料型別處理簡化rest api 開發

開發好可擴充套件的rest api 是一門技術,同時開發靈活擴充套件的rest api 也是比較費事的,很多時候
我們為了業務開發了特別多的rest api,造成系統的維護以及使用都很複雜,graphql 是一種不錯的
解決方法(同時業界也有類似通用查詢處理),以下是一個簡單的基於jackson 多型資料處理簡單
開發的一個玩法,可以參考

核心說明

實際上是基於約定的,包含了實體處理(基於jackson多型處理),以及服務層處理(很多時候我們是需要包含依賴的ioc)

專案準備

  • 專案結構
    就是一個標準的spring boot maven 專案
 
├── pom.xml
└── src
    ├── main
    ├── java
    └── com
    └── dalong
    └── jacksonapp
    ├── ContextUtil.java
    ├── ExceptionHandlers.java
    ├── FirstMyService.java
    ├── FirstUser.java
    ├── JacksonappApplication.java
    ├── MyApi.java
    ├── MyService.java
    ├── MyUser.java
    ├── SecondMyService.java
    └── SecondUser.java
    └── resources
    ├── application.properties
    ├── static
    └── templates
  • pom.xml
    基於starter生成的,主要就是一個web 專案
  • jackson 實體定義說明
 
// 基於JsonTypeInfo 定義型別
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
public interface  MyUser<T> {
    String token(); // 實體demo 方法
    T instance(); // 返回實體型別
    Class serviceType(); // 方便實體需要的服務型別定義(比如不同實體會有不同的service,dao層。。。。)
}

子類
FirstUser

 
@Data
public class FirstUser implements MyUser<FirstUser>{
    private String name;
    private int age;
    @Override
    public String token() {
        return String.format("FirstUser-%d-%s",this.age,this.name);
    }
 
    @Override
    public FirstUser instance() {
        return this;
    }
 
    @Override
    public Class serviceType() {
        return FirstMyService.class;  // 使用FirstMyService服務處理bean
    }
}

SecondUser

@Data
public class SecondUser implements MyUser<SecondUser>{
    private String name;
    private int age;
 
    @Override
    public String token() {
        return String.format("SecondUser-%d-%s",this.age,this.name);
    }
 
    @Override
    public SecondUser instance() {
        return this;
    }
 
    @Override
    public Class serviceType() {
        return SecondMyService.class; // 使用SecondMyService 服務處理bean
    }
}

實體的服務處理契約(處理具體實體的service)

public interface MyService<T extends  MyUser> {
     default String demo(T t){
      return   t.token();
    }
}
   

FirstUser 的服務處理實現

@Service
public class FirstMyService  implements  MyService<FirstUser> {
}

SecondUser 的service

@Service
public class SecondMyService  implements  MyService<SecondUser> {
}

服務工具類ContextUtil,方便基於bean 型別獲取特定實體的服務處理bean

public class ContextUtil {
    public static  <T extends  MyService> T getBean(Class<T> cls) {
       return JacksonappApplication.applicationContext.getBean(cls);
    }
}

通用服務api 處理入口

@RestController
public class MyApi {
    @RequestMapping(value = {"/demoapp"})
    public  Object demo(@RequestBody MyUser myUser){
      // 通過實體可以找到servie,然後基於service 的方法處理對於實體的業務邏輯
       return ContextUtil.getBean(myUser.serviceType()).demo(myUser);
    }
}

spring boot 入口
通過CommandLineRunner 進行資料型別的註冊,沒有直接使用JsonSubTypes 註解是因為直接基於直接的話,程式碼就固化了
使用CommandLineRunner的好處是可以靈活的擴充套件服務(比如多模組,外掛化處理。。。)

 
@SpringBootApplication
public class JacksonappApplication {
 
    public static ApplicationContext applicationContext;
    @Bean
    public CommandLineRunner commandLineRunner(ObjectMapper objectMapper){
        return args -> {
            objectMapper.registerSubtypes(new NamedType(FirstUser.class, "first"));
            objectMapper.registerSubtypes(new NamedType(SecondUser.class, "second"));
        };
    }
    public static void main(String[] args) {
        applicationContext= SpringApplication.run(JacksonappApplication.class, args);
    }
 
}

使用效果

  • 訪問first 型別的
curl --location --request POST 'http://localhost:8080/demoapp' \
--header 'Content-Type: application/json' \
--data-raw '{
    "type":"first",
    "age":333,
    "name":"dalong"
    }'

效果

 

 

  • 訪問second 型別
curl --location --request POST 'http://localhost:8080/demoapp' \
--header 'Content-Type: application/json' \
--data-raw '{
    "type":"second",
    "age":333,
    "name":"dalong"
    }'

 

 

說明

以上是一個簡單的實踐玩法,我們基於此可以實現一個入口靈活的rest api 處理,比如適合post 型別的處理(比如graphql 就是完全基於post 進行資料處理的,包裝了查詢以及修改資料),完整程式碼可以參考github 程式碼

參考資料

https://www.cnblogs.com/rongfengliang/p/15999843.html
https://github.com/rongfengliang/spring-boot-jackson