Pesquisa prática sobre a implementação da arquitetura hierárquica de cinco dimensões e nove níveis do projeto Spring Boot - atualizada continuamente

código var = “12433d02-b242-4fd2-937d-750761a365ea”

Observação: esta postagem do blog refere-se às ideias de alguns blogueiros técnicos e está sendo continuamente resumida e atualizada com base em conteúdo prático e código.

Cinco dimensões de camadas: prática de camadas de engenharia do SpringBoot

1 Pensamento hierárquico

Existe um ditado na área de informática: Qualquer problema em um computador pode ser resolvido adicionando uma camada virtual. Esta frase reflete a importância do pensamento em camadas, que também se aplica à arquitetura de engenharia Java.

A vantagem das camadas é que cada camada se concentra apenas no trabalho de sua própria camada. Isso pode ser comparado ao princípio de responsabilidade única dos padrões de design ou ao princípio da vantagem comparativa em economia. Cada camada faz apenas o que é melhor.

A desvantagem da estratificação é que, ao comunicar-se entre camadas, é necessário um adaptador para traduzir informações que possam ser compreendidas por esta camada ou pela camada inferior, e o custo da comunicação aumenta.

Acho que as camadas de engenharia precisam ser pensadas a partir de cinco dimensões:

(1) Único

Cada camada lida apenas com um tipo de coisa, satisfazendo o princípio da responsabilidade única.

(2) Redução de ruído

As informações são transmitidas em cada camada para atender ao princípio do conhecimento mínimo e apenas as informações necessárias são transmitidas à camada inferior.

(3) Adaptação

Cada camada precisa de um adaptador para traduzir as informações em informações que possam ser compreendidas por esta camada ou pela camada inferior.

(4) Negócios

Os objetos de negócios podem integrar a lógica de negócios, como usar o modelo de congestionamento para integrar os negócios

(5) Dados

Mantenha os objetos de dados tão puros quanto possível e tente não agregar negócios

1.2 Estrutura de nove camadas

Resumindo, o projeto SpringBoot pode ser dividido em nove camadas:

  • Camada de ferramenta: util
  • Camada de integração: integração
  • Camada base: infraestrutura
  • Camada de serviço: serviço
  • Camada de domínio: domínio
  • Camada de fachada: fachada
  • Camada de controle: controlador
  • Cliente: cliente
  • Camada de inicialização: inicialização

2 Explicação detalhada das camadas

Crie o projeto de teste user-demo-service:

user-demo-service
-user-demo-service-boot
-user-demo-service-client
-user-demo-service-controller
-user-demo-service-domain
-user-demo-service-facade
-user-demo-service-infrastructure
-user-demo-service-integration
-user-demo-service-service
-user-demo-service-util

2.1 A
camada de ferramenta util carrega o código da ferramenta

Não depende de outros módulos deste projeto

Confie apenas em alguns kits de ferramentas comuns

user-demo-service-util
-/src/main/java
-date
-DateUtil.java
-json
-JSONUtil.java
-validate
-BizValidator.java

2.2
O núcleo da camada base da infraestrutura é transportar o acesso aos dados, e os objetos da entidade são transportados nesta camada.

2.2.1 Estrutura do projeto
A camada de código é dividida em duas áreas:

jogador: jogador
jogo: competição
Cada campo possui dois subpacotes:

entity
mapper
user-demo-service-infrastructure
-/src/main/java
-player
-entity
-PlayerEntity.java
-mapper
-PlayerEntityMapper.java
-game
-entity
-GameEntity.java
-mapper
-GameEntityMapper.java
-/src/main/resources
-mybatis
-sqlmappers
-gameEntityMappler.xml
-playerEntityMapper.xml

Copiar código

2.2.2 Dependências entre este projeto

infraestrutura depende apenas de módulos de ferramentas

<dependency>
    <groupId>com.test.javafront</groupId>
    <artifactId>user-demo-service-util</artifactId>
</dependency>

2.2.3 Código principal

Crie uma tabela de dados do atleta:

CREATE TABLE `player` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
    `player_id` varchar(256) NOT NULL COMMENT '运动员编号',
    `player_name` varchar(256) NOT NULL COMMENT '运动员名称',
    `height` int(11) NOT NULL COMMENT '身高',
    `weight` int(11) NOT NULL COMMENT '体重',
    `game_performance` text COMMENT '最近一场比赛表现',
    `creator` varchar(256) NOT NULL COMMENT '创建人',
    `updator` varchar(256) NOT NULL COMMENT '修改人',
    `create_time` datetime NOT NULL COMMENT '创建时间',
    `update_time` datetime NOT NULL COMMENT '修改时间',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

