All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gitee.easyopen.support.ApiController Maven / Gradle / Ivy

Go to download

一个简单易用的接口开放平台,平台封装了常用的参数校验、结果返回等功能,开发者只需实现业务代码即可。https://gitee.com/durcframework/easyopen

There is a newer version: 1.16.20
Show newest version
package com.gitee.easyopen.support;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.velocity.VelocityContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

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.auth.Oauth2Manager;
import com.gitee.easyopen.auth.Oauth2Service;
import com.gitee.easyopen.bean.ApiSearch;
import com.gitee.easyopen.bean.Consts;
import com.gitee.easyopen.bean.RequestMode;
import com.gitee.easyopen.config.ConfigClient;
import com.gitee.easyopen.doc.ApiDocHolder;
import com.gitee.easyopen.exception.ApiException;
import com.gitee.easyopen.interceptor.ApiInterceptor;
import com.gitee.easyopen.limit.LimitConfig;
import com.gitee.easyopen.limit.LimitConfigManager;
import com.gitee.easyopen.limit.LimitSearch;
import com.gitee.easyopen.message.Errors;
import com.gitee.easyopen.register.AbstractInitializer;
import com.gitee.easyopen.template.DocTemplate;
import com.gitee.easyopen.template.HandshakeTemplate;
import com.gitee.easyopen.template.InvokeTemplate;
import com.gitee.easyopen.template.LimitTemplate;
import com.gitee.easyopen.template.MonitorTemplate;
import com.gitee.easyopen.template.StatusParam;
import com.gitee.easyopen.template.WebfluxInvokeTemplate;
import com.gitee.easyopen.util.RequestUtil;

