public class SwaggerController extends Controller {
private static Ret swagger = null;
/**
* 首页的处理
*/
public void index() {
this.redirect("/lib/swagger/index.html");
}
/**
*
*/
public void json() throws NoSuchFieldException, IllegalAccessException {
//https://github.com/swagger-api/swagger-ui
if (!FrameworkConfig.SWAGGER_ENABLE && !FrameworkConfig.DEV_MODE) {
this.renderJson(Ret.fail("禁止访问"));
return;
}
if (swagger == null) {
synchronized (this.getClass()) {
if (swagger == null) {
swagger = Ret.ok();
initSwagger(swagger);
}
}
}
this.renderJson(swagger);
}
private void initSwagger(Ret swagger) throws NoSuchFieldException, IllegalAccessException {
Field actionMappingField = JFinal.class.getDeclaredField("actionMapping");
actionMappingField.setAccessible(true);
ActionMapping actionMapping = (ActionMapping) actionMappingField.get(JFinal.me());
Field mappingField = ActionMapping.class.getDeclaredField("mapping");
mappingField.setAccessible(true);
Map<String, Action> actions = (Map<String, Action>) mappingField.get(actionMapping);
Map<? extends Class<? extends Controller>, List<Action>> controllerActionsMap = actions.stream().collect(Collectors.groupingBy(Action::getControllerClass));
List<Kv> tags = new ArrayList<>();
Map<String, Kv> paths = new LinkedHashMap<>();
for (Map.Entry<? extends Class<? extends Controller>, List<Action>> entry : controllerActionsMap.entrySet()) {
Class<? extends Controller> controller = entry.getKey();
List<Action> controllerActions = entry.getValue();
RouteMapping routeMapping = controller.getAnnotation(RouteMapping.class);
if (routeMapping == null) {
continue;
}
String routePath = routeMapping.value().startsWith("/") ? routeMapping.value() : "/" + routeMapping.value();
if (controllerActions.stream().noneMatch(e -> e.getMethod().getAnnotation(ApiName.class) != null)) {
continue;
}
tags.add(Kv.by("name", routePath).set("description", routeMapping.name()));
controllerActions.sort((Action first, Action second) -> {
String firstMethodName = first.getMethodName();
String secondMethodName = second.getMethodName();
return getMethodIndex(firstMethodName) - getMethodIndex(secondMethodName);
});
for (Action action : controllerActions) {
Method method = action.getMethod();
ApiName apiName = method.getAnnotation(ApiName.class);
if (apiName == null) {
continue;
}
Parameter[] paras = method.getParameters();
Class<?>[] parameterTypes = method.getParameterTypes();
List<Kv> parameters = new ArrayList<>();
ApiParams apiParams = method.getAnnotation(ApiParams.class);
if (apiParams != null) {
for (ApiParam apiParam : apiParams.value()) {
Class<?> parameterType = apiParam.type();
if (parameterType.equals(PageVo.class)) {
addPageParameter(parameters);
continue;
}
String typeName = parameterType.getSimpleName().toLowerCase();
Kv parameter = Kv.by("name", apiParam.name())
.set("in", "formData")
.set("description", apiParam.value())
.set("type", (typeName.equals(UploadFile.class.getSimpleName().toLowerCase()) || typeName.equals(UploadFileBean.class.getSimpleName().toLowerCase()))
? "file" : typeName);
parameter.set("required", apiParam.required());
parameters.add(parameter);
}
} else {
for (int i = 0; i < paras.length; i++) {
Parameter para = paras[i];
Para paraAnno = para.getAnnotation(Para.class);
String name = Optional.ofNullable(paraAnno).map(Para::value).filter(e -> !Para.NULL_VALUE.equals(e)).orElse(para.getName());
ApiParam apiParam = para.getAnnotation(ApiParam.class);
Class<?> parameterType = parameterTypes[i];
if (parameterType.equals(PageVo.class)) {
addPageParameter(parameters);
continue;
}
String typeName = parameterType.getSimpleName().toLowerCase();
Kv parameter = Kv.by("name", name)
.set("in", "formData")
.set("description", apiParam == null ? name : apiParam.value())
.set("type", (typeName.equals(UploadFile.class.getSimpleName().toLowerCase()) || typeName.equals(UploadFileBean.class.getSimpleName().toLowerCase()))
? "file" : typeName);
if (apiParam != null) {
parameter.set("required", apiParam.required());
}
parameters.add(parameter);
}
}
Kv responses = Kv.by("200", new Kv());
Kv post = Kv.by("tags", Arrays.asList(routePath))
.set("description", apiName.value() + "(" + action.getActionKey() + ")")
.set("parameters", parameters)
.set("consumes", Arrays.asList("application/x-www-form-urlencoded"))
.set("produces", Arrays.asList("application/json"))
.set("responses", responses);
Deprecated annotation = method.getAnnotation(Deprecated.class);
if (annotation != null) {
post.set("deprecated", true);
}
paths.put(action.getActionKey(), Kv.by("post", post));
}
}
tags.sort(Comparator.comparing(o -> o.getStr("name")));
List<String> descriptions = new ArrayList<>();
descriptions.add("token名称:" + FrameworkConst.TOKEN_NAME);
swagger.set("schemes", Arrays.asList("HTTP", "HTTPS"))
.set("swagger", "2.0")
.set("basePath", "")
.set("info", Kv.by("version", "3.0").set("title", "至道Api").set("description", StrKit.join(descriptions, ";")))
.set("tags", tags)
.set("paths", paths)
;
}
private void addPageParameter(List<Kv> parameters) {
Kv pageNumber = Kv.by("name", "offset")
.set("in", "formData")
.set("description", "数据偏移量")
.set("type", Integer.class.getSimpleName().toLowerCase());
parameters.add(pageNumber);
Kv pageSize = Kv.by("name", "limit")
.set("in", "formData")
.set("description", "每页显示的条数")
.set("type", Integer.class.getSimpleName().toLowerCase());
parameters.add(pageSize);
}
private int getMethodIndex(String methodName) {
if (methodName.startsWith("index")) {
return 1;
}
if (methodName.startsWith("list")) {
return 2;
}
if (methodName.startsWith("page")) {
return 3;
}
if (methodName.startsWith("add")) {
return 4;
}
if (methodName.startsWith("save")) {
return 5;
}
if (methodName.startsWith("edit")) {
return 6;
}
if (methodName.startsWith("update")) {
return 7;
}
if (methodName.startsWith("delete")) {
return 8;
}
return 10;
}
}@RouteMapping(value = "/stayApply", name = "留宿申请", viewPath = "/_admin/stayApply")
public class StayApplyController extends AdminBaseController {
private static StayApplyServiceImpl stayApplyService = Aop.get(StayApplyServiceImpl.class);
@ApiName("初始化参数")
public void index() {
Ret ret = Ret.ok();
this.renderJson(ret);
}
@ApiName("列表(分页)")
public void list(PageVo pageVo) {
Page<StayApply> page = stayApplyService.page(this.getUserLogin(), pageVo);
this.renderJson(Ret.page(page));
}
@ApiName("打开新增")
public void add() {
this.renderJson(Ret.ok());
}
@ApiName("保存")
//@Before(StayApplyValidator.class)
public void save(
@ApiParam(value = "表格id", required = true) Integer tableId,
@ApiParam(value = "内容", required = true) String content,
@ApiParam(value = "内容", required = true) Integer contentId,
@ApiParam(value = "状态", required = true) Integer status,
@ApiParam(value = "年份", required = false) Integer year,
@ApiParam(value = "学期", required = false) Integer term,
@ApiParam(value = "名称", required = true) String name,
@ApiParam(value = "留宿开始时间", required = true) Date beginTime,
@ApiParam(value = "留宿结束时间", required = true) Date endTime
) {
StayApply stayApply = new StayApply();
stayApply.setTableId(tableId);
stayApply.setContent(content);
stayApply.setContentId(contentId);
stayApply.setStatus(status);
stayApply.setYear(year);
stayApply.setTerm(term);
stayApply.setName(name);
stayApply.setBeginTime(beginTime);
stayApply.setEndTime(endTime);
stayApplyService.save(this.getUserLogin(), stayApply);
this.renderJson(Ret.saveOk());
}
@ApiName("打开编辑")
public void edit(@ApiParam(value = "唯一身份id", required = true) Integer id) {
StayApply stayApply = stayApplyService.findById(this.getUserLogin(), id);
this.renderJson(Ret.ok().set("value", stayApply));
}
@ApiName("更新")
//@Before(StayApplyValidator.class)
public void update(
@ApiParam(value = "id", required = true) Integer id,
@ApiParam(value = "表格id", required = true) Integer tableId,
@ApiParam(value = "内容", required = true) String content,
@ApiParam(value = "内容", required = true) Integer contentId,
@ApiParam(value = "状态", required = true) Integer status,
@ApiParam(value = "年份", required = false) Integer year,
@ApiParam(value = "学期", required = false) Integer term,
@ApiParam(value = "名称", required = true) String name,
@ApiParam(value = "留宿开始时间", required = true) Date beginTime,
@ApiParam(value = "留宿结束时间", required = true) Date endTime
) {
StayApply stayApply = new StayApply();
stayApply.setId(id);
stayApply.setTableId(tableId);
stayApply.setContent(content);
stayApply.setContentId(contentId);
stayApply.setStatus(status);
stayApply.setYear(year);
stayApply.setTerm(term);
stayApply.setName(name);
stayApply.setBeginTime(beginTime);
stayApply.setEndTime(endTime);
stayApplyService.update(this.getUserLogin(),stayApply);
this.renderJson(Ret.updateOK());
}
@ApiName("删除")
public void delete(@ApiParam(value = "唯一身份id", required = true) Integer id) {
stayApplyService.delete(this.getUserLogin(), id);
this.renderJson(Ret.deleteOk());
}@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiName {
String value();
}@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiParam {
String value() default "";
boolean required() default false;
String name() default "";
Class<?> type() default Void.class;
}如果需要非空判断,需要和JFinal的Interceptor结合,涉及细节较多,就不一一贴代码
for(String uri : JFinal.me().getAllActionKeys()){
Action action = JFinal.me().getAction(uri, null);
}