O objeto da entidade atleta e o campo gamePerformance são armazenados no banco de dados como strings. Isso reflete que a camada de dados deve ser a mais pura possível e não deve integrar muitos negócios. A tarefa de análise deve ser colocada na camada de negócios:

public class PlayerEntity {
    private Long id;
    private String playerId;
    private String playerName;
    private Integer height;
    private Integer weight;
    private String creator;
    private String updator;
    private Date createTime;
    private Date updateTime;
    private String gamePerformance;
}

Objeto Mapeador de Atleta:

@Repository
public interface PlayerEntityMapper {
    int insert(PlayerEntity record);
    int updateById(PlayerEntity record);
    PlayerEntity selectById(@Param("playerId") String playerId);
}

Domínio 2.3

2.3.1 Descrição do conceito

A camada de domínio é o conceito por trás do aumento da popularidade do DDD

A camada de domínio pode ser entendida por meio de três conjuntos de comparações

Objetos de domínio versus objetos de dados
Objetos de domínio versus objetos de negócios
Camada de domínio versus camada de negócios

(1) Objetos de domínio VS objetos de dados

Mantenha os campos dos objetos de dados tão puros quanto possível e use tipos básicos

public class PlayerEntity {
    private Long id;
    private String playerId;
    private String playerName;
    private Integer height;
    private Integer weight;
    private String creator;
    private String updator;
    private Date createTime;
    private Date updateTime;
    private String gamePerformance;
}

Tome o objeto do campo de resultado da consulta como exemplo

Os objetos de domínio precisam refletir o significado do negócio

public class PlayerQueryResultDomain {
    private String playerId;
    private String playerName;
    private Integer height;
    private Integer weight;
    private GamePerformanceVO gamePerformance;
}

public class GamePerformanceVO {
    // 跑动距离
    private Double runDistance;
    // 传球成功率
    private Double passSuccess;
    // 进球数
    private Integer scoreNum;
}

(2) Objetos de domínio versus objetos de negócios

Os objetos de negócios também refletem negócios. Qual é a diferença entre objetos de domínio e objetos de negócios? Uma das maiores diferenças é que os objetos de domínio utilizam o modelo de congestionamento para agregar negócios.

Novos objetos de negócios para atletas:

public class PlayerCreateBO {
    private String playerName;
    private Integer height;
    private Integer weight;
    private GamePerformanceVO gamePerformance;
    private MaintainCreateVO maintainInfo;
}

Novos objetos de campo para atletas:

public class PlayerCreateDomain implements BizValidator {
private String playerName;
private Integer height;
private Integer weight;
private GamePerformanceVO gamePerformance;
private MaintainCreateVO maintainInfo;

    @Override
    public void validate() {
        if (StringUtils.isEmpty(playerName)) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (null == height) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (height > 300) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (null == weight) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (null != gamePerformance) {
            gamePerformance.validate();
        }
        if (null == maintainInfo) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        maintainInfo.validate();
    }
}

(3) Camada de domínio VS camada de negócios

Tanto a camada de domínio quanto a camada de negócios incluem empresas. O relacionamento entre os dois não é um substituto, mas sim um relacionamento complementar. A camada de negócios pode combinar negócios em diferentes campos de maneira mais flexível e pode adicionar controles como controle de fluxo, monitoramento, logs, permissões e bloqueios distribuídos. Possui funções mais ricas que a camada de domínio.

2.3.2 Estrutura do projeto

A camada de código é dividida em duas áreas:

player:运动员
game:比赛

Cada domínio possui três subpacotes:

domain:领域对象
event:领域事件
vo:值对象
user-demo-service-domain
-/src/main/java
-base
-domain
-BaseDomain.java
-event
-BaseEvent.java
-vo
-BaseVO.java
-MaintainCreateVO.java
-MaintainUpdateVO.java
-player
-domain
-PlayerCreateDomain.java
-PlayerUpdateDomain.java
-PlayerQueryResultDomain.java
-event
-PlayerUpdateEvent.java
-vo
-GamePerformanceVO.java
-game
-domain
-GameCreateDomain.java
-GameUpdateDomain.java
-GameQueryResultDomain.java
-event
-GameUpdateEvent.java
-vo
-GameSubstitutionVO.java

