整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

IDEA 2021首个大版本发布,Java开发者感动哭了(附新亮点演示)

欲善其事,必先利其器!

就在不久之前,Java领域的开发神器IntelliJ IDEA终于迎来2021年的一个重要的大版本更新:IntelliJ IDEA 2021.1

现如今大量的Java开发者深度依赖着这款开发软件,正如网上的段子所言:“可以毫不夸张地说,多少Java程序员离开了IDEA就不会写代码了(狗头)”,由此可见其使用的广泛程度。

新版本一出来,我也迫不及待地想尝试一番。当然,主力开发机我是不敢乱升级的,所以这两天,我在一台平时用来做测试的老开发本子上更新了全新的IDEA。

软件启动界面打开的那一瞬间,我就知道事情并不简单。


全新的启动页面

更新后,全新的启动页面更加花里胡哨了。

软件启动速度也是非常之快,就我这多年苦练的火箭般手速,都差点没截来下面这张启动页面图。


Space集成

JetBrains提供的Space这个功能不知道大家有没有听说过,讲白了就是一套集成的团队协作环境,可以提供包括构建交付、聊天协作、团队管理以及项目管理等在内的一整套协作一体化解决方案。

最新的IDEA 2021.1把Space环境给无缝地集成进来了,现在属于开箱即用的状态,软件的右上角就有快捷入口:


支持WSL 2

这个功能相信对于很多依赖Windows系统以及WSL功能的用户来说,简直是喜大普奔!

以前WSL就算再好用,但是你的IDE并没有和它打通,多少总是一个遗憾。

这下好了,二者直接打通了,IDEA支持WSL 2。你可以直接在新版IDEA 2021.1中运行并开发WSL 2中的Java项目,包括Gradle类型项目和Maven类型等项目均支持。


Run Targets

Run Targets这个功能的意思有点类似于上面刚聊过的WSL 2。它允许开发者直接在远程主机甚至在Docker容器上运行和调试项目。

所以到目前为止,新版IDEA 2021允许开发者可以在本地、WSL 2、SSH远程主机、Docker等目标上运行项目,可以说贼香了!


支持Java 16

这也算是一个比较重磅的更新。

近两年来,Java版本的发布速度也是快如老狗,我还在用Java 8,它都淦到Java 16了。

关于Java 16的新特性,我还准备写篇文章来详细聊一聊呢,包括比如:

  • Records特性转正
  • instanceof模式匹配转正
  • jpackage转正
  • Unix域套接字通道
  • 弹性Metaspace
  • ZGC
  • 矢量API
  • 外部链接API
  • ...

这次IDEA 2021版的一个很重要的更新就是加入了对Java 16的基本支持,注意是基本支持。

除此之外IDEA还新增了几项检查机制,典型比如更加智能的数据流分析检查。

链式构造方式的优化格式设置等等。

目的都是为了帮助提升可读性,进一步提升用户体验。


Code With Me

Code With Me是一项用于协作开发与结对编程的服务,可以实Host-Guest模式的“手摸手”(滑稽)结对编程和群体编程。

目前,新版IDEA开箱即用地支持了Code With Me功能,同时它还具有音频通话和视频通话功能,可以满足随时随地的沟通需求,这操作简直骚到爆。

版本控制

版本控制这一块目前做了不少的更新,包括可以更快地完成PR的创建提交,支持PR模板。

变更提交至代码库前的自定义代码检查配置。

以及支持自定义Git提交模板等等。


其他用户体验提升

IDEA内置HTML网页预览

以前在IDEA中预览网页得跳到外部浏览器,而现如今IDE的编辑器内部就支持Built-in级别的网页预览,只需要在右上角点那个IDEA小图标即可激活,而且可以编辑网页源码时做到同步更新和预览。

Windows版本任务栏增强

在Windows平台的新版IDEA上,可直接在任务栏(或开始菜单)上右键快捷呼出最近使用的项目。

搜索时自定义外部依赖项

