参考了 ideabobo 的文章, https://blog.youkuaiyun.com/ideabobo/article/details/82465638
先看下实现的效果

第一步
到swagger 官网下载 https://github.com/swagger-api/swagger-ui.git 下载UI文件,然后把 文件中 dist 件文件夹里面所有的内容拷贝到你的jfinal项目中,目录参照我的即可,注意下
第二步
修改 pom.xml
新增依赖
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>jfinal</artifactId>
<version>${jfinal.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
第三步
新建一个 Controller
需要修改扫描的包,把里面的 BASE_PACKAGE 改为你自己的的接口包
package cn.yingguang.swagger;
import com.jfinal.core.Controller;
import com.google.gson.Gson;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.models.Contact;
import io.swagger.models.Info;
import io.swagger.models.License;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Response;
import io.swagger.models.Scheme;
import io.swagger.models.Swagger;
import io.swagger.models.Tag;
import io.swagger.models.parameters.Parameter;
import io.swagger.models.parameters.PathParameter;
import java.io.File;
import java.io.FileFilter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.eclipse.jetty.util.StringUtil;
public class SwaggerController extends Controller {
//设置需要扫描哪个包里面的类生产api
public static final String BASE_PACKAGE="cn.yingguang.index";
public void index() {
render("index.html");
}
public void api() {
Swagger doc = new Swagger();
Info info = new Info();
Contact contact = new Contact();
contact.setEmail("admin@bimfoo.com");
contact.setName("bimfoo");
contact.setUrl("http://www.baidu.com");
info.setDescription("项目接口的总体描述信息");
License license = new License();
license.setName("Apache 2.0");
license.setUrl("http://www.baidu.com");
info.setLicense(license);
info.setTitle("运营平台接口");
info.setTermsOfService("http://www.baidu.com");
info.setVersion("2.0");
info.setContact(contact);
List<Scheme> schemes = new ArrayList<>();
schemes.add(Scheme.HTTP);
schemes.add(Scheme.HTTPS);
Map<String, Path> paths = new HashMap<>();
Set<Class<?>> classSet = getClassSet(BASE_PACKAGE);
List<Tag> tags = new ArrayList<>();
for (Class<?> cls : classSet) {
if (cls.isAnnotationPresent(Api.class)) {
Api api = cls.getAnnotation(Api.class);
String[] apitags = api.tags();
String apiValue = api.value();
if (apitags.length > 0) {
for (String tag : apitags) {
Tag tagobj = new Tag();
tagobj.setName(tag);
tags.add(tagobj);
}
} else {
Tag tagobj = new Tag();
tagobj.setName(apiValue);
tags.add(tagobj);
}
Method[] methods = cls.getMethods();
for (Method method : methods) {
Annotation[] annotations = method.getAnnotations();
Path path = new Path();
for (Annotation annotation : annotations) {
// Class<?> aclass = annotation.annotationType();
Operation option = new Operation();
String opvalue = "";
if (method.isAnnotationPresent(ApiOperation.class)) {
ApiOperation opertion = method.getAnnotation(ApiOperation.class);
ArrayList<String> produces = new ArrayList<>();
String producesStr = opertion.produces();
produces.add(producesStr);
opvalue = opertion.value();
String notes = opertion.notes();
/*
* String consumesStr = opertion.consumes();
* String[] ptagsarray = opertion.tags();
*/
List<String> ptags = new ArrayList<>();
ptags.add(apitags[0]);
/*
* if(ptagsarray.length>0){ for(String
* tag:ptagsarray){ ptags.add(tag); } }
*/
option.setConsumes(new ArrayList<String>());
option.setDescription(notes);
option.setSummary(notes);
option.setTags(ptags);
}
List<Parameter> parameters = new ArrayList<>();
if (method.isAnnotationPresent(ApiImplicitParams.class)) {
ApiImplicitParams apiImplicitParams = method.getAnnotation(ApiImplicitParams.class);
ApiImplicitParam[] apiImplicitParamArray = apiImplicitParams.value();
for (ApiImplicitParam param : apiImplicitParamArray) {
PathParameter parameter = new PathParameter();
String in = param.paramType();
String name = param.name();
String value = param.value();
boolean required = param.required();
String dataType = param.dataType();
parameter.setType(dataType);
parameter.setDefaultValue("");
parameter.setDescription(value);
parameter.setRequired(required);
parameter.setIn(in);
parameter.setName(name);
parameters.add(parameter);
}
}
option.setParameters(parameters);
Map<String, Response> responseMap = new HashMap<>();
if (method.isAnnotationPresent(ApiResponses.class)) {
ApiResponses responses = method.getAnnotation(ApiResponses.class);
ApiResponse[] responseArray = responses.value();
for (ApiResponse response : responseArray) {
String code = response.code() + "";
String msg = response.message();
Response res = new Response();
res.setDescription(msg);
responseMap.put(code, res);
}
}
option.setResponses(responseMap);
path.setGet(option);
paths.put(opvalue, path);
}
}
doc.setSchemes(schemes);
doc.setSwagger("2.0");
// doc.setBasePath("/user");
doc.setInfo(info);
doc.setHost("localhost:8080");
doc.setTags(tags);
doc.setPaths(paths);
}
}
Gson gson = new Gson();
String json = gson.toJson(doc);
renderText(json);
}
/**
* 获取指定包名下所有类
*
* @param packageName
* @return
*/
public static Set<Class<?>> getClassSet(String packageName) {
Set<Class<?>> classSet = new HashSet<Class<?>>();
try {
Enumeration<URL> urls = getClassLoader().getResources(packageName.replace(".", "/"));
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url != null) {
String protocol = url.getProtocol();
if (protocol.equals("file")) {
String packagePath = url.getPath().replace("%20", " ");
addClass(classSet, packagePath, packageName);
} else if (protocol.equals("jar")) {
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
if (jarURLConnection != null) {
JarFile jarFile = jarURLConnection.getJarFile();
if (jarFile != null) {
Enumeration<JarEntry> jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String jarEntryName = jarEntry.getName();
if (jarEntryName.endsWith(".class")) {
String className = jarEntryName.substring(0, jarEntryName.lastIndexOf("."))
.replaceAll("/", ".");
doAddClass(classSet, className);
}
}
}
}
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return classSet;
}
/**
* 获取类加载器
*
* @return
*/
public static ClassLoader getClassLoader() {
return Thread.currentThread().getContextClassLoader();
}
private static void addClass(Set<Class<?>> classSet, String packagePath, String packageName) {
File[] files = new File(packagePath).listFiles(new FileFilter() {
public boolean accept(File file) {
return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
}
});
for (File file : files) {
String fileName = file.getName();
if (file.isFile()) {
String className = fileName.substring(0, fileName.lastIndexOf("."));
if (StringUtil.isNotBlank(packageName)) {
className = packageName + "." + className;
}
doAddClass(classSet, className);
} else {
String subPackagePath = fileName;
if (StringUtil.isNotBlank(packagePath)) {
subPackagePath = packagePath + "/" + subPackagePath;
}
String subPackageName = fileName;
if (StringUtil.isNotBlank(packageName)) {
subPackageName = packageName + "." + subPackageName;
}
addClass(classSet, subPackagePath, subPackageName);
}
}
}
private static void doAddClass(Set<Class<?>> classSet, String className) {
Class<?> cls = loadClass(className, false);
classSet.add(cls);
}
/**
* 加载类
*
* @param className
* @param isInitialized
* false 代表装载类的时候 不进行初始化工作[不会执行静态代码块]
* @return
*/
public static Class<?> loadClass(String className, boolean isInitialized) {
Class<?> cls;
try {
cls = Class.forName(className, isInitialized, getClassLoader());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
return cls;
}
}
第四步
配置路由
public void configRoute(Routes me) {
//推荐拆分方式 如果需要就解开注释 创建对应的 Routes
//me.add(new AdminRoutes());//配置后台管理系统路由
//me.add(new FrontRoutes());//配置网站前台路由
me.add(new ApiRoutes());//配置API访问路由
me.add(new SwaggerRoutes());
//me.add(new WechatRoutes());//配置微信端访问路由
//普通不拆分的方式配置 如下
//设置默认访问首页路由 可使用http://localhost:port 直接访问 如果80端口 port可以省略
me.add("/",IndexController.class);
}
import com.jfinal.config.Routes;
import cn.yingguang.swagger.SwaggerController;
public class SwaggerRoutes extends Routes{
@Override
public void config() {
setBaseViewPath("/static");
add("/swagger", SwaggerController.class);
}
}
第五步
修改 第一步中拷贝的文件夹中的 index.html 文件
修改 SwaggerUIBundle 下的请求的URL,改为 你 第三步中的 类 下的 SwaggerController api接口地址,
第六步
运行项目
swagger 注解参数 我这里给一个demo,大家可以模仿下
*****参数必须要 使用 paramType="query" 用 否则无法再页面上请求参数
import org.springframework.web.bind.annotation.RestController;
import com.jfinal.core.Controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
@Api(value="index",tags={"IndexController"})
@RestController
public class IndexController extends Controller {
/**
* 首页Action
*/
@ApiOperation(value = "/index", httpMethod = "POST", notes = "方法1")
@ApiImplicitParams({@ApiImplicitParam(paramType="query", required = false, name = "pname", value = "项目的名称",dataType="string"),
@ApiImplicitParam(paramType="query",required = false, name = "pname2", value = "项目的名称2",dataType="string")})
public void index() {
String params = getPara("pname");
String pname2 = getPara("pname2");
renderJson("{name:caiming,"+params+":"+pname2+"}");
}
@ApiOperation(value = "/getProjectByID", httpMethod = "POST", notes = "方法2")
@ApiImplicitParams({@ApiImplicitParam(paramType="query", required = true, name = "pname", value = "项目的名称",dataType="string"),
@ApiImplicitParam(paramType="query",required = true, name = "pname2", value = "项目的名称2",dataType="string")})
public void getProjectByID() {
String params = getPara("pname");
String pname2 = getPara("pname2");
renderJson("{name:caiming,"+params+":"+pname2+"}"); }
}