Spring責(zé)任鏈模式使用實(shí)例講解
前言
在工作中會(huì)存在這種情況某些業(yè)務(wù)場(chǎng)景會(huì)對(duì)一份數(shù)據(jù)的屬性進(jìn)行多次設(shè)置,這種情況在傳統(tǒng)的代碼風(fēng)格就是在一個(gè)方法中對(duì)應(yīng)屬性進(jìn)行依次的set這種編碼會(huì)在以后的業(yè)務(wù)迭代中造成很大的耦合,代碼復(fù)用程度很低,后期維護(hù)成本會(huì)變大,這個(gè)時(shí)候就可以使用責(zé)任鏈模式對(duì)業(yè)務(wù)set這個(gè)步驟進(jìn)行拆分做到可插拔式,從而做到減少迭代成本和維護(hù)成本對(duì)以后接手項(xiàng)目的同事友好
開(kāi)始編寫(xiě)案例
我這里以電商項(xiàng)目中的商品屬性設(shè)置為例productModel
1.開(kāi)始搭建一個(gè)spring boot 項(xiàng)目
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>spring-batch</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.創(chuàng)建對(duì)應(yīng)案例數(shù)據(jù)
package com.wym.pojo;
import lombok.Data;
/**
* 商品基礎(chǔ)模型
*/
@Data
public class ProductModel {
private Integer id;
private String productCode;
private String productName;
private String productTitle;
private String productTag;
private String productRegion;
private Integer stockNumber;
private String brandName;
}
package com.wym.pojo;
import lombok.Data;
/**
* 商品附帶參數(shù) 方便后期設(shè)置參數(shù)
*/
@Data
public class ProductParamModel {
private String vendorCode;
}
3.創(chuàng)建責(zé)任鏈處理器
創(chuàng)建一個(gè)處理接口,子類根據(jù)自己的業(yè)務(wù)特色去實(shí)現(xiàn)接口,對(duì)數(shù)據(jù)進(jìn)行加工
/**
* 商品處理
*/
public interface ProductPostProcessor {
/**
* 商品加工
* @param productModelList 商品
* @param productParamModel 處理參數(shù)
*/
void productDataProcess(List<? extends ProductModel> productModelList, ProductParamModel productParamModel);
}
這里我設(shè)置3個(gè)常用的商品處理
/**
* 商品品牌設(shè)置
*/
@Component
@Slf4j
@Order(1) //為了后期方便業(yè)務(wù)操作順序編排
public class ProductBrandMappingPostProcessor implements ProductPostProcessor {
@Override
public void productDataProcess(List<? extends ProductModel> productModelList, ProductParamModel productParamModel) {
log.error("進(jìn)入商品品牌設(shè)置");
}
}
/**
* 商品映射設(shè)置
*/
@Component
@Slf4j
@Order(2)
public class ProductCodeMappingPostProcessor implements ProductPostProcessor {
@Override
public void productDataProcess(List<? extends ProductModel> productModelList, ProductParamModel productParamModel) {
log.error("進(jìn)入商品映射設(shè)置");
}
}
/**
* 商品庫(kù)存設(shè)置
*/
@Slf4j
@Component
@Order(3)
public class ProductStockNumberPostProcessor implements ProductPostProcessor {
@Override
public void productDataProcess(List<? extends ProductModel> productModelList, ProductParamModel productParamModel) {
log.error("進(jìn)入商品庫(kù)存設(shè)置");
}
}
這個(gè)時(shí)候就已經(jīng)創(chuàng)建好了責(zé)任鏈處理器,接下來(lái)就是開(kāi)始業(yè)務(wù)調(diào)用
4.創(chuàng)建mvc調(diào)用
controller
@RequestMapping("/test")
@Slf4j
@RestController
public class ProductController {
@Autowired
private ProductServer productServer;
@GetMapping("/query")
public String queryProduct() {
productServer.queryProduct();
return "成功";
}
}
server
public interface ProductServer {
/**
* 查詢商品
* @return List<ProductModel>
*/
public List<ProductModel> queryProduct();
}
impl 這里就是核心點(diǎn)如何操作這個(gè)責(zé)任鏈 ApplicationListener 這個(gè)取獲取容器中的處理器,并排序
@Service
@Slf4j
public class ProductServerImpl implements ProductServer, ApplicationListener<ContextRefreshedEvent> {
private static List<ProductPostProcessor> productPostProcessorList;
/**
* 處理排序
*
* @param contextRefreshedEvent 環(huán)
* @return
*/
private List<ProductPostProcessor> getProductPostProcesser(ContextRefreshedEvent contextRefreshedEvent) {
//子容器加載完畢不進(jìn)這個(gè)邏輯
if (contextRefreshedEvent.getApplicationContext().getParent() == null) {
//監(jiān)聽(tīng)容器加載完畢
Map<String, ProductPostProcessor> beansOfType = contextRefreshedEvent.getApplicationContext().getBeansOfType(ProductPostProcessor.class);
log.error("商品后置處理器注入");
List<ProductPostProcessor> postProcessList = new ArrayList<>(beansOfType.values());
postProcessList.sort((a, b) -> {
Order aOrder = AnnotationUtils.findAnnotation(a.getClass(), Order.class);
Order bOrder = AnnotationUtils.findAnnotation(b.getClass(), Order.class);
if (aOrder == null && bOrder == null) {
return 0;
}
if (aOrder == null) {
return 1;
}
if (bOrder == null) {
return -1;
}
return aOrder.value() - bOrder.value();
}
);
return postProcessList;
}
return null;
}
@Override public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
List<ProductPostProcessor> postProcessor = getProductPostProcesser(contextRefreshedEvent);
if (!CollectionUtils.isEmpty(postProcessor))
{ productPostProcessorList = postProcessor; }
}
@Override public List<ProductModel> queryProduct()
{ ProductModel productModel = new ProductModel(); productModel.setId(0);
productModel.setProductCode("");
productModel.setProductName("");
productModel.setProductTitle("");
productModel.setProductTag("");
productModel.setProductRegion("");
productModel.setStockNumber(0);
productModel.setBrandName("");
ProductParamModel productParamModel = new ProductParamModel(); productParamModel.setVendorCode("1231");
productPostProcessorList.forEach(item -> item.productDataProcess(Arrays.asList(productModel), productParamModel)); return null; }
}
進(jìn)行驗(yàn)證
調(diào)用 http://localhost:8080/test/query 就會(huì)在控制臺(tái)中打印出
2023-01-09 11:07:42.178 ERROR 25096 --- [nio-8080-exec-2] c.w.p.i.ProductBrandMappingPostProcessor : 進(jìn)入商品品牌設(shè)置
2023-01-09 11:07:42.178 ERROR 25096 --- [nio-8080-exec-2] c.w.p.i.ProductCodeMappingPostProcessor : 進(jìn)入商品映射設(shè)置
2023-01-09 11:07:42.179 ERROR 25096 --- [nio-8080-exec-2] c.w.p.i.ProductStockNumberPostProcessor : 進(jìn)入商品庫(kù)存設(shè)置
這樣就做到了業(yè)務(wù)分離對(duì)后期的維護(hù)有幫助
到此這篇關(guān)于Spring責(zé)任鏈模式使用實(shí)例講解的文章就介紹到這了,更多相關(guān)Spring責(zé)任鏈模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringSecurity從數(shù)據(jù)庫(kù)中獲取用戶信息進(jìn)行驗(yàn)證的案例詳解
這篇文章主要介紹了SpringSecurity從數(shù)據(jù)庫(kù)中獲取用戶信息進(jìn)行驗(yàn)證的案例詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01
SpringBoot整合screw實(shí)現(xiàn)自動(dòng)生成數(shù)據(jù)庫(kù)設(shè)計(jì)文檔
使用navicat工作的話,導(dǎo)出的格式是excel不符合格式,還得自己整理。所以本文將用screw工具包,整合到springboot的項(xiàng)目中便可以自動(dòng)生成數(shù)據(jù)庫(kù)設(shè)計(jì)文檔,非常方便,下面就分享一下教程2022-11-11
導(dǎo)入項(xiàng)目出現(xiàn)Java多個(gè)工程相互引用異常A cycle was detected in the build path o
今天小編就為大家分享一篇關(guān)于導(dǎo)入項(xiàng)目出現(xiàn)Java多個(gè)工程相互引用異常A cycle was detected in the build path of project的解決辦法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12
Java中try-catch的使用及注意細(xì)節(jié)
現(xiàn)在有很多的語(yǔ)言都支持try-catch,比如常見(jiàn)的就是c++,java等,這篇文章主要給大家介紹了關(guān)于Java中try-catch的使用及注意細(xì)節(jié)的相關(guān)資料,文中通過(guò)圖文以及實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06
java 較大數(shù)據(jù)量取差集,list.removeAll性能優(yōu)化詳解
這篇文章主要介紹了java 較大數(shù)據(jù)量取差集,list.removeAll性能優(yōu)化詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
使用Java實(shí)現(xiàn)查找并移除字符串中的Emoji
Emoji 實(shí)際上是 UTF-8 (Unicode) 字符集上的特殊字符,這篇文章主要介紹了如何使用Java實(shí)現(xiàn)查找并移除字符串中的Emoji,感興趣的可以了解下2024-03-03
基于多線程并發(fā)的常見(jiàn)問(wèn)題(詳解)
下面小編就為大家?guī)?lái)一篇基于多線程并發(fā)的常見(jiàn)問(wèn)題(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
javaweb啟動(dòng)時(shí)啟動(dòng)socket服務(wù)端代碼實(shí)現(xiàn)
這篇文章主要介紹了javaweb啟動(dòng)時(shí)啟動(dòng)socket服務(wù)端代碼實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
Springboot與vue實(shí)現(xiàn)文件導(dǎo)入方法具體介紹
文件導(dǎo)入時(shí)大多數(shù)項(xiàng)目無(wú)法回避的問(wèn)題,這兩天深入學(xué)習(xí)了文件導(dǎo)入,在這里進(jìn)行記錄,使用到的技術(shù)是Springboot+Vue,前端組件使用el-upload2023-02-02

