注解实体完成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 ,其实我搞这个东西也是因为以前研究过这个注解。
全部评论