注解实体完成CURD操作

2023-03-20 00:09
2746
0

实体加个注解就不用写Controller 或者 Service ?

Q:为什么使用注解生成代码?

A:快捷方便(懒)。当然这些生成的代码基本都是CURD的简单操作。

准备工作

1.新建一个maven工程《demo》导入包如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.yyhouc</groupId>
    <artifactId>demo</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.google.auto.service</groupId>
            <artifactId>auto-service</artifactId>
            <version>1.0-rc2</version>
        </dependency>
        <dependency>
            <groupId>com.squareup</groupId>
            <artifactId>javapoet</artifactId>
            <version>1.13.0</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.23</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.23</version>
        </dependency>
       
    </dependencies>

    <repositories>
        <repository>
            <id>nexus-aliyun</id>
            <name>nexus-aliyun</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                    <!-- 不添加以下配置编译会报  "程序包 xxx 不可见" -->
                    <compilerArgs>
                        <arg>--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
                        <arg>--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
                        <arg>--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
                        <arg>--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
                        <arg>--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2编写注解类AutoCode

package com.yyhouc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * AutoCode
 * 根据实体在编译生成CURD接口
 * @author com.yyhouc
 * @since 2023/2/28
 * @version 1.0.0
 */
@Target({ElementType.TYPE})
//有效范围为CLASS 以前

@Retention(RetentionPolicy.CLASS)
public @interface AutoCoode {
    String value() default "";
    String mapper() default "";//未实现
    String service() default "";//未实现
    String controller() default "";//简单实现
}

3编写注解处理

package com.yyhouc.annotation;

import com.google.auto.service.AutoService;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;
import java.io.*;
import java.util.Set;

@SupportedAnnotationTypes("com.yyhouc.annotation.AutoCode")
@SupportedSourceVersion(SourceVersion.RELEASE_11)
@AutoService(javax.annotation.processing.Processor.class)
public class MyProcessor  extends AbstractProcessor {

    @Override
    public synchronized void init(ProcessingEnvironment env){
        super.init(env);
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        //遍历注解所有内容
        for (TypeElement typeElement : annotations) {
//        遍历所有类
            Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(typeElement);
            for (Element element : elements) {
                try {
                    genClass(element);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return true;
    }
    public void  genClass(Element e) throws IOException {
        //获取类名
        String className = e.getSimpleName().toString();
        //获取包名
        String packageName = processingEnv.getElementUtils().getPackageOf(e).getQualifiedName().toString();

        String path = packageName+"."+className+"Controller";
        //获取创建文件路径,根据package路径与类名
        JavaFileObject source = processingEnv.getFiler().createSourceFile(path);
        Writer writer = source.openWriter();
        //读取模板文件  
        String templatePath = this.getClass().getClassLoader().getResource("").getPath()+"/tpl/Controller.ftl";
        String templContent = getContent(templatePath);
        //templContent 替换   ${package}  ${className}
        templContent = templContent.replaceAll("\\$\\{package\\}", packageName);
        templContent = templContent.replaceAll("\\$\\{className\\}",className);
        writer.write(templContent);
        writer.flush();
        writer.close();
    }
    public String getContent(String path ){
        File file = new File(path);
        System.out.println(file.getAbsolutePath());
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(file));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        String st = "";
        String content = "";
        while (true){
            try {
                if (!((st = br.readLine()) != null)) break;
            } catch (IOException e) {
                e.printStackTrace();
            }
            content += st;
        }
        return content;
    }
}

4打包Maven 生成jar包

5在工作工程中引入  并且新建模板文件 

方式1本地maven 引入

		<dependency>
            <groupId>org.yyhouc</groupId>
            <artifactId>demo</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>system</scope>
            <systemPath>E:\yyhouc\demo\target\demo-1.0-SNAPSHOT.jar</systemPath>
        </dependency>

方式2本地引入

 idea 库文件引入

方式3建立自己的maven镜像仓库

模板文件 在resource/tpl/Controller.ftl

package ${package}.Controller;

import java.util.*;

public class ${className}Controller {
        public List list(){
            return new ArrayList();
        }
        public boolean save( Map<String,Object> map){
            return true;
        }

        public boolean update(  Map<String,Object> map){
            return true;
        }
        public boolean delete(  Map<String,Object> map){
            return true;
        }
}

6在实体上加入注解

package com.yyhouc;

import com.yyhouc.annotation.AutoCode;

@AutoCode
public class TestDemo {
    private String name;
}

 

7编译 maven package

现在 在tag下面就会生成 DemoController 的文件

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.yyhouc.Controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class DemoController {
    public DemoController() {
    }

    public List list() {
        return new ArrayList();
    }

    public boolean save(Map<String, Object> map) {
        return true;
    }

    public boolean update(Map<String, Object> map) {
        return true;
    }

    public boolean delete(Map<String, Object> map) {
        return true;
    }
}

结尾

 小工具用到的java编译原理的一部分,学习安卓的同学献丑了。 现在也没有系统的去搞。有兴趣的大佬可以自己搞一下。

用到了spi 当然我省事。没有去写MATEINFO/services直接上了谷歌的AutoService ,其实我搞这个东西也是因为以前研究过这个注解。

 

全部评论