讲白了,就是使搜索范围更易于自定义,我们可以直接在设置中进行Scope定义,自行选择External Dependencies的范围是否包含。

窗口拆分优化

当你对编辑器里的多个文件进行垂直窗口拆分时,双击某个Tab就可以将当前文件窗口最大化,再次双击Tab则会还原。


当然除了这些之外,新版IDEA还新增了很多更新和增强,比如:对Kotlin、Scala、JavaScript等语言的开发优化、对常见框架与技术的优化和支持、对Kubernetes和Docker的更新支持和改进、数据库工具的更新支持等等,由于时间有限,在此就不一一赘述了,有需要的可以按需细究。

最后,让我们一起大喊一句:“IDEA,yyds!”

Java代码的时候,经常会涉及到重复性的操作,这个时候就会想要是有这样一个插件就好了,如果是大家都会遇到的场景,IDE或许已经提供了,再不然也有可能有人编写了相关的插件。

要是这个操作是你们的编码环境特有的,那就只能自己写工具了。所以这里来学学如何编写IDEA插件,让自己的编程环境更加强大,更好的进行装x。

开发环境

开发IDEA插件有以下这些依赖:

  • IntelliJ IDEA Community Edition
  • IntelliJ IDEA Community Edition 源码
  • Plugin DevKit 插件
  • IntelliJ Platform SDK

安装IntelliJ IDEA Community Edition

你可能已经安装了Ultimate版本,但是你还是需要安装[IDEA][]的社区版本。因为商业版是闭源的,所以在调试时无法调试核心代码。

下载IntelliJ IDEA Community Edition源码

社区版的安装包里是不包含源码的,所以我们需要手动从github上clone一份:

git clone --depth 1 git://git.jetbrains.org/idea/community.git idea

关于从源码运行IDEA的方法参考 Check Out And Build Community Edition:

http://www.jetbrains.org/intellij/sdk/docs/basics/checkout_and_build_community.html

添加IDEA jdk

虽然不知道原因,但是根据Check Out And Build Community Edition:

http://www.jetbrains.org/intellij/sdk/docs/basics/checkout_and_build_community.html

我们需要建立一个 IDEA jdk来运行插件:

除非你在Mac上使用官方JDK,否则你需要手动添加 /lib/tools.jar到classpath中。关注微信公众号:匠心零度,在后台回复:idea,可以获取我整最新 IDEA 教程,都是干货。

配置IntelliJ Platform SDK

打开 File|ProjectStructure新建一个 IntelliJPlatformSDK:

Java SDK选择我们刚刚建立的 IDEA jdk:

然后我们可以把下载的IDEA社区版源码添加到源码路径中,这样在调试时,就可以调试IDEA自身的代码了:

第一个插件

我们来编写一个最简单的插件来学习编写一个插件的完整步骤。

新建工程

选择 IntellJPlatformPlugin,然后Project SDK指定刚刚新建的plugin sdk:

新建的插件项目:

插件根目录下有两个目录 src和 resources。src是插件代码目录, resource是插件资源目录,其中 META-INF/plugin.xml是插件的描述文件,就像Java web项目的 web.xml一样。

plugin.xml默认的内容如下:

<idea-plugin>    <id>com.your.company.unique.plugin.id</id>    <name>Plugin display name here</name>    <version>1.0</version>    <vendor email="support@yourcompany.com" url="http://www.yourcompany.com">YourCompany</vendor>    <description><!\[CDATA\[      Enter short description for your plugin here.<br>        <em>most HTML tags may be used</em>      \]\]></description>    <change-notes><!\[CDATA\[      Add change notes here.<br>        <em>most HTML tags may be used</em>      \]\]>  </change-notes>    <!\-\- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting\_started/build\_number_ranges.html for description -->  <idea-version since-build="145.0"/>    <!\-\- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting\_started/plugin\_compatibility.html       on how to target different products -->  <!\-\- uncomment to enable plugin in all products  <depends>com.intellij.modules.lang</depends>    -->  <extensions defaultExtensionNs="com.intellij">      <!\-\- Add your extensions here -->  </extensions>    <actions>      <!\-\- Add your actions here -->  </actions>  </idea-plugin>  

新建一个Action

插件扩展IDEA最常见的方式就是在菜单栏或者工具栏中添加菜单项,用户通过点击菜单项来触发插件功能。IDEA提供了 AnAction类,这个类有一个虚方法 actionPerformed,这个方法会在每次菜单被点击时调用。

新建一个自定义的Action有两个步骤:

1、 继承 AnAction类,在 actionPerformed方法中实现插件逻辑 2、 注册action,有两种方式,通过代码注册和通过 plugin.xml注册

我们先写一个简单的Action类:

publicclass TextBoxes extends AnAction {      // 如果通过Java代码来注册,这个构造函数会被调用,传给父类的字符串会被作为菜单项的名称    // 如果你通过plugin.xml来注册,可以忽略这个构造函数    public TextBoxes() {          // 设置菜单项名称        super("Text _Boxes");          // 还可以设置菜单项名称,描述,图标        // super("Text _Boxes","Item description",IconLoader.getIcon("/Mypackage/icon.png"));    }      public void actionPerformed(AnActionEvent event) {          Project project = event.getData(PlatformDataKeys.PROJECT);          String txt= Messages.showInputDialog(project, "What is your name?", "Input your name", Messages.getQuestionIcon());          Messages.showMessageDialog(project, "Hello, " \+ txt + "!\n I am glad to see you.", "Information", Messages.getInformationIcon());      }  }  

然后我们在 plugin.xml中注册这个Action:

<actions>    <group id="MyPlugin.SampleMenu" text="_Sample Menu" description="Sample menu">      <add-to-group group-id="MainMenu" anchor="last"  />         <action id="Myplugin.Textboxes"class="Mypackage.TextBoxes" text="Text _Boxes" description="A test menu item" />    </group>  </actions>  

这里我们新建了一个菜单组,其中text字符串的下划线表示这个字母作为快捷键。这个菜单显示的效果如下:

除了手动新建Action,IDEA还提供了快速新建的方法,在代码目录上点击新建,可以看到Action:

可以在这个面板中填写你要新建的Action信息,IDEA会帮你新建类,还有在plugin.xml中帮你注册:

运行插件

运行插件特别简单,和运行普通Java代码一样,点击运行或者调试的按钮,就会启动一个新的IDEA实例,这个实例中插件是生效的。

点击Text Boxes就可以看到插件的效果了。

asyCode

EasyCode是一款专为IntelliJ IDEA设计的代码生成工具插件,旨在通过自动化和模板化的方式,极大地提高Java开发者的编码效率和代码质量。这款插件深度融合于IDEA的开发环境中,为开发者带来全新的开发体验,让编程变得更加轻松愉快。

功能特点

  1. 智能代码生成
  2. EasyCode基于模板引擎的原理,能够快速生成标准化的代码片段,包括类、方法、注释、测试等。通过简单的配置和选择,开发者可以在几秒钟内完成繁琐的代码编写工作,如实体类的属性、Getter和Setter方法、数据库操作代码等。
  3. 它支持自定义代码模板,开发者可以根据项目需求和团队编码规范,定制适合自己的代码模板,以最佳实践的方式生成代码,减少因格式问题而浪费的时间。
  4. 智能代码补全
  5. 在编程过程中,开发者只需输入少量的关键字或方法名,EasyCode便能自动补全剩余部分,不仅减少了输入的工作量,还降低了出现拼写错误或语法错误的可能性,提高了代码的可读性和稳定性。
  6. 丰富的模板库
  7. EasyCode提供了丰富的代码模板库,涵盖了常见的代码结构和设计模式。开发者可以根据项目需求,选择合适的模板快速生成代码,节省了大量的编码时间。
  8. 高效便捷的操作
  9. 插件支持通过快捷键和上下文菜单快速生成代码。开发者可以自定义快捷键组合,或在编辑器中选中代码片段后,通过右键菜单选择EasyCode的相关选项,快速生成对应的代码。
  10. 其他实用功能
  11. EasyCode还提供了快速生成文档注释、自动导入所需的包和类、代码格式化等实用功能,帮助开发者更加专注于解决问题和实现功能,而不必在琐碎的代码编写上花费过多的时间和精力。

优缺点

优点

  • 简单容易上手:EasyCode与IDEA完美结合,界面操作简洁明了,操作起来简单方便。
  • 配置少,修改少:几乎不需要手写配置,只需修改模板文件,即可轻松适应项目需求,生成所需代码。
  • 提高开发效率:通过自动生成重复性的代码,减少了手动编写代码的时间和精力,使开发者能够更专注于业务逻辑的实现。
  • 保持代码一致性:使用EasyCode生成的代码遵循统一的标准和规范,提高了代码的一致性和可读性。

缺点

  • 精细度不够:EasyCode主要基于数据库表的字段生成代码,但在实际开发中,某些字段可能需要更精细的处理,如状态字段的多种状态表示、关联字段的关联关系等。
  • 团队共享性差:在团队中,如果某个成员修改了模板,需要手动导出并分享给其他成员导入,才能获得最新的模板,这在一定程度上影响了模板的共享性和更新效率。

综上所述,EasyCode作为一款高效的IDEA插件,通过自动化和模板化的方式,为Java开发者带来了极大的便利和效率提升。尽管存在一些缺点,但在大多数情况下,它仍然是提高开发效率、保持代码一致性的有力工具。

其实这么古老的插件大家应该都知道,我就简单讲述一下。并且逆向生成也有很多的方式,这篇文章主要是记录下生成的模板配置信息,方便后续使用。

image.png

使用教程

1.通过IDEA自带的数据库工具连接上数据库

image.png

image.png

2.配置EasyCode生成的模板

*注:点击上面的+是创建分组,输入分组名创建后点击里面的+是创建该分组的模板,后续生成的时候选择其分组就行

3.选择数据表,鼠标右键选择EasyCode来生成模板

image.png

image.png

*注:Package和Path选到要生成的模块级就行了(模块包名会根据模板自动创建,不要自己去创),比如:xxx/src/main/java/com/xx/包名

Mybatis-plus模板:

  • controller.java.vm
##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "Controller"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/controller"))
##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import $!{tableInfo.savePackageName}.domain.$!{tableInfo.name};
import $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;
import $!{tableInfo.savePackageName}.common.R;
import org.springframework.web.bind.annotation.*;

import jakarta.annotation.Resource;
import java.io.Serializable;
import java.util.List;

/**
 * $!{tableInfo.comment}($!{tableInfo.name})控制层
 *
 * @author ycc
 * @since $!time.currTime()
 */
@RestController
@RequestMapping("$!tool.firstLowerCase($tableInfo.name)")
public class $!{tableName} {

    /**
     * 服务对象
     */
    @Resource
    private $!{tableInfo.name}Service $!tool.firstLowerCase($tableInfo.name)Service;

    /**
     * 分页查询所有数据
     */
    @GetMapping
    public R page(@RequestParam int current,@RequestParam int size){
        Page<$!{tableInfo.name}> page=new Page<>(current,size);
        return R.ok($!{tool.firstLowerCase($tableInfo.name)}Service.page(page));}


    /**
     * 通过主键查询单条数据
     */
    @GetMapping("{id}")
    public R selectOne(@PathVariable Serializable id){
        return R.ok($!{tool.firstLowerCase($tableInfo.name)}Service.getById(id));}
    
    /**
     * 新增数据
     */
    @PostMapping
    public R save(@RequestBody $!{tableInfo.name} $!tool.firstLowerCase($tableInfo.name)){
        return R.ok($!{tool.firstLowerCase($tableInfo.name)}Service.save($!tool.firstLowerCase($tableInfo.name)));}
    
    /**
     * 修改数据
     */
    @PutMapping
    public R updateById(@RequestBody $!{tableInfo.name} $!tool.firstLowerCase($tableInfo.name)){
        return R.ok($!{tool.firstLowerCase($tableInfo.name)}Service.updateById($!tool.firstLowerCase($tableInfo.name)));}
    
    /**
     * 单条/批量删除数据
     */
    @DeleteMapping
    public R delete(@RequestParam List<Long> id){
        return R.ok($!{tool.firstLowerCase($tableInfo.name)}Service.removeByIds(id));
    }
}
  • service.java.vm
##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "Service"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/service"))

##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service;

import $!{tableInfo.savePackageName}.domain.$!{tableInfo.name};
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * $!{tableInfo.comment}($!{tableInfo.name})服务接口
 *
 * @author ycc
 * @since $!time.currTime()
 */
public interface $!{tableName} extends IService<$!tableInfo.name> {}
  • serviceImpl.java.vm
##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "ServiceImpl"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/service/impl"))

##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import $!{tableInfo.savePackageName}.domain.$!{tableInfo.name};
import $!{tableInfo.savePackageName}.mapper.$!{tableInfo.name}Mapper;
import $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;
import org.springframework.stereotype.Service;

/**
 * $!{tableInfo.comment}($!{tableInfo.name})服务实现类
 *
 * @author ycc
 * @since $!time.currTime()
 */
@Service
public class $!{tableName} extends ServiceImpl<$!{tableInfo.name}Mapper, $!{tableInfo.name}> implements $!{tableInfo.name}Service {}
  • mapper.java.vm
##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "Mapper"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/mapper"))

##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import $!{tableInfo.savePackageName}.domain.$!tableInfo.name;

/**
 * $!{tableInfo.comment}($!{tableInfo.name})数据库访问层
 *
 * @author ycc
 * @since $!time.currTime()
 */
 @Mapper
public interface $!{tableName} extends BaseMapper<$!tableInfo.name> {}
  • mapper.xml.vm
##引入mybatis支持
$!{mybatisSupport.vm}

##设置保存名称与保存位置
$!callback.setFileName($tool.append($!{tableInfo.name}, "Mapper.xml"))
$!callback.setSavePath($tool.append($modulePath, "/src/main/resources/mapper"))

##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="$!{tableInfo.savePackageName}.mapper.$!{tableInfo.name}Mapper">

    <resultMap type="$!{tableInfo.savePackageName}.domain.vo.$!{tableInfo.name}VO" id="$!{tableInfo.name}VOMap">
#foreach($column in $tableInfo.fullColumn)
        <result property="$!column.name" column="$!column.obj.name" jdbcType="$!column.ext.jdbcType"/>
#end
    </resultMap>
    
</mapper>
  • domain.java.vm
##引入宏定义
$!{define.vm}

##使用宏定义设置回调(保存位置与文件后缀)
#save("/domain", ".java")

##使用宏定义设置包后缀
#setPackageSuffix("domain")

##使用全局变量实现默认包导入
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


/**
 * $!{tableInfo.comment}($!{tableInfo.comment})表
 *
 * @author ycc
 * @since $!time.currTime()
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class $!{tableInfo.name}{
private static final long serialVersionUID= 1L;
#foreach($column in $tableInfo.pkColumn)
    #if(${column.comment})/**
     * ${column.comment}
     */#end

    @TableId(value = "$!{column.obj.name}" , type = IdType.NONE)
    private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end
#foreach($column in $tableInfo.otherColumn)

    #if(${column.comment})
/**
     * ${column.comment}
     */
    #end
@TableField(value = "$!{column.obj.name}")
    private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end
}
  • dto.java.vm
