欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

spring boot 之使用mapstruct

程序员文章站 2022-07-26 10:05:56
最近在阅读swagger源码,当看到 springfox.documentation.swagger2.mappers.ModelMapper 类时,无意中看到该类上面使用的 org.mapstruct.Mapper 注解时,对这个注解一时竟想不出个所意然来。便打开百度搜索了一番,有关这个注解的文章... ......

  最近在阅读swagger源码,当看到 springfox.documentation.swagger2.mappers.modelmapper 类时,无意中看到该类上面使用的 org.mapstruct.mapper 注解时,对这个注解一时竟想不出个所意然来。便打开百度搜索了一番,有关这个注解的文章不是很多,从这些文章中了解到,这个注解跟jsr 269 有关,下面列出这个注解相关的文章链接。


 相关的文章链接:

  1.  mapstruct官网 http://mapstruct.org/
  2.  mapstruct github网址:https://github.com/mapstruct/mapstruct
  3. jsr 269: pluggable annotation processing api  https://jcp.org/en/jsr/detail?id=269
  4. 插入式注解处理api(pluggable annotation processing api)  https://blog.csdn.net/yczz/article/details/34116189
  5. 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 }

 

spring boot 之使用mapstruct

 


 修改之后的代码:

 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源文件。

spring boot 之使用mapstruct

 


 

示例代码: https://github.com/gittorlight/springboot-example/tree/master/example4