Implementing Device Modeling (Thing Model) in KCloud-Platform-IoT: Clean Architecture Guide
KCloud-Platform-IoT implements device modeling through a four-layer clean architecture separating Domain, Application, Infrastructure, and Client concerns, using ThingModelE as the core entity with MyBatis-Plus persistence and bidirectional DTO conversion.
The Thing Model (device-model) serves as the central entity describing device data points, events, and commands in the koushenhai/kcloud-platform-iot repository. This implementation demonstrates how to structure complex IoT domain logic using Spring Boot, MyBatis-Plus, and strict layer isolation. Understanding this architecture allows developers to extend device capabilities while maintaining testable, maintainable code boundaries.
Clean Architecture Layers Overview
The implementation strictly follows clean architecture principles with four distinct layers. Each layer has specific responsibilities and dependency directions pointing inward toward the Domain.
- Domain: Encapsulates business rules, validation, and entity definitions in
ThingModelE - Application: Orchestrates use-cases through
ThingModelDomainService - Infrastructure: Handles MySQL persistence via MyBatis-Plus and entity conversion
- Client: Defines API contracts with command objects like
ThingModelSaveCmd
This structure ensures that business logic remains independent of storage mechanisms and transport protocols.
Domain Layer: Entities and Validation
The Domain layer contains the pure business logic for device modeling, isolated from external frameworks.
ThingModelE Entity Definition
The ThingModelE class in laokou-service/laokou-iot/laokou-iot-domain/src/main/java/org/laokou/iot/thingModel/model/ThingModelE.java represents the logical state of a device model:
public class ThingModelE {
private Long id;
private String name;
private String code;
private String dataType; // integer, string, decimal, boolean
private Integer category; // 1=属性, 2=事件
private String type; // read/write/report
private Integer sort;
private String specs; // rule description
private String remark;
private OperateType operateType; // SAVE or MODIFY
public void checkThingModelParam() throws Exception {
// validation hook implementation
}
}
Validation and Factory Patterns
ThingModelParamValidator enforces uniqueness constraints on the code and name fields during insertion and ensures required fields are present. Located in laokou-service/laokou-iot/laokou-iot-app/src/main/java/org/laokou/iot/thingModel/service/validator/ThingModelParamValidator.java, this validator prevents duplicate device model definitions.
ThingModelFactory provides Spring-managed prototype instantiation of ThingModelE entities, located in the domain module's factory package. This pattern decouples entity creation from the application layer.
Application Layer: Use Case Orchestration
The ThingModelDomainService class in laokou-service/laokou-iot/laokou-iot-domain/src/main/java/org/laokou/iot/thingModel/ability/ThingModelDomainService.java coordinates all Thing Model operations. It validates entities using ThingModelParamValidator before delegating to the infrastructure gateway.
Key methods include:
createThingModel(ThingModelE entity)– Handles new device model creationupdateThingModel(ThingModelE entity)– Manages modification workflowsdeleteThingModel(Long[] ids)– Executes batch deletion
This service acts as the transactional boundary, ensuring business rules execute atomically before persistence.
Infrastructure Layer: Persistence and Conversion
Infrastructure concerns are isolated in the laokou-iot-infrastructure module, implementing the repository pattern through MyBatis-Plus.
Data Objects and Database Mapping
ThingModelDO in laokou-service/laokou-iot/laokou-iot-infrastructure/src/main/java/org/laokou/iot/thingModel/gatewayimpl/database/dataobject/ThingModelDO.java maps directly to the iot_thing_model table. The corresponding ThingModelMapper interface extends MyBatis-Plus BaseMapper for CRUD operations.
Gateway Implementation
The ThingModelGateway interface defines the port used by the domain layer, while ThingModelGatewayImpl in gatewayimpl/ThingModelGatewayImpl.java provides the concrete implementation. This adapter converts domain entities to data objects and orchestrates database transactions through ThingModelMapper.insert().
Type Conversion Strategy
ThingModelConvertor handles bidirectional mapping between three representations:
ThingModelE(Domain entity)ThingModelDO(Infrastructure data object)ThingModelCO(Client presentation object)
Located in gatewayimpl/convertor/ThingModelConvertor.java, this class ensures type safety when crossing architectural boundaries.
Client Layer: API Contracts
The Client layer defines the external API surface through command objects and service interfaces.
ThingModelsServiceI in laokou-service/laokou-iot/laokou-iot-client/src/main/java/org/laokou/iot/thingModel/api/ThingModelsServiceI.java declares the service contract implemented by HTTP controllers.
Command classes carry request data:
ThingModelSaveCmd– Create new model requestsThingModelModifyCmd– Update existing modelsThingModelRemoveCmd– Delete by ID arraysThingModelPageQry– Paginated queries
ThingModelCO serves as the client-side representation for API responses, located in the dto/clientobject package.
Practical Implementation Example
Below is a complete controller implementation demonstrating the end-to-end flow for creating a Thing Model:
@RestController
@RequestMapping("/thing-model")
public class ThingModelController {
@Autowired
private ThingModelDomainService thingModelDomainService;
@PostMapping
public Result<Long> create(@RequestBody ThingModelSaveCmd cmd) throws Exception {
// Convert command to domain entity using infrastructure convertor
ThingModelE entity = ThingModelConvertor.toEntity(cmd.getCo(), true);
// Execute domain logic with validation and persistence
thingModelDomainService.createThingModel(entity);
// Return generated primary key assigned by MyBatis-Plus
return Result.success(entity.getPrimaryKey());
}
}
The execution flow follows this sequence:
- API Layer receives
ThingModelSaveCmdextendingCommonCommand ThingModelConvertor.toEntity()transforms the command intoThingModelEThingModelDomainService.createThingModel()validates viaThingModelParamValidatorand delegates to the gatewayThingModelGatewayImplconverts toThingModelDOand inserts viaThingModelMapper
Update operations follow an identical pattern using ThingModelModifyCmd and updateThingModel(), while deletion accepts ID arrays through deleteThingModel().
Summary
The Thing Model implementation in KCloud-Platform-IoT demonstrates production-ready clean architecture for IoT device management:
- Domain isolation keeps business rules in
ThingModelEandThingModelParamValidatorindependent of frameworks - Application orchestration through
ThingModelDomainServiceprovides clear use-case boundaries - Infrastructure abstraction via
ThingModelGatewayImpland MyBatis-Plus enables swappable persistence strategies - Client contracts using command objects (
ThingModelSaveCmd,ThingModelModifyCmd) ensure API stability
The conversion flow between ThingModelCO, ThingModelE, and ThingModelDO maintains type safety across all four architectural layers.
Frequently Asked Questions
How does KCloud-Platform-IoT validate Thing Model uniqueness?
The platform validates uniqueness through ThingModelParamValidator in the Application layer, which checks that the combination of code and name fields does not already exist in the iot_thing_model table before allowing insertion. This prevents duplicate device model definitions while keeping validation logic out of the infrastructure layer.
What database table stores the Thing Model entities?
Thing Model data persists to the iot_thing_model table via ThingModelDO and ThingModelMapper in the Infrastructure layer. The implementation uses MyBatis-Plus for CRUD operations, with the gateway pattern abstracting database specifics from the Domain layer.
Can the Thing Model support custom data types beyond integer, string, decimal, and boolean?
Yes. While the reference implementation includes standard IoT data types (integer, string, decimal, boolean) in the dataType field of ThingModelE, the domain model is extensible. Developers can modify the validation logic in checkThingModelParam() and update the database schema to support additional complex types or structured specifications within the specs JSON field.
How does the architecture handle the conversion between API requests and database entities?
The architecture uses ThingModelConvertor to handle bidirectional mapping between three representations: ThingModelCO (Client/API), ThingModelE (Domain), and ThingModelDO (Infrastructure). This conversion happens at the architectural boundaries—when entering the Domain from the Client layer and when persisting to the database through the Gateway implementation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →