123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- package org.ssssssss.magicapi.config;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.util.StringUtils;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.context.request.NativeWebRequest;
- import org.springframework.web.context.request.RequestAttributes;
- import org.springframework.web.context.request.ServletWebRequest;
- import org.springframework.web.servlet.HandlerMapping;
- import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
- import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
- import org.ssssssss.magicapi.provider.ApiServiceProvider;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.lang.reflect.Method;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
- /**
- * 请求映射
- */
- public class MappingHandlerMapping {
- /**
- * 已缓存的映射信息
- */
- private static Map<String, ApiInfo> mappings = new ConcurrentHashMap<>();
- private static Logger logger = LoggerFactory.getLogger(MappingHandlerMapping.class);
- /**
- * spring中的请求映射处理器
- */
- private RequestMappingHandlerMapping requestMappingHandlerMapping;
- /**
- * 请求处理器
- */
- private RequestHandler handler;
- /**
- * 请求到达时处理的方法
- */
- private Method method = RequestHandler.class.getDeclaredMethod("invoke", HttpServletRequest.class, HttpServletResponse.class, Map.class, Map.class);
- /**
- * 接口信息读取
- */
- private ApiServiceProvider magicApiService;
- /**
- * 统一接口前缀
- */
- private String prefix;
- /**
- * 缓存已映射的接口信息
- */
- private List<ApiInfo> apiInfos = Collections.synchronizedList(new ArrayList<>());
- public MappingHandlerMapping() throws NoSuchMethodException {
- }
- public void setPrefix(String prefix) {
- this.prefix = prefix;
- }
- /**
- * 根据request获取对应的接口信息
- */
- public static ApiInfo getMappingApiInfo(HttpServletRequest request) {
- NativeWebRequest webRequest = new ServletWebRequest(request);
- // 找到注册的路径
- String requestMapping = (String) webRequest.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
- // 根据请求方法和路径获取接口信息
- return getMappingApiInfo(buildMappingKey(request.getMethod(), requestMapping));
- }
- /**
- * 根据绑定的key获取接口信息
- */
- public static ApiInfo getMappingApiInfo(String key) {
- return mappings.get(key);
- }
- /**
- * 构建缓存map的key
- *
- * @param requestMethod 请求方法
- * @param requestMapping 请求路径
- * @return
- */
- public static String buildMappingKey(String requestMethod, String requestMapping) {
- //TODO 判断 requestMapping 是否已 “/” 开头
- if (!StringUtils.isEmpty(requestMapping) && !requestMapping.startsWith("/")) {
- requestMapping = "/" + requestMapping;
- }
- return requestMethod.toUpperCase() + ":" + requestMapping;
- }
- public void setRequestMappingHandlerMapping(RequestMappingHandlerMapping requestMappingHandlerMapping) {
- this.requestMappingHandlerMapping = requestMappingHandlerMapping;
- }
- public void setHandler(RequestHandler handler) {
- this.handler = handler;
- }
- public void setMagicApiService(ApiServiceProvider magicApiService) {
- this.magicApiService = magicApiService;
- }
- public List<ApiInfo> getApiInfos() {
- return apiInfos;
- }
- /**
- * 注册请求
- */
- public void registerAllMapping() {
- List<ApiInfo> list = magicApiService.listWithScript();
- if (list != null) {
- apiInfos.addAll(list);
- for (ApiInfo info : list) {
- registerMapping(info, false);
- }
- }
- }
- /**
- * 根据请求方法和路径获取接口信息
- *
- * @param method 请求方法
- * @param requestMapping 请求路径
- */
- public ApiInfo getApiInfo(String method, String requestMapping) {
- return mappings.get(buildMappingKey(method, requestMapping));
- }
- public void updateGroupPrefix(String oldGroupName, String newGroupName, String prefix) {
- for (ApiInfo info : apiInfos) {
- if (oldGroupName.equals(info.getGroupName())) {
- unregisterMapping(info.getId(), false);
- info.setGroupName(newGroupName);
- info.setGroupPrefix(prefix);
- registerMapping(info, false);
- }
- }
- }
- /**
- * 注册请求映射
- *
- */
- public void registerMapping(ApiInfo info, boolean delete) {
- // 先判断是否已注册,如果已注册,则先取消注册在进行注册。
- if (mappings.containsKey(info.getId())) {
- ApiInfo oldInfo = mappings.get(info.getId());
- logger.info("取消注册接口:{}", oldInfo.getName());
- // 取消注册
- mappings.remove(getMappingKey(info));
- requestMappingHandlerMapping.unregisterMapping(getRequestMapping(oldInfo));
- }
- logger.info("注册接口:{}", info.getName());
- // 注册
- RequestMappingInfo requestMapping = getRequestMapping(info);
- mappings.put(info.getId(), info);
- mappings.put(getMappingKey(info), info);
- requestMappingHandlerMapping.registerMapping(requestMapping, handler, method);
- if (delete) { // 刷新缓存
- apiInfos.removeIf(i -> i.getId().equalsIgnoreCase(info.getId()));
- apiInfos.add(info);
- }
- }
- /**
- * 取消注册请求映射
- */
- public void unregisterMapping(String id, boolean delete) {
- ApiInfo info = mappings.remove(id);
- if (info != null) {
- logger.info("取消注册接口:{}", info.getName());
- mappings.remove(getMappingKey(info));
- requestMappingHandlerMapping.unregisterMapping(getRequestMapping(info));
- if (delete) { //刷新缓存
- apiInfos.removeIf(i -> i.getId().equalsIgnoreCase(info.getId()));
- }
- }
- }
- /**
- * 根据接口信息获取绑定map的key
- */
- private String getMappingKey(ApiInfo info) {
- return buildMappingKey(info.getMethod(), getRequestPath(info.getGroupPrefix(), info.getPath()));
- }
- /**
- * 处理前缀
- *
- * @param groupPrefix 分组前缀
- * @param path 请求路径
- */
- public String getRequestPath(String groupPrefix, String path) {
- groupPrefix = groupPrefix == null ? "" : groupPrefix;
- while (groupPrefix.endsWith("/")) {
- groupPrefix = groupPrefix.substring(0, groupPrefix.length() - 1);
- }
- while (path.startsWith("/")) {
- path = path.substring(1);
- }
- path = groupPrefix + "/" + path;
- if (prefix != null) {
- path = prefix + (path.startsWith("/") ? path.substring(1) : path);
- }
- return path;
- }
- /**
- * 根据接口信息构建 RequestMappingInfo
- */
- private RequestMappingInfo getRequestMapping(ApiInfo info) {
- return RequestMappingInfo.paths(getRequestPath(info.getGroupPrefix(), info.getPath())).methods(RequestMethod.valueOf(info.getMethod().toUpperCase())).build();
- }
- }
|