2.3.3 Dependências entre este projeto:
o domínio depende de dois módulos deste projeto:

util
client

A razão pela qual confiamos no módulo cliente é que os objetos de domínio agregam verificação de negócios e as seguintes informações precisam ser expostas externamente:

BizException
ErrorCodeBizEnum
<dependency>
<groupId>com.test.javafront</groupId>
<artifactId>user-demo-service-util</artifactId>
</dependency>
<dependency>
<groupId>com.test.javafront</groupId>
<artifactId>user-demo-service-client</artifactId>
</dependency>

2.3.4 Código principal

Tomemos como exemplo atletas modificando objetos de campo:

//Os atletas modificam o objeto do campo

public class PlayerUpdateDomain extends BaseDomain implements BizValidator {
private String playerId;
private String playerName;
private Integer height;
private Integer weight;
private String updator;
private Date updatetime;
private GamePerformanceVO gamePerformance;
private MaintainUpdateVO maintainInfo;

    @Override
    public void validate() {
        if (StringUtils.isEmpty(playerId)) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (StringUtils.isEmpty(playerName)) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (null == height) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (height > 300) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (null == weight) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (null != gamePerformance) {
            gamePerformance.validate();
        }
        if (null == maintainInfo) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        maintainInfo.validate();
    }
}

// Objeto de valor de desempenho do jogo

public class GamePerformanceVO implements BizValidator {

    // 跑动距离
    private Double runDistance;
    // 传球成功率
    private Double passSuccess;
    // 进球数
    private Integer scoreNum;
 
    @Override
    public void validate() {
        if (null == runDistance) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (null == passSuccess) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (Double.compare(passSuccess, 100) > 0) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (null == runDistance) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (null == scoreNum) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
    }
}

//Modifica o objeto de valor da pessoa

public class MaintainUpdateVO implements BizValidator {

    // 修改人
    private String updator;
    // 修改时间
    private Date updateTime;
 
    @Override
    public void validate() {
        if (null == updator) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
        if (null == updateTime) {
            throw new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT);
        }
    }
}

2.4 serviço

2.4.1 Estrutura do projeto

user-demo-service-service
-/src/main/java
-player
-adapter
-PlayerServiceAdapter.java
-event
-PlayerMessageSender.java
-service
-PlayerService.java
-game
-adapter
-GameServiceAdapter.java
-event
-GameMessageSender.java
-service
-GameService.java

2.4.2 Dependências entre este projeto
O serviço depende de quatro módulos deste projeto:

util
domain
integration
infrastructure
<dependency>
<groupId>com.test.javafront</groupId>
<artifactId>user-demo-service-domain</artifactId>
</dependency>
<dependency>
<groupId>com.test.javafront</groupId>
<artifactId>user-demo-service-infrastructure</artifactId>
</dependency>
<dependency>
<groupId>com.test.javafront</groupId>
<artifactId>user-demo-service-util</artifactId>
</dependency>
<dependency>
<groupId>com.test.javafront</groupId>
<artifactId>user-demo-service-integration</artifactId>
</dependency>

2.4.3 Código principal

Veja os serviços de edição de atletas como exemplo:

//Serviços para atletas

public class PlayerService {

    @Resource
    private PlayerEntityMapper playerEntityMapper;
    @Resource
    private PlayerMessageSender playerMessageSender;
    @Resource
    private PlayerServiceAdapter playerServiceAdapter;
 
    public boolean updatePlayer(PlayerUpdateDomain player) {
        AssertUtil.notNull(player, new BizException(ErrorCodeBizEnum.ILLEGAL_ARGUMENT));
        player.validate();
        PlayerEntity entity = playerServiceAdapter.convertUpdate(player);
        playerEntityMapper.updateById(entity);
        playerMessageSender.sendPlayerUpdatemessage(player);
        return true;
    }
}

//Serviço de mensagens do atleta

public class PlayerMessageSender {

    @Resource
    private PlayerServiceAdapter playerServiceAdapter;
 
    public boolean sendPlayerUpdatemessage(PlayerUpdateDomain domain) {
        PlayerUpdateEvent event = playerServiceAdapter.convertUpdateEvent(domain);
        log.info("sendPlayerUpdatemessage event={}", event);
        return true;
    }
}