##引入宏定义
$!{define.vm}

##使用宏定义设置回调(保存位置与文件后缀)
#save("/domain/dto", "DTO.java")

##使用宏定义设置包后缀
#setPackageSuffix("domain.dto")

import $!{tableInfo.savePackageName}.domain.$!{tableInfo.name};

##使用全局变量实现默认包导入
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * $!{tableInfo.comment}($!{tableInfo.name})DTO
 *
 * @author ycc
 * @since $!time.currTime()
 */
##使用宏定义实现类注释信息
@Data
@NoArgsConstructor
public class $!{tableInfo.name}DTO extends $!{tableInfo.name}{
    
}
  • vo.java.vm
##引入宏定义
$!{define.vm}

##使用宏定义设置回调(保存位置与文件后缀)
#save("/domain/vo", "VO.java")

##使用宏定义设置包后缀
#setPackageSuffix("domain.vo")

import $!{tableInfo.savePackageName}.domain.$!{tableInfo.name};

##使用全局变量实现默认包导入
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * $!{tableInfo.comment}($!{tableInfo.name})VO
 *
 * @author ycc
 * @since $!time.currTime()
 */
##使用宏定义实现类注释信息
@Data
@NoArgsConstructor
public class $!{tableInfo.name}VO extends $!{tableInfo.name}{
    
}

