Commit 463fbb4ddf8162dc71030e49a8cfea1b772c8f0d

Authored by 徐烜
1 parent 27b23e0d

1、添加MyObjectUtils工具类,添加方法查找对象中属性值为null的属性名列表

2、修改WorkDto的静态方法toWork,添加参数work,让workDto的属性整合到指定的work中
3、修改WorkServiceImpl,完善listWorks方法,修正updateWork方法,使用WorkDto的新的toWork方法整合Work对戏
4、删除WorkPageRequest
5、修改WorkQueryRequest属性,将workPageRequest的属性移入,删除不必要的属性,添加is_template属性时手动生成get/set方法,使用Lombok生成有问题
6、修改WorkUpdateRequest属性,删除createTime的初始化定义
7、修改WorkController,添加initBinder,适应前端以下划线命名的参数,传到后台不能转换成对象的问题
8、添加UploadController,值添加方法前端映射,方法实现后续再议
9、修改pom.xml,修改spring-boot-maven-plugin定义,添加<fork>false</fork>,解决不能debug的问题
... ... @@ -87,6 +87,9 @@
87 87 <plugin>
88 88 <groupId>org.springframework.boot</groupId>
89 89 <artifactId>spring-boot-maven-plugin</artifactId>
  90 + <configuration>
  91 + <fork>false</fork>
  92 + </configuration>
90 93 </plugin>
91 94 </plugins>
92 95 </build>
... ...
src/main/java/com/bsth/luban_springboot2/controller/UploadController.java 0 → 100644
  1 +package com.bsth.luban_springboot2.controller;
  2 +
  3 +import org.springframework.web.bind.annotation.PostMapping;
  4 +import org.springframework.web.bind.annotation.RequestMapping;
  5 +import org.springframework.web.bind.annotation.RequestParam;
  6 +import org.springframework.web.bind.annotation.RestController;
  7 +import org.springframework.web.multipart.MultipartFile;
  8 +
  9 +/**
  10 + * 上传文件控制器
  11 + * TODO:swagger标注后面再加
  12 + */
  13 +@RestController
  14 +@RequestMapping(value = "/upload")
  15 +public class UploadController {
  16 +
  17 + @PostMapping
  18 + public void upload(
  19 + @RequestParam(name = "files") MultipartFile file,
  20 + @RequestParam(name = "workId") Long workId) {
  21 + // TODO:后面再做上传
  22 +
  23 +
  24 + System.out.println(workId);
  25 + }
  26 +}
... ...
src/main/java/com/bsth/luban_springboot2/controller/WorkController.java
... ... @@ -2,19 +2,19 @@ package com.bsth.luban_springboot2.controller;
2 2  
3 3 import com.bsth.luban_springboot2.dto.WorkDto;
4 4 import com.bsth.luban_springboot2.dto.request.WorkCreateRequest;
5   -import com.bsth.luban_springboot2.dto.request.WorkPageRequest;
6 5 import com.bsth.luban_springboot2.dto.request.WorkQueryRequest;
7 6 import com.bsth.luban_springboot2.dto.request.WorkUpdateRequest;
8 7 import com.bsth.luban_springboot2.service.WorkService;
9 8 import org.springframework.beans.BeanUtils;
10 9 import org.springframework.beans.factory.annotation.Autowired;
11   -import org.springframework.data.domain.Page;
12 10 import org.springframework.data.domain.PageRequest;
13 11 import org.springframework.data.domain.Sort;
14 12 import org.springframework.http.HttpStatus;
  13 +import org.springframework.web.bind.WebDataBinder;
15 14 import org.springframework.web.bind.annotation.*;
16 15  
17 16 import javax.validation.Valid;
  17 +import java.util.List;