//adaptador de serviço

public class PlayerServiceAdapter {

    // domain -> entity
    public PlayerEntity convertUpdate(PlayerUpdateDomain domain) {
        PlayerEntity player = new PlayerEntity();
        player.setPlayerId(domain.getPlayerId());
        player.setPlayerName(domain.getPlayerName());
        player.setWeight(domain.getWeight());
        player.setHeight(domain.getHeight());
        if (null != domain.getGamePerformance()) {
            player.setGamePerformance(JacksonUtil.bean2Json(domain.getGamePerformance()));
        }
        String updator = domain.getMaintainInfo().getUpdator();
        Date updateTime = domain.getMaintainInfo().getUpdateTime();
        player.setUpdator(updator);
        player.setUpdateTime(updateTime);
        return player;
    }
 
    // domain -> event
    public PlayerUpdateEvent convertUpdateEvent(PlayerUpdateDomain domain) {
        PlayerUpdateEvent event = new PlayerUpdateEvent();
        event.setPlayerUpdateDomain(domain);
        event.setMessageId(UUID.randomUUID().toString());
        event.setMessageId(PlayerMessageType.UPDATE.getMsg());
        return event;
    }
}

2.5 integração
Este projeto pode contar com serviços externos, portanto, a conversão de DTOs externos em objetos que este projeto possa compreender precisa ser processada nesta camada.

2.5.1 Estrutura do projeto
Suponha que este projeto chame o serviço do centro do usuário:

user-demo-service-intergration
-/src/main/java
-user
-adapter
-UserClientAdapter.java
-proxy
-UserClientProxy.java

Copie o código
2.5.2 A
integração de dependências entre este projeto depende de dois módulos deste projeto:

util
domain

A razão pela qual ele depende do módulo de domínio é que essa camada precisa converter DTOs externos em objetos que este projeto possa entender, e esses objetos são colocados no módulo de domínio.

<dependency>
    <groupId>com.test.javafront</groupId>
    <artifactId>user-demo-service-domain</artifactId>
</dependency>
<dependency>
    <groupId>com.test.javafront</groupId>
    <artifactId>user-demo-service-util</artifactId>
</dependency>

2.5.3 Código principal
Agora usaremos o objeto externo UserClientDTO

Converter para o objeto de domínio do projeto UserInfoDomain

(1) Serviços externos

//objeto externo

public class UserInfoClientDTO implements Serializable {
private String id;
private String name;
private Date createTime;
private Date updateTime;
private String mobile;
private String cityCode;
private String addressDetail;
}

//serviço externo

public class UserClientService {

    // RPC模拟
    public UserInfoClientDTO getUserInfo(String userId) {
        UserInfoClientDTO userInfo = new UserInfoClientDTO();
        userInfo.setId(userId);
        userInfo.setName(userId);
        userInfo.setCreateTime(DateUtil.now());
        userInfo.setUpdateTime(DateUtil.now());
        userInfo.setMobile("test-mobile");
        userInfo.setCityCode("test-city-code");
        userInfo.setAddressDetail("test-address-detail");
        return userInfo;
    }
}

(2) Objetos neste campo de projeto

O módulo de domínio adiciona o campo de usuário:

user-demo-service-domain
-/src/main/java
-user
-domain
-UserDomain.java
-vo
-UserAddressVO.java
-UserContactVO.java

Código do objeto do campo do usuário:

// domínio do usuário

public class UserInfoDomain extends BaseDomain {
    private UserContactVO contactInfo;
    private UserAddressVO addressInfo;
}

//Objeto de valor de endereço

public class UserAddressVO extends BaseVO {
    private String cityCode;
    private String addressDetail;
}

//Objeto de valor de contato

public class UserContactVO extends BaseVO {
private String mobile;
}

(3) Adaptador

public class UserClientAdapter {

    // third dto -> domain
    public UserInfoDomain convertUserDomain(UserInfoClientDTO userInfo) {
        UserInfoDomain userDomain = new UserInfoDomain();
        UserContactVO contactVO = new UserContactVO();
        contactVO.setMobile(userInfo.getMobile());
        userDomain.setContactInfo(contactVO);
 
        UserAddressVO addressVO = new UserAddressVO();
        addressVO.setCityCode(userInfo.getCityCode());
        addressVO.setAddressDetail(userInfo.getAddressDetail());
        userDomain.setAddressInfo(addressVO);
        return userDomain;
    }
}