VO/DTO/DOMAIN区别

VO(View Object)、DTO(Data Transfer Object)和DOMAIN(领域模型)是三种常见的用于数据传递和处理的类型,它们各自在不同的场景下发挥着重要作用。下面分别解释它们的区别和使用场景。

1. VO(View Object)

定义:VO通常用于表示视图层(如JSP、HTML页面等)与控制器(Controller)之间的数据传输对象。它封装了需要展示给用户的数据,但不包含业务逻辑。

使用场景

  • 当需要将数据库中的某些数据展示到页面上时,可以使用VO来封装这些数据。
  • VO可以包含多个领域模型(Domain)的属性,用于满足特定视图的展示需求。
  • 便于前端直接处理,减少数据转换的复杂度。

2. DTO(Data Transfer Object)

定义:DTO是一种设计模式,用于在系统不同层(如表现层与业务层之间,或微服务之间的远程调用)之间传输数据。DTO主要用于封装跨层或跨系统边界传输的数据。

使用场景

  • 在微服务架构中,服务间的通信通常使用DTO来传递数据。
  • 当需要在网络间传输数据时(如REST API的返回数据),DTO可以有效地封装需要传输的数据。
  • DTO可以只包含需要的字段,减少数据传输的冗余,提高性能。
  • 在分层架构中,DTO可以隔离层与层之间的数据依赖,提高系统的可扩展性和可维护性。

3. DOMAIN(领域模型)

定义:DOMAIN是领域驱动设计(Domain-Driven Design, DDD)中的一个核心概念,表示业务领域内的一组具有业务含义和规则的类及它们之间的关系。Domain类通常包含业务逻辑和状态信息。

使用场景

  • Domain模型是业务逻辑的核心,它封装了业务领域的知识和规则。
  • 在复杂的业务系统中,Domain模型帮助开发者理解和实现业务逻辑。
  • Domain模型可以直接与数据库表映射(通过ORM工具),但更重要的是,它代表了业务逻辑和数据行为的抽象。
  • 相比DTO和VO,Domain模型更加侧重于业务逻辑的实现和表达。

总结

  • VO 专注于视图展示,封装展示层需要的数据。
  • DTO 专注于数据的跨层或跨系统传输,减少数据冗余,提高传输效率。
  • DOMAIN 专注于业务逻辑的实现,封装业务领域的知识和规则。

在实际项目中,应根据具体需求和场景来选择合适的类型,以达到最佳的开发效率和系统性能。

结语

"非常感谢您一直观看到现在,这些看似基础的内容,实则构建了我们知识的基石。我惊喜地发现,将这些基础知识系统地记录下来,不仅是对自我学习的一种巩固,也是一件非常有意义且值得分享的事情。您也完全可以这样做,让我们一起在基础中深耕,发现更多可能。"


原文:https://juejin.cn/post/7392513123860365339

作者:世界哪有真情

#记录我的2024#