Для начала введем понятия ВО ПО ДТО и так далее. Чтобы облегчить наше понимание.
Прежде всего, давайте поговорим о наиболее часто используемых из них — DTO и VO.
С развитием Интернета все более популярной становится модель разработки с разделением фронтенда и бэкэнда. В процессе взаимодействия внешних и внутренних данных для обеспечения безопасности и эффективности данных обычно используются DTO и VO для инкапсуляции данных.
DTO (объект передачи данных) и VO (объект значения) — это шаблоны проектирования, используемые для инкапсуляции данных и предоставления услуг.
Здесь нужно отметить, что это ВО Я где-то видел, что это написано так.:VO(
View Object
):просмотреть объект,для уровня представления,Его функция — инкапсулировать все данные указанной страницы (или компонента). После поиска большого количества информации по этому вопросу я получил следующее объяснение: хотя "View Object" Также допустимое объяснение, но в контексте объектно-ориентированного проектирования и доменно-ориентированного проектирования (DDD), VO. обычно относится к "Value Объект». Какая интерпретация будет выбрана, зависит от конкретного контекста и сценария использования.
Поэтому лучше всего использовать контекст, чтобы определить, относится ли он к «Объекту значения» или «Объекту просмотра».
Их основные отличия:
DTO да Что-то вродеобъект передачи данных,Используется для хранения данных в базе данныхПреобразование данных в формат, требуемый интерфейсом,удобный Данные между интерфейсом и серверомвзаимодействие。и VO да Что-то вродеценитьобъект,Используется для инкапсуляции различных атрибутов данных.,удобныйГлавная страницаотображатьивзаимодействие。
Их также очень легко спутать.
Можно сказать, что,Для большинства сценариев применения,Значения атрибутов DTOиVO в основном одинаковы.,и И они обычнодаPOJO,Так что раз есть ВО,Зачем вам нужен ДТО?
Более распространенные операции,СразудаДесенсибилизация пользовательских данных。
Конечно, в некоторых проектах я видел, что соглашение об именах DTO — xxxrequest.
Соглашение об именах для Vo — xxxresponse.
Это всего лишь соглашение об именах.
Тогда давайте разберемся, что такое PO и DAO
PO(Persistent Object)обычно относится ксопоставлено с таблицей в базе данныхJavaобъект。Он содержит поля таблицы базы данных.Соответствующие частные переменные-члены и соответствующие методы get и set.,Используется для инкапсуляции записи в таблице базы данных. Классы PO обычно используются на уровне доступа к данным (уровень DAO).,Как связующее звено между базой данных и приложениеммост,Реализуйте постоянное хранение и извлечение данных.
Чтобы многие люди не путали этот объект поля.
Далее позвольте мне рассказать об этой спецификации Alibaba для объектов домена:
1) Объект данных: xxxDO, xxx — имя таблицы данных. 2) Объект передачи данных: xxxDTO, xxx — имя, связанное с бизнес-сферой. 3) Объект отображения: xxxVO, xxx обычно представляет собой имя веб-страницы. 4) POJO — это собирательное имя DO/DTO/BO/VO, и называть его как xxxPOJO запрещено.
Разницы между DO и PO здесь нет или очень мало.
Ниже я буду использовать диаграмму и пример, чтобы помочь вам сначала разобраться в этих вещах.
Позже мы опишем различия между ними через программы.
Сначала давайте посмотрим на таблицу базы данных:
user_id bigint not null comment 'ID пользователя'
primary key,
username varchar(255) default '' not null comment 'имя пользователя',
password varchar(255) default '' not null comment 'пароль',
salt varchar(255) default '' not null comment «Случайная соль»,
question varchar(255) default '' not null comment «Вопрос безопасности»,
answer varchar(255) default '' not null comment «Секретный ответ»,
create_time datetime default CURRENT_TIMESTAMP not null comment «Время создания»,
update_time datetime default CURRENT_TIMESTAMP not null comment 'время обновления',
constraint uk_username
unique (username) comment 'имя пользователяуникальный индекс'
Это все поля.
Далее, давайте сначала посмотрим на простейший уровень Po, который представляет собой взаимно однозначное соответствие с этой базой данных.
@Data
public class UPanUser implements Serializable {
/**
* ID пользователя
*/
@TableId(value = "user_id")
private Long userId;
/**
* имя пользователя
*/
@TableField(value = "username")
private String username;
/**
* пароль
*/
@TableField(value = "password")
private String password;
/**
* Случайная соль
*/
@TableField(value = "salt")
private String salt;
/**
* Проблемы безопасности
*/
@TableField(value = "question")
private String question;
/**
* Секретный ответ
*/
@TableField(value = "answer")
private String answer;
/**
* время создания
*/
@TableField(value = "create_time")
private Date createTime;
/**
* Время обновления
*/
@TableField(value = "update_time")
private Date updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}
Затем мы используем случай входа пользователя для демонстрации VO и DTO.
ВО предполагает, что мы хотим вернуть во внешний интерфейс только имя пользователя.
Тогда наш атрибут имеет только одно имя пользователя.
@Data
public class UserInfoVo implements Serializable {
private static final long serialVersionUID = 1226886631190798234L;
private String username;
}
Давайте посмотрим на DTO позже
@Data
public class UserLoginPo implements Serializable {
private static final long serialVersionUID = 1L;
@NotBlank(message = "имя пользователь не может быть пустым")
@Pattern(regexp = "^[a-zA-Z0-9_-]{4,16}$", message = "имя ошибка формата пользователя")
private String username;
@NotBlank(message = "пароль не может быть пустым")
@Length(min = 6, max = 20, message = «Длина пароля должна быть от 6 до 20»).
private String password;
}
Здесь, в dto, мы можем использовать некоторую структуру проверки для ограничения. Это параметр, передаваемый нам интерфейсной страницей или вызывающей службой. То есть номер счета и пароль используются для завершения входа в систему.
Тогда приступим к конвертации.
Это относительно простой метод. Это тоже метод, который я часто использую
Вот пример:
import org.springframework.beans.BeanUtils;
public class SpringBeanUtilsExample {
public static void main(String[] args) {
// Создать объект заказа на покупку
UPanUser po = new UPanUser();
po.setUserId(1L);
po.setUsername("user");
po.setPassword("password");
po.setSalt("salt");
po.setQuestion("question");
po.setAnswer("answer");
po.setCreateTime(new Date());
po.setUpdateTime(new Date());
// Конвертировать PO в VO
UserInfoVo vo = new UserInfoVo();
BeanUtils.copyProperties(po, vo);
System.out.println("Конвертировать PO в VO:" + vo.getUsername());
// Создайте объект DTO
UserLoginPo dto = new UserLoginPo();
dto.setUsername("user");
dto.setPassword("password");
// Конвертировать DTO в PO
UPanUser poFromDto = new UPanUser();
BeanUtils.copyProperties(dto, poFromDto);
System.out.println("Конвертировать DTO в PO:" + poFromDto.getUsername());
}
}
Здесь необходимо отметить следующее.
import org.springframework.beans.BeanUtils;
Я использую этот Beanutils
Если вы используете import org.apache.commons.beanutils.BeanUtils;
Если это так, то позиции исходного и целевого параметров copyProperties этих двух методов противоположны.
Можно сказать, что это очень просто. Если вам нужно добавить комментарии, я рекомендую плагин под названием BeanUtilsHelper.
Он может поддерживать метод преобразования этого кода beanutils в исходное значение, полученное с помощью set get. Если вам интересно, вы можете попробовать. Он также может поддерживать множество аннотаций.
Далее я хочу поговорить о методе преобразования, обеспечивающем взрывную производительность, элегантность высокого уровня и высокие заводские стандарты.
Если вы хотите использовать библиотеку MapStruct для сопоставления объектов, сначала необходимо определить интерфейс Mapper и написать в нем методы сопоставления. Затем библиотека MapStruct автоматически сгенерирует соответствующий класс реализации сопоставления.
Во-первых, в pom.xml
Добавить в файл MapStruct Зависимости:
xmlCopy code<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
Затем определите интерфейс Mapper:
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
@Mapper
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
@Mapping(source = "username", target = "name")
UserInfoVo toUserInfoVo(UPanUser po);
@Mapping(source = "name", target = "username")
UPanUser toUPanUser(UserLoginPo dto);
}
Давайте посмотрим на его применение весной:
package com.xiaou.pan.server.modules.user.converter;
import com.xiaou.pan.server.modules.file.domain.UPanUserFile;
import com.xiaou.pan.server.modules.user.context.*;
import com.xiaou.pan.server.modules.user.domain.UPanUser;
import com.xiaou.pan.server.modules.user.po.*;
import com.xiaou.pan.server.modules.user.vo.UserInfoVo;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
/**
* Класс инструмента преобразования сущностей пользовательского модуля
*/
@Mapper(componentModel = "spring")
public interface UserConverter {
/**
* Заказ на регистрацию пользователя преобразован в контекст регистрации пользователя.
*
* @param userRegisterPo
* @return
*/
UserRegisterContext userRegisterPo2UserRegisterContext(UserRegisterPo userRegisterPo);
/**
* Контекст регистрации пользователя преобразован в PO регистрации пользователя.
*
* @param userRegisterContext
* @return
*/
@Mapping(target = "password", ignore = true)
UPanUser UserRegisterContext2UpanUser(UserRegisterContext userRegisterContext);
/**
* PO для входа пользователя преобразован в контекст входа пользователя
*
* @param userLoginPo
* @return
*/
UserLoginContext userLoginPO2UserLoginContext(UserLoginPo userLoginPo);
/**
* имя преобразование контекста проверки пользователя в имя пользователяпроверятьPO
*
* @param checkUserNamePo
* @return
*/
CheckUserNameContext CheckUserNamePo2CheckUserNameContext(CheckUserNamePo checkUserNamePo);
/**
* CheckAnswerPo — CheckAnswerContext
*
* @param checkAnswerPo
* @return
*/
CheckAnswerContext CheckAnswerPo2CheckAnswerContext(CheckAnswerPo checkAnswerPo);
ResetPasswordContext ResetPasswordPo2ResetPasswordContext(ResetPasswordPo resetPasswordPo);
ChangePasswordContext ChangePasswordPo2ChangePasswordContext(ChangePasswordPo changePasswordPo);
/**
* Соберите основную информацию о пользователе и верните объект.
* @param uPanUser
* @param uPanUserFile
* @return
*/
@Mapping(source = "uPanUser.username", target = "username")
@Mapping(source = "uPanUserFile.fileId", target = "rootFileId")
@Mapping(source = "uPanUserFile.fileName", target = "rootFilename")
UserInfoVo assembleUserInfoVo(UPanUser uPanUser, UPanUserFile uPanUserFile);
}
В дополнение к этому @mapping также имеет множество параметров:
Например, выражение
@Mapping(target = "userId", expression = "java(com.xiaou.pan.server.common.utils.UserIdUtil.get())")
Это может выполнить Java-код.
Фактический его принцип заключается в автоматическом написании для нас классов реализации:
import org.modelmapper.ModelMapper;
public class ModelMapperExample {
public static void main(String[] args) {
// Создать объект заказа на покупку
UPanUser po = new UPanUser();
po.setUserId(1L);
po.setUsername("user");
po.setPassword("password");
po.setSalt("salt");
po.setQuestion("question");
po.setAnswer("answer");
po.setCreateTime(new Date());
po.setUpdateTime(new Date());
// создавать ModelMapper объект
ModelMapper modelMapper = new ModelMapper();
// Конвертировать PO в VO
UserInfoVo vo = modelMapper.map(po, UserInfoVo.class);
System.out.println("Конвертировать PO в VO:" + vo.getUsername());
// Создайте объект DTO
UserLoginPo dto = new UserLoginPo();
dto.setUsername("user");
dto.setPassword("password");
// Конвертировать DTO в PO
UPanUser poFromDto = modelMapper.map(dto, UPanUser.class);
System.out.println("Конвертировать DTO в PO:" + poFromDto.getUsername());
}
}
использовать ModelMapper Правила сопоставления свойств можно определить более гибко, просто создав ModelMapper объект, а затем вызвать его map
Метод можно использовать для копирования атрибутов между объектами.
Напоследок хочу сказать, к этим ВО ПО ДТО относятся БО СО и так далее, если разрабатывать масштабный проект. Необходимо выполнить полную архитектуру, но если речь идет о небольших проектах, нет необходимости проектировать ради дизайна, что приводит к перепроектированию.