18 18  
19 19 /**
20 20 * 作品控制器(和鲁班h5后台strapi.js保持一致)。
... ... @@ -32,17 +32,33 @@ public class WorkController {
32 32 return this.workService.findWorkById(id);
33 33 }
34 34  
  35 + @InitBinder
  36 + protected void initBinder(WebDataBinder binder) {
  37 + // springMVC请求参数绑定对象属性时,忽略前缀是下划线的名字,如_ocx这种参数
  38 + // 1、不使用下划线
  39 + // 2、使用initBinder定义没有前缀
  40 + binder.setFieldMarkerPrefix(null);
  41 + }
  42 +
  43 + // 作品数量
  44 + @RequestMapping(value = "/count", method = RequestMethod.GET)
  45 + public Long countWork(@Valid @ModelAttribute WorkQueryRequest request) {
  46 + WorkDto workDto = WorkDto.getBuilder()
  47 + .setTemplate(request.isIs_template())
  48 + .build();
  49 + return this.workService.countWork(workDto);
  50 + }
  51 +
35 52 // 分页查询work
36 53 @RequestMapping(method = RequestMethod.GET)
37   - public Page<WorkDto> listWorks(
38   - @Valid @ModelAttribute WorkQueryRequest request,
39   - @Valid @ModelAttribute WorkPageRequest workPageRequest) {
  54 + public List<WorkDto> listWorks(@Valid @ModelAttribute WorkQueryRequest request) {
40 55 PageRequest pageRequest = PageRequest.of(
41   - workPageRequest.getPage(), workPageRequest.getSize(),
  56 + request.get_start(), request.get_limit(),
42 57 Sort.Direction.DESC, "createTime");
43 58  
44   - WorkDto workDto = new WorkDto();
45   - BeanUtils.copyProperties(request, workDto);
  59 + WorkDto workDto = WorkDto.getBuilder()
  60 + .setTemplate(request.isIs_template())
  61 + .build();
46 62 return this.workService.listWorks(workDto, pageRequest);
47 63 }
48 64  
... ... @@ -77,14 +93,6 @@ public class WorkController {
77 93 return this.workService.markWorkAsTemplate(id);
78 94 }
79 95  
80   - // 作品数量
81   - @RequestMapping(value = "/count", method = RequestMethod.GET)
82   - public Long countWork(@Valid @ModelAttribute WorkQueryRequest request) {
83   - WorkDto workDto = new WorkDto();
84   - BeanUtils.copyProperties(request, workDto);
85   - return this.workService.countWork(workDto);
86   - }
87   -
88 96 // 使用模版创建作品
89 97 @RequestMapping(value = "/use-template/{id}", method = RequestMethod.POST)
90 98 public WorkDto useTemplate(@PathVariable Long id) {
... ...
src/main/java/com/bsth/luban_springboot2/dto/WorkDto.java
1 1 package com.bsth.luban_springboot2.dto;
2 2  
3 3 import com.bsth.luban_springboot2.entity.Work;
  4 +import com.bsth.luban_springboot2.utils.MyObjectUtils;
4 5 import com.fasterxml.jackson.annotation.JsonProperty;
5 6 import com.fasterxml.jackson.core.JsonProcessingException;
6 7 import com.fasterxml.jackson.core.type.TypeReference;
7 8 import com.fasterxml.jackson.databind.ObjectMapper;
8 9 import org.springframework.beans.BeanUtils;
9   -import org.springframework.beans.BeanWrapper;
10   -import org.springframework.beans.BeanWrapperImpl;
11 10 import org.springframework.util.CollectionUtils;
12 11 import org.springframework.util.StringUtils;
13 12  
14 13 import java.io.Serializable;
15 14 import java.util.Date;
16   -import java.util.HashSet;
17 15 import java.util.List;
18   -import java.util.Set;
19 16  
20 17 /**
21 18 * 作品Dto。
... ... @@ -168,12 +165,27 @@ public class WorkDto implements Serializable {
168 165  
169 166 /**
170 167 * 转换成Work对象。
171   - * @param workDto
  168 + * @param work 原始work对象
  169 + * @param workDto 等待复制用的workDto
  170 + * @param ignoreNullProperties 是否忽略空值
172 171 * @return
173 172 */
174   - public static Work toWork(WorkDto workDto) {
175   - Work work = new Work();
176   - BeanUtils.copyProperties(workDto, work);
  173 + public static Work toWork(Work work, WorkDto workDto, boolean ignoreNullProperties) {
  174 + if (work == null) {
  175 + throw new RuntimeException("原始work对象为空!");
  176 + }
  177 +
  178 + if (ignoreNullProperties) {
  179 + List<String> emptyPropertyNames = MyObjectUtils.getNullValueProperties(workDto);
  180 + if (CollectionUtils.isEmpty(emptyPropertyNames)) {
  181 + BeanUtils.copyProperties(workDto, work);
  182 + } else {
  183 + String[] result = new String[emptyPropertyNames.size()];
  184 + BeanUtils.copyProperties(workDto, work, (String[]) emptyPropertyNames.toArray(result));
  185 + }
  186 + } else {
  187 + BeanUtils.copyProperties(workDto, work);
  188 + }
177 189 if (!CollectionUtils.isEmpty(workDto.getPages())) {
178 190 ObjectMapper objectMapper = new ObjectMapper();
179 191 try {
... ... @@ -184,8 +196,10 @@ public class WorkDto implements Serializable {
184 196 }
185 197  
186 198 }
  199 +
187 200 return work;
188 201 }
  202 +
189 203 public static Builder getBuilder() {
190 204 return new Builder();
191 205 }
... ... @@ -278,42 +292,22 @@ public class WorkDto implements Serializable {
278 292 /**
279 293 * 使用work对象直接复制属性。
280 294 * @param work
  295 + * @param ignoreNullProperties 是否忽略空值
281 296 * @return
282 297 */
283   - public Builder setPropertyFromWork(Work work) {
284   - setPropertyFromWork(work, false);
285   - return this;
286   - }
287   - /**
288   - * 使用work对象直接复制属性(忽略空值属性)。
289   - * @param work
290   - * @return
291   - */
292   - public Builder setPropertyFromWorkIgnoreNullProperties(Work work) {
293   - setPropertyFromWork(work, true);
294   - return this;
295   - }
296   -
297   - private void setPropertyFromWork(Work work, boolean ignoreNullProperties) {
  298 + public Builder setPropertyFromWork(Work work, boolean ignoreNullProperties) {
298 299 if (ignoreNullProperties) {
299   - // 查找空值属性名数组
300   - final BeanWrapper src = new BeanWrapperImpl(work);
301   - java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
302   - Set emptyNames = new HashSet();
303   - for(java.beans.PropertyDescriptor pd : pds) {
304   - //check if value of this property is null then add it to the collection
305   - Object srcValue = src.getPropertyValue(pd.getName());
306   - if (srcValue == null) {
307   - emptyNames.add(pd.getName());
308   - }
  300 + List<String> emptyPropertyNames = MyObjectUtils.getNullValueProperties(work);
  301 + if (CollectionUtils.isEmpty(emptyPropertyNames)) {
  302 + BeanUtils.copyProperties(work, this);
  303 + } else {
  304 + String[] result = new String[emptyPropertyNames.size()];
  305 + BeanUtils.copyProperties(work, this, (String[]) emptyPropertyNames.toArray(result));
309 306 }
310   - String[] result = new String[emptyNames.size()];
311   - BeanUtils.copyProperties(work, this, (String[]) emptyNames.toArray(result));
312   -
313 307 } else {
314 308 BeanUtils.copyProperties(work, this);
315 309 }
316   - if (!StringUtils.hasText(work.getPages())) {
  310 + if (StringUtils.hasText(work.getPages())) {
317 311 ObjectMapper objectMapper = new ObjectMapper();
318 312 TypeReference<List<Object>> type = new TypeReference<List<Object>>() {};
319 313 try {
... ... @@ -325,6 +319,7 @@ public class WorkDto implements Serializable {
325 319 }
326 320  
327 321 }
  322 + return this;
328 323 }
329 324  
330 325 public WorkDto build() {
... ...
src/main/java/com/bsth/luban_springboot2/dto/request/WorkPageRequest.java deleted 100644 → 0
1   -package com.bsth.luban_springboot2.dto.request;
2   -
3   -import com.fasterxml.jackson.annotation.JsonProperty;
4   -import lombok.Data;
5   -
6   -/**
7   - * 分页请求。
8   - */
9   -@Data
10   -public class WorkPageRequest {
11   - /** 第几页(从0开始) */
12   - @JsonProperty(value = "_start")
13   - private Integer page;
14   - /** 每页记录数 */
15   - @JsonProperty(value = "_limit")
16   - private Integer size;
17   -}
src/main/java/com/bsth/luban_springboot2/dto/request/WorkQueryRequest.java
1 1 package com.bsth.luban_springboot2.dto.request;
2 2  
3   -import com.fasterxml.jackson.annotation.JsonProperty;
4 3 import lombok.Data;
5 4  
6 5 /**
... ... @@ -8,13 +7,17 @@ import lombok.Data;
8 7 */
9 8 @Data
10 9 public class WorkQueryRequest {
11   - private String title;
  10 + private boolean is_template;
  11 + /** 每页记录数 */
  12 + private Integer _limit;
  13 + /** 第几页(从0开始) */
  14 + private Integer _start;
12 15  
13   - private String description;
  16 + public boolean isIs_template() {
  17 + return is_template;
  18 + }
14 19  
15   - @JsonProperty(value = "is_publish")
16   - private boolean publish = false;
17   -
18   - @JsonProperty(value = "is_template")
19   - private boolean template = false;
  20 + public void setIs_template(boolean is_template) {
  21 + this.is_template = is_template;
  22 + }
20 23 }
... ...
src/main/java/com/bsth/luban_springboot2/dto/request/WorkUpdateRequest.java
... ... @@ -23,7 +23,7 @@ public class WorkUpdateRequest {
23 23 private List<Object> pages;
24 24  
25 25 @JsonProperty(value = "create_at")
26   - private Date createTime = new Date();
  26 + private Date createTime;
27 27  
28 28 @JsonProperty(value = "update_at")
29 29 private Date updateTime = new Date();
... ...
src/main/java/com/bsth/luban_springboot2/entity/Work.java
... ... @@ -93,4 +93,5 @@ public class Work implements Serializable {
93 93 @org.hibernate.annotations.ForeignKey(name = "none")
94 94 private Set<WorkForm> workForms = new HashSet<>();
95 95  
  96 +
96 97 }
... ...
src/main/java/com/bsth/luban_springboot2/service/WorkService.java
1 1 package com.bsth.luban_springboot2.service;
2 2  
3 3 import com.bsth.luban_springboot2.dto.WorkDto;
4   -import org.springframework.data.domain.Page;
5 4 import org.springframework.data.domain.Pageable;
6 5  
  6 +import java.util.List;
  7 +
7 8 /**
8 9 * 作品Service。
9 10 */
... ... @@ -15,7 +16,7 @@ public interface WorkService {
15 16 * @param pageable
16 17 * @return
17 18 */
18   - Page<WorkDto> listWorks(WorkDto workDto, Pageable pageable);
  19 + List<WorkDto> listWorks(WorkDto workDto, Pageable pageable);
19 20  
20 21 /**
21 22 * 创建work。
... ...
src/main/java/com/bsth/luban_springboot2/service/impl/WorkServiceImpl.java
... ... @@ -14,6 +14,7 @@ import org.springframework.transaction.annotation.Propagation;
14 14 import org.springframework.transaction.annotation.Transactional;
15 15  
16 16 import java.util.Date;
  17 +import java.util.List;
17 18 import java.util.Optional;
18 19  
19 20 /**
... ... @@ -25,18 +26,33 @@ public class WorkServiceImpl implements WorkService {
25 26 private WorkRepo workRepo;
26 27  
27 28 @Override
28   - public Page<WorkDto> listWorks(WorkDto workDto, Pageable pageable) {
29   - // TODO:暂无业务驱动
  29 + public Long countWork(WorkDto workDto) {
  30 + Work work = WorkDto.toWork(new Work(), workDto, false);
  31 + Example<Work> example = Example.of(work);
  32 + return this.workRepo.count(example);
  33 + }
  34 +
  35 + @Override
  36 + public List<WorkDto> listWorks(WorkDto workDto, Pageable pageable) {
  37 + Work work = WorkDto.toWork(new Work(), workDto, false);
  38 + Example<Work> example = Example.of(work);
  39 + Page<Work> workPage = this.workRepo.findAll(example, pageable);
  40 + Page<WorkDto> workDtoPage = workPage.map((work_source) -> {
  41 + WorkDto workDto_convert = WorkDto.getBuilder()
  42 + .setPropertyFromWork(work_source, false)
  43 + .build();
  44 + return workDto_convert;
  45 + });
30 46  
31   - return null;
  47 + return workDtoPage.getContent();
32 48 }
33 49  
34 50 @Override
35 51 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
36 52 public WorkDto createWork(WorkDto workDto) {
37   - Work work = WorkDto.toWork(workDto);
  53 + Work work = WorkDto.toWork(new Work(), workDto, true);
38 54 work = this.workRepo.save(work);
39   - return WorkDto.getBuilder().setPropertyFromWork(work).build();
  55 + return WorkDto.getBuilder().setPropertyFromWork(work, false).build();
40 56 }
41 57  
42 58 @Override
... ... @@ -47,15 +63,10 @@ public class WorkServiceImpl implements WorkService {
47 63 if (work == null) {
48 64 return null;
49 65 }
50   -
51   - WorkDto updateWorkDto = WorkDto
52   - .getBuilder()
53   - .setPropertyFromWorkIgnoreNullProperties(work)
54   - .setUpdateTime(new Date())
55   - .build();
56   - Work updateWork = WorkDto.toWork(updateWorkDto);
  66 + Work updateWork = WorkDto.toWork(work, workDto, true);
  67 + updateWork.setUpdateTime(new Date());
57 68 updateWork = this.workRepo.save(updateWork);
58   - return WorkDto.getBuilder().setPropertyFromWork(updateWork).build();
  69 + return WorkDto.getBuilder().setPropertyFromWork(updateWork, false).build();
59 70 }
60 71  
61 72 @Override
... ... @@ -65,7 +76,7 @@ public class WorkServiceImpl implements WorkService {
65 76 if (work == null) {
66 77 return null;
67 78 } else {
68   - return WorkDto.getBuilder().setPropertyFromWork(work).build();
  79 + return WorkDto.getBuilder().setPropertyFromWork(work, false).build();
69 80 }
70 81 }
71 82  
... ... @@ -79,7 +90,7 @@ public class WorkServiceImpl implements WorkService {
79 90 } else {
80 91 WorkDto workDto = WorkDto
81 92 .getBuilder()
82   - .setPropertyFromWorkIgnoreNullProperties(work)
  93 + .setPropertyFromWork(work, false)
83 94 .build();
84 95 this.workRepo.deleteById(id);
85 96 return workDto;
... ... @@ -98,14 +109,7 @@ public class WorkServiceImpl implements WorkService {
98 109 work.setTemplate(true);
99 110 work.setUpdateTime(new Date());
100 111 work = this.workRepo.save(work);
101   - return WorkDto.getBuilder().setPropertyFromWork(work).build();
102   - }
103   -
104   - @Override
105   - public Long countWork(WorkDto workDto) {
106   - Work work = WorkDto.toWork(workDto);
107   - Example<Work> example = Example.of(work);
108   - return this.workRepo.count(example);
  112 + return WorkDto.getBuilder().setPropertyFromWork(work, false).build();
109 113 }
110 114  
111 115 @Override
... ... @@ -118,13 +122,15 @@ public class WorkServiceImpl implements WorkService {
118 122 }
119 123 WorkDto templateWorkDto = WorkDto
120 124 .getBuilder()
121   - .setPropertyFromWork(work)
  125 + .setPropertyFromWork(work, false)
122 126 .setId(null)
123 127 .setTemplate(false)
124 128 .setPublish(false)
  129 + .setCreateTime(new Date())
  130 + .setUpdateTime(new Date())
125 131 .build();
126   - Work newWork = WorkDto.toWork(templateWorkDto);
  132 + Work newWork = WorkDto.toWork(new Work(), templateWorkDto, false);
127 133 newWork = this.workRepo.save(newWork);
128   - return WorkDto.getBuilder().setPropertyFromWork(newWork).build();
  134 + return WorkDto.getBuilder().setPropertyFromWork(newWork, false).build();
129 135 }
130 136 }
... ...
src/main/java/com/bsth/luban_springboot2/utils/MyObjectUtils.java 0 → 100644
  1 +package com.bsth.luban_springboot2.utils;
  2 +
  3 +import org.springframework.beans.BeanWrapper;
  4 +import org.springframework.beans.BeanWrapperImpl;
  5 +
  6 +import java.beans.PropertyDescriptor;
  7 +import java.util.ArrayList;
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * 对象工具类。
  12 + */
  13 +public class MyObjectUtils {
  14 + /**
  15 + * 获取对象中属性值为null的属性名列表。
  16 + * @param obj
  17 + * @return
  18 + */
  19 + public static List<String> getNullValueProperties(Object obj) {
  20 + List<String> emptyPropertyNames = new ArrayList<>();
  21 + final BeanWrapper src = new BeanWrapperImpl(obj);
  22 + PropertyDescriptor[] pds = src.getPropertyDescriptors();
  23 + for (PropertyDescriptor pd : pds) {
  24 + Object srcValue = src.getPropertyValue(pd.getName());
  25 + if (srcValue == null) {
  26 + emptyPropertyNames.add(pd.getName());
  27 + }
  28 + }
  29 + return emptyPropertyNames;
  30 + }
  31 +}
... ...
src/main/resources/logback-spring.xml
... ... @@ -23,11 +23,6 @@
23 23 <appender-ref ref="STDOUT" />
24 24 </logger>
25 25  
26   - <logger name="com.xuxuan.hotel_service"
27   - level="DEBUG" additivity="false">
28   - <appender-ref ref="STDOUT" />
29   - </logger>
30   -
31 26 <root level="INFO">
32 27 <appender-ref ref="STDOUT" />
33 28 </root>
... ...
src/test/java/com/bsth/luban_springboot2/LubanSpringboot2ServiceTests.java
1 1 package com.bsth.luban_springboot2;
2 2  
3   -import com.bsth.luban_springboot2.dto.request.WorkPageRequest;
  3 +import com.bsth.luban_springboot2.dto.request.WorkQueryRequest;
4 4 import com.fasterxml.jackson.databind.ObjectMapper;
5 5 import org.junit.jupiter.api.DisplayName;
6 6 import org.junit.jupiter.api.Test;
... ... @@ -34,13 +34,14 @@ class LubanSpringboot2ServiceTests extends BaseTest_junit5 {
34 34 @Test
35 35 void contextLoads() throws Exception {
36 36 // 测试@JsonProperty
37   - WorkPageRequest workPageRequest = new WorkPageRequest();
38   - workPageRequest.setPage(0);
39   - workPageRequest.setSize(10);
40   - LOG.info("json={}", new ObjectMapper().writeValueAsString(workPageRequest));
41   -
42   - String json = "{\"_start\":0,\"_limit\":10}";
43   - LOG.info("object={}", new ObjectMapper().readValue(json, WorkPageRequest.class).toString());
  37 + WorkQueryRequest workQueryRequest = new WorkQueryRequest();
  38 + workQueryRequest.setIs_template(true);
  39 + workQueryRequest.set_start(0);
  40 + workQueryRequest.set_limit(10);
  41 + LOG.info("json={}", new ObjectMapper().writeValueAsString(workQueryRequest));
  42 +
  43 + String json = "{\"is_template\": true,\"_start\":0,\"_limit\":10}";
  44 + LOG.info("object={}", new ObjectMapper().readValue(json, WorkQueryRequest.class).toString());
44 45  
45 46 }
46 47  
... ...