最近在閱讀swagger源碼,當看到 springfox.documentation.swagger2.mappers.ModelMapper 類時,無意中看到該類上面使用的 org.mapstruct.Mapper 注解時,對這個注解一時竟想不出個所意然來。便打開百度搜索了一番,有關這個注解的文章不是很多,從這些文章中了解到,這個注解跟JSR 269 有關,下面列出這個注解相關的文章鏈接。
相關的文章鏈接:
- mapstruct官網 http://mapstruct.org/
- mapstruct github網址:https://github.com/mapstruct/mapstruct
- JSR 269: Pluggable Annotation Processing API https://jcp.org/en/jsr/detail?id=269
- 插入式注解處理API(Pluggable Annotation Processing API) https://blog.csdn.net/yczz/article/details/34116189
- MapStruct實體間轉換快速入門 https://blog.csdn.net/lx_yoyo/article/details/75061614
當看完上面的幾篇的文章之后,對這個注解到底起何作用,仍然是一知半解。於是參照上面列表中的 MapStruct實體間轉換快速入門 ,當我把工程建好,copy完相關的代碼之后,根據文章的提示,執行mvn install(mvn compile)命令之后,沒有出現文章中提到的在 target\generated-sources\annotations 會自動生成PeopleMapperImpl.Java 源文件,反到是控制台打印出的日志信息提示編譯失敗,錯誤信息如下所示:
[INFO] ------------------------------------------------------------- [ERROR] COMPILATION ERROR : [INFO] ------------------------------------------------------------- [ERROR] /F:/java.ws.01/springboot-example/example4/src/main/java/com/github/torlight/sbex/PeopleMapper.java:[21,15] No property named "age" exists in source parameter(s). Did you mean "null"? [ERROR] /F:/java.ws.01/springboot-example/example4/src/main/java/com/github/torlight/sbex/PeopleMapper.java:[32,10] No property named "user.name" exists in source parameter(s). Did you mean "null"? [INFO] 2 errors [INFO] ------------------------------------------------------------- [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 5.951 s [INFO] Finished at: 2018-08-19T10:52:59+08:00 [INFO] Final Memory: 26M/282M [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.5.1:compile (default-compile) on project example4: Compilation failure: Compilation failure: [ERROR] /F:/java.ws.01/springboot-example/example4/src/main/java/com/github/torlight/sbex/PeopleMapper.java:[21,15] No property named "age" exists in source parameter(s). Did you mean "null"? [ERROR] /F:/java.ws.01/springboot-example/example4/src/main/java/com/github/torlight/sbex/PeopleMapper.java:[32,10] No property named "user.name" exists in source parameter(s). Did you mean "null"? [ERROR] -> [Help 1] org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.5.1:compile (default-compile) on project example4: Compilation failure at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:212) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80) at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51) at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128) at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307) at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193) at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106) at org.apache.maven.cli.MavenCli.execute(MavenCli.java:862) at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:286) at org.apache.maven.cli.MavenCli.main(MavenCli.java:197) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289) at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229) at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415) at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356) Caused by: org.apache.maven.plugin.compiler.CompilationFailureException: Compilation failure at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:972) at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:129) at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208) ... 20 more [ERROR] [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
當出現上面的錯誤之后,先是在網上找了一下,但沒有找到相關的資料,沒辦法只能靠自己解決了。查看工程的pom.xml文件,有用到maven-compiler-plugin 插件,看到該插件的配置項中mapstruct-processor ,心里也清楚當maven執行maven-compiler-plugin 插件中相關類的方法時,肯定會執行mapstruct-processor 中相關類的方法。可是不清楚具體會先從那個類的方法開始執行。
沒辦法,只能根據上面的異常提示信息,在maven源碼工程中一路跟蹤下來,發現錯誤源是當執行SourceReference類的getSourceEntries方法時觸發的。No property named "age" exists in source parameter(s). Did you mean "null"? 在被轉換的實體中找不到age屬性,可是在PeopleEntity 實體中本來就存在age屬性。原來報錯是因為getSourceEntries方法是通過反射讀取實體的get方法來獲取屬性,然后再進行屬性比較,怪不得會報錯。當找到報錯的原因之后,我把目光停留在源碼中的注釋 //constructor, getters, setters etc. 原來實體中的getter,setter 方法都被省略了。
1 package com.github.torlight.sbex;
2
3 public class PeopleEntity {
4 private Integer age;
5 private String name;
6 private String callNumber;
7 private String address;
8 private String email;
9
10 public PeopleEntity() {
11
12 }
13
14 public PeopleEntity(Integer age, String name, String callNumber, String address, String email) {
15 this.age = age;
16 this.name = name;
17 this.callNumber = callNumber;
18 this.address = address;
19 this.email = email;
20 }
21
22 //constructor, getters, setters etc.
23
24 }
修改之后的代碼:
1 package com.github.torlight.sbex; 2 3 public class PeopleDTO { 4 5 private String phoneNumber; 6 private String address; 7 private String email; 8 private User user; 9 10 public PeopleDTO() { 11 12 } 13 14 public PeopleDTO(String phoneNumber, String address, String email, User user) { 15 this.phoneNumber = phoneNumber; 16 this.address = address; 17 this.email = email; 18 this.user = user; 19 } 20 21 public String getPhoneNumber() { 22 return phoneNumber; 23 } 24 25 public void setPhoneNumber(String phoneNumber) { 26 this.phoneNumber = phoneNumber; 27 } 28 29 public String getAddress() { 30 return address; 31 } 32 33 public void setAddress(String address) { 34 this.address = address; 35 } 36 37 public String getEmail() { 38 return email; 39 } 40 41 public void setEmail(String email) { 42 this.email = email; 43 } 44 45 public User getUser() { 46 return user; 47 } 48 49 public void setUser(User user) { 50 this.user = user; 51 } 52 53 }
1 package com.github.torlight.sbex; 2 3 public class PeopleEntity { 4 private Integer age; 5 private String name; 6 private String callNumber; 7 private String address; 8 private String email; 9 10 public PeopleEntity() { 11 12 } 13 14 public PeopleEntity(Integer age, String name, String callNumber, String address, String email) { 15 this.age = age; 16 this.name = name; 17 this.callNumber = callNumber; 18 this.address = address; 19 this.email = email; 20 } 21 22 public Integer getAge() { 23 return age; 24 } 25 26 public void setAge(Integer age) { 27 this.age = age; 28 } 29 30 public String getName() { 31 return name; 32 } 33 34 public void setName(String name) { 35 this.name = name; 36 } 37 38 public String getCallNumber() { 39 return callNumber; 40 } 41 42 public void setCallNumber(String callNumber) { 43 this.callNumber = callNumber; 44 } 45 46 public String getAddress() { 47 return address; 48 } 49 50 public void setAddress(String address) { 51 this.address = address; 52 } 53 54 public String getEmail() { 55 return email; 56 } 57 58 public void setEmail(String email) { 59 this.email = email; 60 } 61 62 }
package com.github.torlight.sbex; public class User { private Integer age; private String name; public User() { } public User(Integer age, String name) { this.age = age; this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
執行mvn install(mvn compile)命令之后,控制台沒有提示報錯,但在 \target\generated-sources\annotations\ 文件夾下面還是空的,奇怪了? 先執行mvn clean 然后再執行 mvn install(mvn compile)之后,終於出現了PeopleMapperImpl.java 源文件。要確保 target\class 文件夾下面為空時,執行mvn install(mvn compile)命令才能生成java源文件。
示例代碼: https://github.com/gittorlight/springboot-example/tree/master/example4