(4) Ligue para serviços externos

public class UserClientProxy {

    @Resource
    private UserClientService userClientService;
    @Resource
    private UserClientAdapter userClientAdapter;
 
    public UserInfoDomain getUserInfo(String userId) {
        UserInfoClientDTO user = userClientService.getUserInfo(userId);
        UserInfoDomain result = userClientAdapter.convertUserDomain(user);
        return result;
    }
}

2.6 fachada + cliente

Existe um modo Fachada no padrão de design, que é chamado de modo fachada ou modo de aparência. Esse padrão fornece uma semântica externa concisa e protege a complexidade interna do sistema.

O cliente carrega o objeto externo de transmissão de dados DTO, e a fachada carrega o serviço externo.Essas duas camadas devem atender ao princípio do conhecimento mínimo, e informações irrelevantes não precisam ser divulgadas ao mundo exterior.

Isto tem duas vantagens:

Simplicidade: A semântica do serviço externo é clara e concisa
Segurança: Os campos sensíveis não podem ser expostos ao mundo exterior.

2.6.1 Estrutura do projeto

(1) cliente

user-demo-service-client
-/src/main/java
-base
-dto
-BaseDTO.java
-error
-BizException.java
-BizErrorCode.java
-event
-BaseEventDTO.java
-result
-ResultDTO.java
-player
-dto
-PlayerCreateDTO.java
-PlayerQueryResultDTO.java
-PlayerUpdateDTO.java
-enums
-PlayerMessageTypeEnum.java
-event
-PlayerUpdateEventDTO.java
-service
-PlayerClientService.java

(2) fachada

user-demo-service-facade
-/src/main/java
-player
-adapter
-PlayerFacadeAdapter.java
-impl
-PlayerClientServiceImpl.java
-game
-adapter
-GameFacadeAdapter.java
-impl
-GameClientServiceImpl.java

2.6.2 Dependências entre este projeto
O cliente não depende de outros módulos deste projeto, isso é muito importante porque o cliente será referenciado externamente, esta camada deve ser mantida simples e segura.

A fachada depende de três módulos deste projeto:

domain
client
service
<dependency>
    <groupId>com.test.javafront</groupId>
    <artifactId>user-demo-service-domain</artifactId>
</dependency>
    <dependency>
    <groupId>com.test.javafront</groupId>
    <artifactId>user-demo-service-client</artifactId>
</dependency>
<dependency>
    <groupId>com.test.javafront</groupId>
    <artifactId>user-demo-service-service</artifactId>
</dependency>

2.6.3 Código principal

(1) DTO

Tomando como exemplo a consulta de informações do atleta, o DTO do resultado da consulta encapsula apenas os campos mais críticos, como ID do atleta, horário de criação, horário de modificação e outros campos que não são de uso intensivo de negócios e não precisam ser divulgados:

public class PlayerQueryResultDTO implements Serializable {
    private String playerName;
    private Integer height;
    private Integer weight;
    private GamePerformanceDTO gamePerformanceDTO;
}

(2) Atendimento ao cliente

public interface PlayerClientService {
    public ResultDTO<PlayerQueryResultDTO> queryById(String playerId);
}

(3) Adaptador

public class PlayerFacadeAdapter {

    // domain -> dto
    public PlayerQueryResultDTO convertQuery(PlayerQueryResultDomain domain) {
        if (null == domain) {
            return null;
        }
        PlayerQueryResultDTO result = new PlayerQueryResultDTO();
        result.setPlayerId(domain.getPlayerId());
        result.setPlayerName(domain.getPlayerName());
        result.setHeight(domain.getHeight());
        result.setWeight(domain.getWeight());
        if (null != domain.getGamePerformance()) {
            GamePerformanceDTO performance = convertGamePerformance(domain.getGamePerformance());
            result.setGamePerformanceDTO(performance);
        }
        return result;
    }
}        

(4) Implementação de serviço

public class PlayerClientServiceImpl implements PlayerClientService {

    @Resource
    private PlayerService playerService;
    @Resource
    private PlayerFacadeAdapter playerFacadeAdapter;
 