/**
 * 提供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 WebfluxInvokeTemplate webfluxInvokeTemplate; private DocTemplate docTemplate; private MonitorTemplate monitorTemplate; private LimitTemplate limitTemplate; private HandshakeTemplate handshakeTemplate; @Autowired(required = false) protected Oauth2Manager oauth2Manager; protected Oauth2Service oauth2Service; /** * 初始化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); this.apiConfig.loadPrivateKey(); // 初始化Template this.initTemplate(); // 初始化配置 this.initApiConfig(this.apiConfig); // easyopen初始化工作,注册接口 this.init(applicationContext, this.apiConfig); // 初始化其它组件 // 放在最后 this.initComponent(); } @Override public void onRegistFinished(ApiConfig apiConfig) { ConfigClient configClient = this.apiConfig.getConfigClient(); if(configClient != null) { configClient.init(); } else { LimitConfigManager limitConfigManager = apiConfig.getLimitConfigManager(); if(limitConfigManager != null) { limitConfigManager.loadToLocalCache(); } } } protected void initTemplate() { this.invokeTemplate = new InvokeTemplate(apiConfig, this); this.webfluxInvokeTemplate = new WebfluxInvokeTemplate(apiConfig, this); this.docTemplate = new DocTemplate(apiConfig, this); this.monitorTemplate = new MonitorTemplate(apiConfig,this); this.limitTemplate = new LimitTemplate(apiConfig,this); this.handshakeTemplate = new HandshakeTemplate(apiConfig); } protected ApiConfig newApiConfig() { return ApiContext.getApiConfig(); } private void initComponent() { if(oauth2Manager != null) { apiConfig.initOauth2Service(oauth2Manager); oauth2Service = apiConfig.getOauth2Service(); } initInterceptor(); } /** 添加监控拦截器 */ private void initInterceptor() { if(this.apiConfig.isShowMonitor()) { ApiInterceptor[] interceptors = this.apiConfig.getInterceptors(); int len = interceptors.length + 1; ApiInterceptor[] newInterceptors = new ApiInterceptor[len]; // 监控拦截器放在首位 newInterceptors[0] = this.apiConfig.getMonitorInerceptor(); for (int i = 0; i < interceptors.length; i++) { newInterceptors[i + 1] = interceptors[i]; } this.apiConfig.setInterceptors(newInterceptors); } } /** * 请求入口 * * @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 request * @param response * @throws Throwable */ @RequestMapping(value = "ssl", method = RequestMethod.POST) public void ssl(HttpServletRequest request, HttpServletResponse response) throws Throwable { ApiContext.setRequestMode(RequestMode.ENCRYPT); this.invokeTemplate.processInvoke(request, response); } /** * 加密请求入口 * @param request * @param response * @throws Throwable */ @RequestMapping(value = "ssl2", method = RequestMethod.POST) public void ssl2(HttpServletRequest request, HttpServletResponse response) throws Throwable { ApiContext.useNewSSL(request); this.invokeTemplate.processInvoke(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); } @Override public Result caugthException(Throwable e) { String code = Errors.SYS_ERROR.getCode(); String msg = e.getMessage(); Object data = null; if (e instanceof ApiException) { ApiException apiEx = (ApiException) e; code = apiEx.getCode(); msg = apiEx.getMessage(); data = apiEx.getData(); } return this.apiConfig.getResultCreator().createErrorResult(code, msg, data); } /** * 文档页面 * * @param request * @param response * @throws Throwable */ @RequestMapping("doc") public void doc(HttpServletRequest request, HttpServletResponse response) throws Throwable { this.docTemplate.processDoc(request, response); } /** * 文档下载 * * @param request * @param response * @throws Throwable */ @RequestMapping("doc/download") public void docDl(HttpServletRequest request, HttpServletResponse response) throws Throwable { this.docTemplate.downloadPdf(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; } /** * 进入监控页面 * @throws IOException * @throws ServletException */ @RequestMapping("monitor") public void monitor(HttpServletRequest request, HttpServletResponse response) throws Throwable { this.monitorTemplate.processMonitor(request, response); } /** 查询监控数据 */ @RequestMapping("monitor/data") @ResponseBody public Object monitorData(ApiSearch apiSearch,HttpServletRequest request) throws IOException { return this.monitorTemplate.monitorData(apiSearch, request); } /** 删除监控数据 */ @RequestMapping("monitor/del") @ResponseBody public Object monitorDel(String name,String version) throws IOException { return this.monitorTemplate.monitorDel(name, version); } /** * 交换随机码 * @param request * @param response * @return 返回握手信息 * @throws Throwable */ @RequestMapping(value = "handshake", method = RequestMethod.POST) @ResponseBody public Object handshake(HttpServletRequest request, HttpServletResponse response) { return this.handshakeTemplate.handshake(request, response); } /** * 交换随机码 * @param request * @param response * @return 返回握手信息 * @throws Throwable */ @RequestMapping(value = "handshake2", method = RequestMethod.POST) @ResponseBody public Object handshake2(HttpServletRequest request, HttpServletResponse response) { return this.handshakeTemplate.handshake2(request, response); } /** * oauth2认证获取code * @param request * @param resp * @return 返回code * @throws URISyntaxException * @throws OAuthSystemException */ @RequestMapping("authorize") public Object authorize(HttpServletRequest request,HttpServletResponse resp) throws URISyntaxException, OAuthSystemException { OAuthResponse response = oauth2Service.authorize(request, resp, apiConfig); if(response == null) { return null; } HttpHeaders headers = new HttpHeaders(); headers.setLocation(new URI(response.getLocationUri())); return new ResponseEntity(headers, HttpStatus.valueOf(response.getResponseStatus())); } /** * 通过code获取accessToken * @param request * @return 返回accessToken * @throws URISyntaxException * @throws OAuthSystemException */ @RequestMapping("accessToken") public HttpEntity accessToken(HttpServletRequest request) throws URISyntaxException, OAuthSystemException { OAuthResponse response = oauth2Service.accessToken(request, apiConfig); return new ResponseEntity( response.getBody(), HttpStatus.valueOf(response.getResponseStatus())); } /** * 捕捉异常。
* 接口调用抛出的异常在 * 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; } public void setWebfluxInvokeTemplate(WebfluxInvokeTemplate webfluxInvokeTemplate) { this.webfluxInvokeTemplate = webfluxInvokeTemplate; } /* ***********************************限流内容start*********************************** */ /** * 进入监控页面 * @throws IOException * @throws ServletException */ @RequestMapping("limit") public void limit(HttpServletRequest request, HttpServletResponse response) throws Throwable { this.limitTemplate.processLimit(request, response); } @RequestMapping("limit/data") @ResponseBody public Object limitData(LimitSearch apiSearch,HttpServletRequest request) throws IOException { return this.limitTemplate.limitData(apiSearch, request); } @RequestMapping("limit/modify") @ResponseBody public Object limitModify(LimitConfig limitConfig, HttpServletRequest request) throws IOException { return this.limitTemplate.limitModify(limitConfig, request); } @RequestMapping("limit/status") @ResponseBody public Object limitStatus(@RequestBody StatusParam statusParam, HttpServletRequest request) throws IOException { return this.limitTemplate.limitStatus(statusParam, request); } /* ***********************************限流内容end*********************************** */ @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 WebfluxInvokeTemplate getWebfluxInvokeTemplate() { return webfluxInvokeTemplate; } public DocTemplate getDocTemplate() { return docTemplate; } public void setDocTemplate(DocTemplate docTemplate) { this.docTemplate = docTemplate; } public MonitorTemplate getMonitorTemplate() { return monitorTemplate; } public void setMonitorTemplate(MonitorTemplate monitorTemplate) { this.monitorTemplate = monitorTemplate; } public LimitTemplate getLimitTemplate() { return limitTemplate; } public void setLimitTemplate(LimitTemplate limitTemplate) { this.limitTemplate = limitTemplate; } public HandshakeTemplate getHandshakeTemplate() { return handshakeTemplate; } public void setHandshakeTemplate(HandshakeTemplate handshakeTemplate) { this.handshakeTemplate = handshakeTemplate; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy