mirror of https://github.com/halo-dev/halo
Refactor InputConverter and OutputConverter
parent
12a6b548a4
commit
d49a21501d
|
@ -2,7 +2,7 @@ package cc.ryanc.halo.model.dto;
|
|||
|
||||
import cc.ryanc.halo.model.domain.Comment;
|
||||
import cc.ryanc.halo.model.domain.Post;
|
||||
import cc.ryanc.halo.model.dto.base.AbstractOutputConverter;
|
||||
import cc.ryanc.halo.model.dto.base.OutputConverter;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
@ -12,7 +12,7 @@ import java.util.Date;
|
|||
* @date : 2019-03-09
|
||||
*/
|
||||
@Data
|
||||
public class CommentViewOutputDTO extends AbstractOutputConverter<CommentViewOutputDTO, Comment> {
|
||||
public class CommentViewOutputDTO implements OutputConverter<CommentViewOutputDTO, Comment> {
|
||||
|
||||
private Long commentId;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package cc.ryanc.halo.model.dto;
|
|||
|
||||
import cc.ryanc.halo.model.domain.Comment;
|
||||
import cc.ryanc.halo.model.domain.Post;
|
||||
import cc.ryanc.halo.model.dto.base.AbstractOutputConverter;
|
||||
import cc.ryanc.halo.model.dto.base.OutputConverter;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
|
@ -14,7 +14,7 @@ import java.util.List;
|
|||
* @date : 2019-03-09
|
||||
*/
|
||||
@Data
|
||||
public class PageAdminOutputDTO extends AbstractOutputConverter<PageAdminOutputDTO, Post> {
|
||||
public class PageAdminOutputDTO implements OutputConverter<PageAdminOutputDTO, Post> {
|
||||
|
||||
private Long postId;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cc.ryanc.halo.model.dto;
|
||||
|
||||
import cc.ryanc.halo.model.domain.*;
|
||||
import cc.ryanc.halo.model.dto.base.AbstractOutputConverter;
|
||||
import cc.ryanc.halo.model.dto.base.OutputConverter;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
|
@ -14,7 +14,7 @@ import java.util.List;
|
|||
* @author johnniang
|
||||
*/
|
||||
@Data
|
||||
public class PostDetailOutputDTO extends AbstractOutputConverter<PostDetailOutputDTO, Post> {
|
||||
public class PostDetailOutputDTO implements OutputConverter<PostDetailOutputDTO, Post> {
|
||||
|
||||
private Long postId;
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package cc.ryanc.halo.model.dto;
|
||||
|
||||
import cc.ryanc.halo.model.domain.*;
|
||||
import cc.ryanc.halo.model.dto.base.AbstractOutputConverter;
|
||||
import cc.ryanc.halo.model.domain.Category;
|
||||
import cc.ryanc.halo.model.domain.Post;
|
||||
import cc.ryanc.halo.model.domain.Tag;
|
||||
import cc.ryanc.halo.model.dto.base.OutputConverter;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
|
@ -14,7 +16,7 @@ import java.util.List;
|
|||
* @author johnniang
|
||||
*/
|
||||
@Data
|
||||
public class PostSimpleOutputDTO extends AbstractOutputConverter<PostSimpleOutputDTO, Post> {
|
||||
public class PostSimpleOutputDTO implements OutputConverter<PostSimpleOutputDTO, Post> {
|
||||
|
||||
private Long postId;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cc.ryanc.halo.model.dto;
|
||||
|
||||
import cc.ryanc.halo.model.domain.Post;
|
||||
import cc.ryanc.halo.model.dto.base.AbstractOutputConverter;
|
||||
import cc.ryanc.halo.model.dto.base.OutputConverter;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
|
@ -12,7 +12,7 @@ import java.util.Date;
|
|||
* @date : 2019-03-09
|
||||
*/
|
||||
@Data
|
||||
public class PostViewOutputDTO extends AbstractOutputConverter<PostViewOutputDTO, Post> {
|
||||
public class PostViewOutputDTO implements OutputConverter<PostViewOutputDTO, Post> {
|
||||
|
||||
private Long postId;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import static cc.ryanc.halo.utils.BeanUtils.updateProperties;
|
|||
*
|
||||
* @author johnniang
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractInputConverter<DOMAIN> implements InputConverter<DOMAIN> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -12,7 +12,8 @@ import static cc.ryanc.halo.utils.BeanUtils.updateProperties;
|
|||
*
|
||||
* @author johnniang
|
||||
*/
|
||||
public abstract class AbstractOutputConverter<DTO, DOMAIN> implements OutputConverter<DTO, DOMAIN> {
|
||||
@Deprecated
|
||||
public abstract class AbstractOutputConverter<DTO extends OutputConverter<DTO, DOMAIN>, DOMAIN> implements OutputConverter<DTO, DOMAIN> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final Class<DTO> dtoType = (Class<DTO>) fetchType(0);
|
||||
|
@ -23,9 +24,9 @@ public abstract class AbstractOutputConverter<DTO, DOMAIN> implements OutputConv
|
|||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public DTO convertFrom(DOMAIN domain) {
|
||||
public <T extends DTO> T convertFrom(DOMAIN domain) {
|
||||
updateProperties(domain, this);
|
||||
return (DTO) this;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
package cc.ryanc.halo.model.dto.base;
|
||||
|
||||
import cc.ryanc.halo.utils.ReflectionUtils;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.Objects;
|
||||
|
||||
import static cc.ryanc.halo.utils.BeanUtils.transformFrom;
|
||||
import static cc.ryanc.halo.utils.BeanUtils.updateProperties;
|
||||
|
||||
/**
|
||||
* Converter interface for input DTO.
|
||||
*
|
||||
|
@ -12,13 +20,26 @@ public interface InputConverter<DOMAIN> {
|
|||
*
|
||||
* @return new domain with same value(not null)
|
||||
*/
|
||||
DOMAIN convertTo();
|
||||
@SuppressWarnings("unchecked")
|
||||
default DOMAIN convertTo() {
|
||||
// Get parameterized type
|
||||
ParameterizedType currentType = ReflectionUtils.getParameterizedType(InputConverter.class, this.getClass());
|
||||
|
||||
// Assert not equal
|
||||
Objects.requireNonNull(currentType, "Cannot fetch actual type because parameterized type is null");
|
||||
|
||||
Class<DOMAIN> domainClass = (Class<DOMAIN>) currentType.getActualTypeArguments()[0];
|
||||
|
||||
return transformFrom(this, domainClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a domain by dto.(shallow)
|
||||
*
|
||||
* @param domain updated domain
|
||||
*/
|
||||
void update(DOMAIN domain);
|
||||
default void update(DOMAIN domain) {
|
||||
updateProperties(this, domain);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
package cc.ryanc.halo.model.dto.base;
|
||||
|
||||
import static cc.ryanc.halo.utils.BeanUtils.updateProperties;
|
||||
|
||||
/**
|
||||
* Converter interface for output DTO.
|
||||
*
|
||||
* <b>The implementation type must be equal to DTO type</b>
|
||||
*
|
||||
* @param <DTO> the implementation class type
|
||||
* @param <DOMAIN> doamin type
|
||||
* @author johnniang
|
||||
*/
|
||||
public interface OutputConverter<DTO, DOMAIN> {
|
||||
public interface OutputConverter<DTO extends OutputConverter<DTO, DOMAIN>, DOMAIN> {
|
||||
|
||||
/**
|
||||
* Convert from domain.(shallow)
|
||||
|
@ -13,5 +19,11 @@ public interface OutputConverter<DTO, DOMAIN> {
|
|||
* @param domain domain data
|
||||
* @return converted dto data
|
||||
*/
|
||||
DTO convertFrom(DOMAIN domain);
|
||||
@SuppressWarnings("unchecked")
|
||||
default <T extends DTO> T convertFrom(DOMAIN domain) {
|
||||
|
||||
updateProperties(domain, this);
|
||||
|
||||
return (T) this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cc.ryanc.halo.model.params;
|
||||
|
||||
import cc.ryanc.halo.model.domain.Post;
|
||||
import cc.ryanc.halo.model.dto.base.AbstractInputConverter;
|
||||
import cc.ryanc.halo.model.dto.base.InputConverter;
|
||||
import cc.ryanc.halo.model.enums.PostTypeEnum;
|
||||
import cc.ryanc.halo.utils.MarkdownUtils;
|
||||
import lombok.Data;
|
||||
|
@ -13,7 +13,7 @@ import lombok.Data;
|
|||
* @date : 2019/03/04
|
||||
*/
|
||||
@Data
|
||||
public class JournalParam extends AbstractInputConverter<Post> {
|
||||
public class JournalParam implements InputConverter<Post> {
|
||||
|
||||
/**
|
||||
* 标题
|
||||
|
|
|
@ -52,7 +52,7 @@ public class BeanUtils {
|
|||
// Return the target instance
|
||||
return targetInstance;
|
||||
} catch (Exception e) {
|
||||
throw new BeanUtilsException("Failed to new " + targetClass.getName() + "instance or copy properties", e);
|
||||
throw new BeanUtilsException("Failed to new " + targetClass.getName() + " instance or copy properties", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package cc.ryanc.halo.utils;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Reflection utilities.
|
||||
*
|
||||
* @author johnniang
|
||||
*/
|
||||
public class ReflectionUtils {
|
||||
|
||||
private ReflectionUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets parameterized type.
|
||||
*
|
||||
* @param interfaceType interface type must not be null
|
||||
* @param genericTypes generic type array
|
||||
* @return parameterized type of the interface or null if it is mismatch
|
||||
*/
|
||||
@Nullable
|
||||
public static ParameterizedType getParameterizedType(@NonNull Class<?> interfaceType, Type... genericTypes) {
|
||||
Assert.notNull(interfaceType, "Interface type must not be null");
|
||||
|
||||
ParameterizedType currentType = null;
|
||||
|
||||
for (Type genericType : genericTypes) {
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) genericType;
|
||||
if (parameterizedType.getRawType().getTypeName().equals(interfaceType.getTypeName())) {
|
||||
currentType = parameterizedType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets parameterized type.
|
||||
*
|
||||
* @param interfaceType interface type must not be null
|
||||
* @param implementationClass implementation class of the interface must not be null
|
||||
* @return parameterized type of the interface or null if it is mismatch
|
||||
*/
|
||||
@Nullable
|
||||
public static ParameterizedType getParameterizedType(@NonNull Class<?> interfaceType, Class<?> implementationClass) {
|
||||
Assert.notNull(interfaceType, "Interface type must not be null");
|
||||
|
||||
if (implementationClass == null) {
|
||||
// If the super class is Object parent then return null
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get parameterized type
|
||||
ParameterizedType currentType = getParameterizedType(interfaceType, implementationClass.getGenericInterfaces());
|
||||
|
||||
if (currentType != null) {
|
||||
// return the current type
|
||||
return currentType;
|
||||
}
|
||||
|
||||
Class<?> superclass = implementationClass.getSuperclass();
|
||||
|
||||
return getParameterizedType(interfaceType, superclass);
|
||||
}
|
||||
}
|
|
@ -110,7 +110,7 @@ public class AdminController extends BaseController {
|
|||
//查询最新的文章
|
||||
final List<PostViewOutputDTO> postsLatest = postService.findPostLatest()
|
||||
.stream()
|
||||
.map(post -> new PostViewOutputDTO().convertFrom(post))
|
||||
.map(post -> (PostViewOutputDTO) new PostViewOutputDTO().convertFrom(post))
|
||||
.collect(Collectors.toList());
|
||||
model.addAttribute("postsLatest", postsLatest);
|
||||
|
||||
|
@ -121,7 +121,7 @@ public class AdminController extends BaseController {
|
|||
//查询最新的评论
|
||||
final List<CommentViewOutputDTO> commentsLatest = commentService.findCommentsLatest()
|
||||
.stream()
|
||||
.map(comment -> new CommentViewOutputDTO().convertFrom(comment))
|
||||
.map(comment -> (CommentViewOutputDTO) new CommentViewOutputDTO().convertFrom(comment))
|
||||
.collect(Collectors.toList());
|
||||
model.addAttribute("commentsLatest", commentsLatest);
|
||||
|
||||
|
|
|
@ -48,9 +48,9 @@ public class MenuController {
|
|||
public String menus(Model model) {
|
||||
List<PostViewOutputDTO> posts = postService.findAll(PostTypeEnum.POST_TYPE_PAGE.getDesc())
|
||||
.stream()
|
||||
.map(post -> new PostViewOutputDTO().convertFrom(post))
|
||||
.map(post -> (PostViewOutputDTO) new PostViewOutputDTO().convertFrom(post))
|
||||
.collect(Collectors.toList());
|
||||
model.addAttribute("posts",posts);
|
||||
model.addAttribute("posts", posts);
|
||||
return "admin/admin_menu";
|
||||
}
|
||||
|
||||
|
|
|
@ -87,8 +87,10 @@ public class PageController {
|
|||
public String pages(Model model) {
|
||||
final List<PageAdminOutputDTO> posts = postService.findAll(PostTypeEnum.POST_TYPE_PAGE.getDesc())
|
||||
.stream()
|
||||
.map(post -> new PageAdminOutputDTO().convertFrom(post))
|
||||
.map(post -> (PageAdminOutputDTO) new PageAdminOutputDTO().convertFrom(post))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
model.addAttribute("pages", posts);
|
||||
return "admin/admin_page";
|
||||
}
|
||||
|
|
|
@ -94,6 +94,9 @@ public class PostController extends BaseController {
|
|||
@RequestParam(value = "status", defaultValue = "0") Integer status,
|
||||
@PageableDefault(sort = "postDate", direction = DESC) Pageable pageable) {
|
||||
final Page<Post> posts = postService.findPostByStatus(status, PostTypeEnum.POST_TYPE_POST.getDesc(), pageable);
|
||||
|
||||
Page<PostViewOutputDTO> postViewOutputDTOS = posts.map(post -> new PostViewOutputDTO().convertFrom(post));
|
||||
|
||||
model.addAttribute("posts", posts);
|
||||
model.addAttribute("publishCount", postService.getCountByStatus(PostStatusEnum.PUBLISHED.getCode()));
|
||||
model.addAttribute("draftCount", postService.getCountByStatus(PostStatusEnum.DRAFT.getCode()));
|
||||
|
@ -180,7 +183,7 @@ public class PostController extends BaseController {
|
|||
@RequestParam("tagList") String tagList) {
|
||||
//old data
|
||||
final Post oldPost = postService.fetchById(post.getPostId()).orElse(new Post());
|
||||
BeanUtils.updateProperties(oldPost,post);
|
||||
BeanUtils.updateProperties(oldPost, post);
|
||||
post.setPostContent(MarkdownUtils.renderMarkdown(post.getPostContentMd()));
|
||||
if (null == post.getPostDate()) {
|
||||
post.setPostDate(new Date());
|
||||
|
@ -308,7 +311,7 @@ public class PostController extends BaseController {
|
|||
final String blogUrl = OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp());
|
||||
final List<PostViewOutputDTO> posts = postService.findAll(PostTypeEnum.POST_TYPE_POST.getDesc())
|
||||
.stream()
|
||||
.map(post -> new PostViewOutputDTO().convertFrom(post))
|
||||
.map(post -> (PostViewOutputDTO) new PostViewOutputDTO().convertFrom(post))
|
||||
.collect(Collectors.toList());
|
||||
final StringBuilder urls = new StringBuilder();
|
||||
for (PostViewOutputDTO post : posts) {
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
package cc.ryanc.halo.web.controller.api;
|
||||
|
||||
import cc.ryanc.halo.model.domain.Post;
|
||||
import cc.ryanc.halo.model.domain.User;
|
||||
import cc.ryanc.halo.model.dto.PostDetailOutputDTO;
|
||||
import cc.ryanc.halo.model.params.JournalParam;
|
||||
import cc.ryanc.halo.service.PostService;
|
||||
import cc.ryanc.halo.service.UserService;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import static cc.ryanc.halo.model.support.HaloConst.USER_SESSION_KEY;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 日志 API
|
||||
|
@ -21,8 +27,12 @@ public class ApiJournalController {
|
|||
|
||||
private final PostService postService;
|
||||
|
||||
public ApiJournalController(PostService postService) {
|
||||
private final UserService userService;
|
||||
|
||||
public ApiJournalController(PostService postService,
|
||||
UserService userService) {
|
||||
this.postService = postService;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,9 +43,12 @@ public class ApiJournalController {
|
|||
*/
|
||||
@PostMapping
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public PostDetailOutputDTO save(@RequestBody JournalParam journalParam) {
|
||||
public PostDetailOutputDTO save(@RequestBody JournalParam journalParam, HttpSession session) {
|
||||
|
||||
User user = userService.findUser();
|
||||
|
||||
Post post = journalParam.convertTo();
|
||||
post.setUser(user);
|
||||
|
||||
return new PostDetailOutputDTO().convertFrom(postService.create(post));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package cc.ryanc.halo.model.dto.base;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class InputConverterTest {
|
||||
|
||||
@Test
|
||||
public void convertToTest() {
|
||||
TestInputDTO inputDTO = new TestInputDTO("test_name");
|
||||
|
||||
TestDomain domain = inputDTO.convertTo();
|
||||
assertThat(domain.getName(), equalTo("test_name"));
|
||||
assertNull(domain.getAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateTest() {
|
||||
TestInputDTO inputDTO = new TestInputDTO("test_input_dto_name");
|
||||
|
||||
TestDomain domain = new TestDomain("test_domain_name", 10);
|
||||
|
||||
inputDTO.update(domain);
|
||||
|
||||
assertThat(domain.getName(), equalTo("test_input_dto_name"));
|
||||
assertThat(domain.getAge(), equalTo(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subConvertToTest() {
|
||||
SubTestInputDTO subTestInputDTO = new SubTestInputDTO();
|
||||
subTestInputDTO.setName("test_name");
|
||||
subTestInputDTO.setAge(10);
|
||||
|
||||
TestDomain domain = subTestInputDTO.convertTo();
|
||||
|
||||
assertThat(domain.getName(), equalTo("test_name"));
|
||||
assertThat(domain.getAge(), equalTo(10));
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class TestDomain {
|
||||
|
||||
private String name;
|
||||
|
||||
private Integer age;
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class TestInputDTO implements InputConverter<TestDomain>, Serializable {
|
||||
|
||||
private String name;
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class SubTestInputDTO extends TestInputDTO {
|
||||
|
||||
private Integer age;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package cc.ryanc.halo.model.dto.base;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Output converter test.
|
||||
*
|
||||
* @author johnniang
|
||||
*/
|
||||
public class OutputConverterTest {
|
||||
|
||||
@Test
|
||||
public void convertFromTest() {
|
||||
TestDomain domain = new TestDomain("test_domain_name", 10);
|
||||
|
||||
TestOutputDTO testOutputDTO = new TestOutputDTO().convertFrom(domain);
|
||||
|
||||
assertThat(testOutputDTO.getName(), equalTo("test_domain_name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertFromSubTest() {
|
||||
TestDomain domain = new TestDomain("test_domain_name", 10);
|
||||
|
||||
SubTestOutputDTO subTestOutputDTO = new SubTestOutputDTO().convertFrom(domain);
|
||||
|
||||
assertThat(subTestOutputDTO.getName(), equalTo("test_domain_name"));
|
||||
assertThat(subTestOutputDTO.getAge(), equalTo(10));
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class TestDomain {
|
||||
|
||||
private String name;
|
||||
|
||||
private Integer age;
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class TestOutputDTO implements OutputConverter<TestOutputDTO, TestDomain> {
|
||||
|
||||
private String name;
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class SubTestOutputDTO extends TestOutputDTO {
|
||||
private Integer age;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package cc.ryanc.halo.utils;
|
||||
|
||||
/**
|
||||
* Reflection utils test.
|
||||
*
|
||||
* @author johnniang
|
||||
*/
|
||||
public class ReflectionUtilsTest {
|
||||
|
||||
}
|
Loading…
Reference in New Issue