    @Override
    public ResultDTO<PlayerQueryResultDTO> queryById(String playerId) {
        PlayerQueryResultDomain resultDomain = playerService.queryPlayerById(playerId);
        if (null == resultDomain) {
            return ResultCommonDTO.success();
        }
        PlayerQueryResultDTO result = playerFacadeAdapter.convertQuery(resultDomain);
        return ResultCommonDTO.success(result);
    }
}

Controlador 2.7

A implementação do serviço de fachada pode fornecer serviços como RPC, e o controlador fornece serviços como a interface HTTP deste projeto para chamadas front-end.

O controlador precisa prestar atenção às características relacionadas ao HTTP. Informações confidenciais, como ID de usuário de login, não podem ser passadas pelo front-end. Após o login, o front-end carregará informações de usuário de login no cabeçalho da solicitação, e o servidor precisa obter e analise-o no cabeçalho da solicitação.

2.7.1 Estrutura do projeto

user-demo-service-controller
-/src/main/java
-config
-CharsetConfig.java
-controller
-player
-PlayerController.java
-game
-GameController.java

2.7.2 Dependências deste projeto

O controlador depende de um módulo deste projeto:

facade

De acordo com o princípio de transferência de dependência, os seguintes módulos também dependem de:

domain
client
service
<dependency>
    <groupId>com.test.javafront</groupId>
    <artifactId>user-demo-service-facade</artifactId>
</dependency>

2.7.3 Código principal

@RestController
@RequestMapping("/player")
public class PlayerController {

    @Resource
    private PlayerClientService playerClientService;
 
    @PostMapping("/add")
    public ResultDTO<Boolean> add(@RequestHeader("test-login-info") String loginUserId, @RequestBody PlayerCreateDTO dto) {
        dto.setCreator(loginUserId);
        ResultCommonDTO<Boolean> resultDTO = playerClientService.addPlayer(dto);
        return resultDTO;
    }
 
    @PostMapping("/update")
    public ResultDTO<Boolean> update(@RequestHeader("test-login-info") String loginUserId, @RequestBody PlayerUpdateDTO dto) {
        dto.setUpdator(loginUserId);
        ResultCommonDTO<Boolean> resultDTO = playerClientService.updatePlayer(dto);
        return resultDTO;
    }
 
    @GetMapping("/{playerId}/query")
    public ResultDTO<PlayerQueryResultDTO> queryById(@RequestHeader("test-login-info") String loginUserId, @PathVariable("playerId") String playerId) {
        ResultCommonDTO<PlayerQueryResultDTO> resultDTO = playerClientService.queryById(playerId);
        return resultDTO;
    }
}

inicialização 2.8

boot é a camada de inicialização e possui apenas o código de entrada de inicialização.

2.8.1 Estrutura do projeto

Todo o código do módulo deve pertencer ao subcaminho com.user.demo.service

user-demo-service-boot
-/src/main/java
-com.user.demo.service
-MainApplication.java

2.8.2 Este projeto depende de
boot para referenciar todos os módulos deste projeto

util
integration
infrastructure
service
domain
facade
controller
client

2.8.3 Código principal

@MapperScan("com.user.demo.service.infrastructure.*.mapper")
@SpringBootApplication
public class MainApplication {
    public static void main(final String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}

3 Resumo do artigo

Vamos revisar novamente as cinco dimensões do pensamento hierárquico:

(1) Único

Cada camada lida apenas com um tipo de coisa. Por exemplo, util carrega apenas objetos de ferramenta e a integração lida apenas com serviços externos. As responsabilidades de cada camada são únicas e claras.

(2) Redução de ruído

Se não houver necessidade de adicionar entidades, por exemplo, o resultado da consulta DTO revela apenas os campos mais críticos, como ID do atleta, horário de criação, horário de modificação e outros campos que não são intensivos em negócios e não precisam ser divulgados.

(3) Adaptação

Existem adaptadores nas camadas de serviço, fachada e integração, e as informações de tradução são informações que podem ser compreendidas por esta camada ou pela camada inferior.

(4) Negócios

Os objetos de negócios podem agregar serviços por meio do modelo de congestionamento, como agregar lógica de verificação de negócios em objetos de negócios.

(5) Dados

O objeto de dados deve ser puro, por exemplo, o desempenho do jogo deve ser salvo no tipo string e a camada de dados não precisa ser analisada.

Acho que você gosta

Origin blog.csdn.net/lqzixi/article/details/132114466
Recomendado
Clasificación