独立应用feign能够帮助我们解决什么样的问题或者带来什么好处呢。一方面是优雅,优雅的代码总是具有更好的可读性,这将意味着可能具有更好的维护性。另一方面是独立,独立意味着它可以不依赖繁琐的框架,意味着能够在更多的环境中得到应用。
1、建立一个基于maven的普通的Java项目,pom.xml配置如下
<dependencies>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>9.7.0</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
<version>9.7.0</version>
</dependency>
</dependencies>
2、使用到的一些注解
FeignService.java
package com.suntown.annotation;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FeignService{
}
??Url.java
package com.suntown.annotation;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Url{
public String value();
}
??Wired.java
??
package com.suntown.annotation;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Wired{
}
3、自动扫描package并管理feign接口类
FeignJust.java
package com.suntown;
import com.suntown.annotation.FeignService;
import com.suntown.annotation.Url;
import com.suntown.annotation.Wired;
import feign.Feign;
import feign.Request;
import feign.Retryer;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
import sun.net.www.protocol.file.FileURLConnection;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class FeignJust{
private static Map<Class,Object> actionMap = new HashMap<>();
private static Map<Class,Object> feignServiceMap = new HashMap<>();
public static <T> T getAction(Class<T> interClass){
return (T) actionMap.get(interClass);
}
public static <T> T action(Class<T> tClass,String url){
T action = Feign.builder()
.encoder(new GsonEncoder())
.decoder(new GsonDecoder())
.options(new Request.Options(1000, 3500))
.retryer(new Retryer.Default(5000, 5000, 3))
.target(
tClass,
url
);
return action;
}
public static String firstLower(String s){
return (char)(s.charAt(0) + 32) + s.substring(1);
}
public static void scanPackage(String packageName) {
try {
String packageNamePath = packageName.replace(".","\\");
URL url = FeignJust.class.getResource("FeignJust.class");
URLConnection urlConnection = url.openConnection();
if(urlConnection instanceof FileURLConnection){
FileURLConnection fileURLConnection = (FileURLConnection)urlConnection;
File rootFile = new File(FeignJust.class.getResource("/").toURI().getPath());
File dirFile = new File(rootFile.getAbsolutePath() + File.separator + packageNamePath);
File[] classesFile = dirFile.listFiles(new FilenameFilter() {
@Override
public boolean accept(File file, String s) {
return s.endsWith(".class");
}
});
for(File classFile : classesFile){
String classFilePath = classFile.getAbsolutePath();
String className = classFilePath.substring(rootFile.getAbsolutePath().length() + 1)
.replace("\\",".");
className = className.substring(0,className.length() - 6);
Class interClass = FeignJust.class.getClassLoader().loadClass(className);
Url urlAno = (Url)interClass.getAnnotation(Url.class);
if(urlAno!=null){
Object action = FeignJust.action(interClass,urlAno.value());
String classSimpleName = firstLower(interClass.getSimpleName());
actionMap.put(interClass,action);
}
}
}else if(urlConnection instanceof JarURLConnection){
JarURLConnection jarURLConnection = (JarURLConnection)urlConnection;
URL jarFileURL = jarURLConnection.getJarFileURL();
File fileJarFile = new File(jarFileURL.toURI().getPath());
JarFile jarFile = jarURLConnection.getJarFile();
Enumeration<JarEntry> it = jarFile.entries();
while(it.hasMoreElements()){
String className = it.nextElement().getName().replace("/",".");
if(className.endsWith(".class") && className.startsWith(packageName + ".")){
className = className.substring(0,className.length() - 6);
Class interClass = FeignJust.class.getClassLoader().loadClass(className);
Url urlAno = (Url)interClass.getAnnotation(Url.class);
if(urlAno!=null){
Object action = FeignJust.action(interClass,urlAno.value());
String classSimpleName = firstLower(interClass.getSimpleName());
actionMap.put(interClass,action);
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static <T> T getService(Class<T> interClass) {
return (T) feignServiceMap.get(interClass);
}
public static void scanServicePackage(String packageName) {
try {
String packageNamePath = packageName.replace(".","\\");
URL url = FeignJust.class.getResource("FeignJust.class");
URLConnection urlConnection = url.openConnection();
if(urlConnection instanceof FileURLConnection){
FileURLConnection fileURLConnection = (FileURLConnection)urlConnection;
File rootFile = new File(FeignJust.class.getResource("/").toURI().getPath());
File dirFile = new File(rootFile.getAbsolutePath() + File.separator + packageNamePath);
File[] classesFile = dirFile.listFiles(new FilenameFilter() {
@Override
public boolean accept(File file, String s) {
return s.endsWith(".class");
}
});
for(File classFile : classesFile){
String classFilePath = classFile.getAbsolutePath();
String className = classFilePath.substring(rootFile.getAbsolutePath().length() + 1)
.replace("\\",".");
className = className.substring(0,className.length() - 6);
Class interClass = FeignJust.class.getClassLoader().loadClass(className);
FeignService feignService = (FeignService)interClass.getAnnotation(FeignService.class);
if(feignService!=null){
Object serivce = FeignJust.serivce(interClass);
String classSimpleName = firstLower(interClass.getSimpleName());
if(serivce!=null){
Field[] fields = interClass.getDeclaredFields();
for(Field field : fields){
if(field.getAnnotation(Wired.class)!=null){
field.setAccessible(true);
Object action = getAction(field.getType());
if(action!=null){
field.set(serivce,action);
}
}
}
feignServiceMap.put(interClass, serivce);
}
}
}
}else if(urlConnection instanceof JarURLConnection){
JarURLConnection jarURLConnection = (JarURLConnection)urlConnection;
URL jarFileURL = jarURLConnection.getJarFileURL();
File fileJarFile = new File(jarFileURL.toURI().getPath());
JarFile jarFile = jarURLConnection.getJarFile();
Enumeration<JarEntry> it = jarFile.entries();
while(it.hasMoreElements()){
String className = it.nextElement().getName().replace("/",".");
if(className.endsWith(".class") && className.startsWith(packageName + ".")){
className = className.substring(0,className.length() - 6);
Class interClass = FeignJust.class.getClassLoader().loadClass(className);
Url urlAno = (Url)interClass.getAnnotation(Url.class);
if(urlAno!=null){
Object action = FeignJust.action(interClass,urlAno.value());
String classSimpleName = firstLower(interClass.getSimpleName());
actionMap.put(interClass,action);
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private static Object serivce(Class interClass) {
try {
return interClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
4、测试接口类 IBaseAction.java
package com.suntown.interaction;
import com.suntown.annotation.Url;
import feign.Headers;
import feign.RequestLine;
@Url("http://localhost:8089")
public interface IBaseAction{
@RequestLine("POST /login/login")
@Headers({"Content-Type: application/json","Accept: application/json"})
public Object login(Admin admin);
public static class Admin{
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
private String password;
}
}
5、feign接口的调用
package com.suntown;
import com.suntown.interaction.IBaseAction;
public class Main{
public static void main(String[] args){
FeignJust.scanPackage("com.suntown.interaction");
IBaseAction baseAction = FeignJust.getAction(IBaseAction.class);
IBaseAction.Admin admin = new IBaseAction.Admin();
admin.setUsername("admin");
admin.setPassword("123");
Object result = baseAction.login(admin);
System.out.println("class="+result.getClass()+","+result);
}
}
6、运行结果
|