com.gitee.easyopen.support.ApiController Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of easyopen-mini Show documentation
Show all versions of easyopen-mini Show documentation
easyopen mini版,保留基本签名校验,文档功能。https://gitee.com/durcframework/easyopen
package com.gitee.easyopen.support;
import com.gitee.easyopen.ApiConfig;
import com.gitee.easyopen.ApiContext;
import com.gitee.easyopen.ApiResult;
import com.gitee.easyopen.ParamNames;
import com.gitee.easyopen.RespWriter;
import com.gitee.easyopen.Result;
import com.gitee.easyopen.bean.Consts;
import com.gitee.easyopen.bean.RequestMode;
import com.gitee.easyopen.doc.ApiDocHolder;
import com.gitee.easyopen.exception.ApiException;
import com.gitee.easyopen.message.Errors;
import com.gitee.easyopen.register.AbstractInitializer;
import com.gitee.easyopen.template.DocTemplate;
import com.gitee.easyopen.template.InvokeTemplate;
import com.gitee.easyopen.util.RequestUtil;
import org.apache.velocity.VelocityContext;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
* 提供API访问能力,新建一个类继承这个即可.RequestMapping中的value自己定义
*
*
* @Controller
* @RequestMapping(value = "/api")
* public class IndexController extends ApiController {
* }
*
* 这样接口的统一访问路径为:http://ip:port/contextPath/api
*
*
* @author tanghc
*/
public abstract class ApiController extends AbstractInitializer implements ApplicationListener, ResponseHandler, VelocityContextHandler {
protected static volatile ApplicationContext ctx;
protected volatile ApiConfig apiConfig;
private InvokeTemplate invokeTemplate;
private DocTemplate docTemplate;
/**
* 初始化apiConfig对象。spring容器加载完毕后触发此方法,因此方法中可以使用被@Autowired注解的对象。
*
* @param apiConfig
*/
protected abstract void initApiConfig(ApiConfig apiConfig);
@Component
private static class Ctx implements ApplicationContextAware {
/**
* 这里会在onApplicationEvent之前触发
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ctx = applicationContext;
}
}
/**
* spring容器加载完毕后执行
*/
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext appCtx = this.getApplicationContext();
if (appCtx == null) {
appCtx = event.getApplicationContext();
}
this.onStartup(appCtx);
}
protected ApplicationContext getApplicationContext() {
return ctx;
}
protected synchronized void onStartup(ApplicationContext applicationContext) {
if (this.apiConfig != null) {
return;
}
// 保存ApplicationContext
ApiContext.setApplicationContext(applicationContext);
// 新建一个ApiConfig
this.apiConfig = newApiConfig();
ApiContext.setApiConfig(apiConfig);
// 初始化Template
this.initTemplate();
// 初始化配置
this.initApiConfig(this.apiConfig);
// easyopen初始化工作,注册接口
this.init(applicationContext, this.apiConfig);
}
protected void initTemplate() {
this.invokeTemplate = new InvokeTemplate(apiConfig, this);
this.docTemplate = new DocTemplate(apiConfig, this);
}
protected ApiConfig newApiConfig() {
return ApiContext.getApiConfig();
}
/**
* 请求入口
*
* @param request
* @param response
* @throws Throwable
*/
@RequestMapping(method = {RequestMethod.POST, RequestMethod.GET})
public void index(HttpServletRequest request, HttpServletResponse response) {
// 调用接口方法,即调用被@Api标记的方法
ApiContext.setRequestMode(RequestMode.SIGNATURE);
this.invokeTemplate.processInvoke(request, response);
}
/**
* 接口名体现在地址栏:http://www.xxx.com/api/接口名/
* 如:
* http://www.xxx.com/api/goods.get/
* 注意:必须要以斜杠“/”结尾
*
* @param name 接口名
* @param request
* @param response
*/
@RequestMapping(value = "/{name}/", method = {RequestMethod.POST, RequestMethod.GET})
public void rest(@PathVariable("name") String name,
HttpServletRequest request, HttpServletResponse response) {
this.doRest(name, null, request, response);
}
/**
* 接口名和版本号体现在地址栏:http://www.xxx.com/api/接口名/版本号/
* 如:
* http://www.xxx.com/api/goods.get/1.0/
* 注意:必须要以斜杠“/”结尾
*
* @param name 接口名
* @param version 版本号
* @param request
* @param response
*/
@RequestMapping(value = "/{name}/{version}/", method = {RequestMethod.POST, RequestMethod.GET})
public void rest2(@PathVariable("name") String name, @PathVariable("version") String version,
HttpServletRequest request, HttpServletResponse response) {
this.doRest(name, version, request, response);
}
protected void doRest(String name, String version,
HttpServletRequest request, HttpServletResponse response) {
if (name == null) {
throw new IllegalArgumentException("name不能为空");
}
if (version == null) {
version = this.apiConfig.getDefaultVersion();
}
request.setAttribute(Consts.REST_PARAM_NAME, name);
request.setAttribute(Consts.REST_PARAM_VERSION, version);
this.index(request, response);
}
/**
* Mock请求入口
*
* @param request
* @param response
* @throws Throwable
*/
@RequestMapping(value = "mock", method = {RequestMethod.POST, RequestMethod.GET})
public void indexMock(HttpServletRequest request, HttpServletResponse response) {
// 调用接口方法,即调用被@Api标记的方法
ApiContext.setRequestMode(RequestMode.SIGNATURE);
this.invokeTemplate.processInvokeMock(request, response);
}
/**
* 写数据到客户端
*
* @param response
* @param result 结果
*/
@Override
public void responseResult(HttpServletRequest request, HttpServletResponse response, Object result) {
if (result == null) {
return;
}
RespWriter respWriter = this.apiConfig.getRespWriter();
respWriter.write(request, response, result);
}
/**
* 文档页面
*
* @param request
* @param response
* @throws Throwable
*/
@RequestMapping("doc")
public void doc(HttpServletRequest request, HttpServletResponse response) throws Throwable {
this.docTemplate.processDoc(request, response);
}
@RequestMapping("json/doc")
@ResponseBody
public Map jsondoc(HttpServletRequest request, HttpServletResponse response) throws Throwable {
Map context = new HashMap();
context.put("apiModules", ApiDocHolder.getApiDocBuilder().getApiModules());
context.put("ACCESS_TOKEN_NAME", ParamNames.ACCESS_TOKEN_NAME);
context.put("API_NAME", ParamNames.API_NAME);
context.put("APP_KEY_NAME", ParamNames.APP_KEY_NAME);
context.put("DATA_NAME", ParamNames.DATA_NAME);
context.put("FORMAT_NAME", ParamNames.FORMAT_NAME);
context.put("SIGN_METHOD_NAME", ParamNames.SIGN_METHOD_NAME);
context.put("SIGN_NAME", ParamNames.SIGN_NAME);
context.put("TIMESTAMP_NAME", ParamNames.TIMESTAMP_NAME);
context.put("TIMESTAMP_PATTERN", ParamNames.TIMESTAMP_PATTERN);
context.put("VERSION_NAME", ParamNames.VERSION_NAME);
context.put("code_name", "code");
context.put("code_description", "状态值,\"0\"表示成功,其它都是失败");
context.put("msg_name", "msg");
context.put("msg_description", "错误信息,出错时显示");
context.put("data_name", "data");
context.put("data_description", "返回的数据,没有则返回{}");
return context;
}
@RequestMapping("doc/pwd")
@ResponseBody
public Map docPwd(String password, HttpServletRequest request) throws Throwable {
Map map = new HashMap();
if (apiConfig.getDocPassword().equals(password)) {
map.put("code", 0);
map.put("msg", "验证成功");
Map data = new HashMap<>();
data.put("id", "doc");
data.put("username", RequestUtil.getClientIP(request));
String jwt = ApiContext.createJwt(data);
map.put("jwt", jwt);
} else {
map.put("code", 1);
map.put("msg", "验证失败");
}
return map;
}
/**
* 捕捉异常。
* 接口调用抛出的异常在
* InvokeTemplate.processError()
中执行,其它情况的异常会走这里。
*
* @param request
* @param response
* @param e
*/
@ExceptionHandler(value = Throwable.class)
public void jsonErrorHandler(HttpServletRequest request, HttpServletResponse response, Throwable e) {
logger.error("jsonErrorHandler error", e);
ApiResult result = new ApiResult();
result.setCode(Errors.SYS_ERROR.getCode());
result.setMsg(e.getMessage());
try {
apiConfig.getRespWriter().write(request, response, result);
} catch (Exception e1) {
logger.error("com.gitee.easyopen.support.ApiController.jsonErrorHandler()写json失败", e1);
}
}
public void setInvokeTemplate(InvokeTemplate invokeTemplate) {
this.invokeTemplate = invokeTemplate;
}
@Override
public void processDocVelocityContext(VelocityContext context) {
}
@Override
public void processLimitVelocityContext(VelocityContext context) {
}
@Override
public void processMonitorVelocityContext(VelocityContext context) {
}
@Override
public String getDocRemark() {
return "";
}
public InvokeTemplate getInvokeTemplate() {
return invokeTemplate;
}
public DocTemplate getDocTemplate() {
return docTemplate;
}
public void setDocTemplate(DocTemplate docTemplate) {
this.docTemplate = docTemplate;
}
}