init project

This commit is contained in:
2021-07-08 18:02:26 +08:00
commit 10e056aa44
380 changed files with 28364 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
package com.mt.wms.gateway;
/*
* Copyright (c) 2018.
* http://www.ulabcare.com
*/
import com.mt.wms.core.EnableMesCore;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 服务网关
*
* @author FanYi
* @date 2020/07/01
* @since 1.0
*/
@SpringBootApplication(exclude = {})
@ComponentScan(basePackages = {
"com.mt.wms.gateway",
"com.mt.wms.common",
"com.mt.wms.passport",
"com.mt.wms.upms"
})
@ServletComponentScan("com.mt.wms.gateway.filter")
@EnableDiscoveryClient
//@EnableFeignClients
@RefreshScope
@EnableMesCore
@EnableScheduling
public class MesGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(MesGatewayApplication.class, args);
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018.
* http://www.ulabcare.com
*/
package com.mt.wms.gateway.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
/**
* 服务网关配置
*
* @author jiff
* @date 2018/11/1
* @since 1.0
*/
@ConfigurationProperties("wms.gateway")
@Validated
@Data
@Component
public class GatewayConfig {
@NotNull
@Valid
private List<String> ignoreAuths = new ArrayList<>();
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2018.
* http://www.ulabcare.com
*/
package com.mt.wms.gateway.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
/**
* 路由配置
*
* @author jiff
* @date 2018/11/1
* @since 1.0
*/
@Configuration
@Slf4j
public class RouteConfig {
private static final String ALLOWED_HEADERS = "Content-Type, authorization, credential, token, X-Requested-With";
private static final String ALLOWED_METHODS = "*";
private static final String ALLOWED_ORIGIN = "*";
private static final String ALLOWED_EXPOSE = "*";
private static final String MAX_AGE = "18000L";
@Bean
public WebFilter corsFilter() {
return (ServerWebExchange exchange, WebFilterChain chain) -> {
ServerHttpRequest request = exchange.getRequest();
if (CorsUtils.isCorsRequest(request)) {
ServerHttpResponse response = exchange.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, ALLOWED_ORIGIN);
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, ALLOWED_METHODS);
headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, ALLOWED_HEADERS);
headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALLOWED_EXPOSE);
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
}
return chain.filter(exchange);
};
}
}

View File

@@ -0,0 +1,63 @@
package com.mt.wms.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* 服务网关swagger配置
*
* @author jiff
* @date 2018/11/1
* @since 1.0
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket passportApi() {
return new Docket(DocumentationType.SWAGGER_2).groupName("wms-passport")
.apiInfo(apiInfo("passport", "统一认证接口"))
.select()
.apis(RequestHandlerSelectors.basePackage("com.mt.wms.passport"))
.paths(PathSelectors.any())
.build();
}
@Bean
public Docket commonApi() {
return new Docket(DocumentationType.SWAGGER_2).groupName("wms-common")
.apiInfo(apiInfo("common", "公共接口"))
.select()
.apis(RequestHandlerSelectors.basePackage("com.mt.wms.common"))
.paths(PathSelectors.any())
.build();
}
@Bean
public Docket upmsApi() {
return new Docket(DocumentationType.SWAGGER_2).groupName("wms-upms")
.apiInfo(apiInfo("upms", "通用权限接口"))
.select()
.apis(RequestHandlerSelectors.basePackage("com.mt.wms.upms"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo(String title, String description) {// 创建API的基本信息这些信息会在Swagger UI中进行显示
return new ApiInfoBuilder()
.title(title)
.description(description)
.termsOfServiceUrl("http://www.mt.com")
.contact(new Contact("jiff", "", "jiff@ulabcare.com"))
.version("1.0")
.build();
}
}

View File

@@ -0,0 +1,20 @@
package com.mt.wms.gateway.config;
import com.mt.wms.core.config.CommonConfig;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@RequiredArgsConstructor
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
private final CommonConfig mCommonConfig;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/common/**").addResourceLocations("file:" + mCommonConfig.getUploadPath());
super.addResourceHandlers(registry);
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2018.
* http://www.ulabcare.com
*/
package com.mt.wms.gateway.feign;
import com.mt.wms.gateway.feign.fallback.PassportServiceFallback;
import com.mt.wms.core.dto.LoginUser;
import com.mt.wms.core.vo.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* 统一用户服务
*
* @author jiff
* @date 2018/11/1
* @since 1.0
*/
@FeignClient(value = "wms-passport", fallback = PassportServiceFallback.class)
public interface PassportService {
/**
* 请求资源鉴权
*
* @param url 请求地址
* @param method 请求方法
* @return
*/
@PostMapping("authorization")
R<LoginUser> authorization(@RequestParam("url") String url, @RequestParam("method") String method);
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2018.
* http://www.ulabcare.com
*/
package com.mt.wms.gateway.feign.fallback;
import com.mt.wms.core.dto.LoginUser;
import com.mt.wms.core.vo.R;
import com.mt.wms.gateway.feign.PassportService;
import com.mt.wms.passport.controller.PassportController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 统一用户服务失败回调实现
*
* @author jiff
* @date 2018/11/1
* @since 1.0
*/
@Service
@Slf4j
public class PassportServiceFallback implements PassportService {
@Autowired
PassportController passportController;
@Override
public R<LoginUser> authorization(String url, String method) {
return passportController.authorization(url, method);
}
}

View File

@@ -0,0 +1,54 @@
package com.mt.wms.gateway.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author jiff
* @date 2019/11/27
* @since 1.0
*/
@Slf4j
@WebFilter(urlPatterns = "/*", filterName = "corsFilter")
public class CorsFilter implements Filter {
private static final String ALLOWED_HEADERS = "Content-Type, authorization, credential, token, X-Requested-With";
private static final String ALLOWED_METHODS = "*";
private static final String ALLOWED_ORIGIN = "*";
private static final String ALLOWED_EXPOSE = "*";
private static final String MAX_AGE = "18000L";
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = ((HttpServletRequest) request);
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setHeader("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Allow-Methods", ALLOWED_METHODS);
httpServletResponse.setHeader("Access-Control-Max-Age", MAX_AGE);
httpServletResponse.setHeader("Access-Control-Allow-Headers", ALLOWED_HEADERS);
httpServletResponse.setHeader("Access-Control-Expose-Headers", ALLOWED_EXPOSE);
if (httpRequest.getMethod().equalsIgnoreCase(HttpMethod.OPTIONS.name())) {
return;
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}

View File

@@ -0,0 +1,154 @@
package com.mt.wms.gateway.filter;
import com.alibaba.fastjson.JSON;
import com.mt.wms.core.dto.LoginUser;
import com.mt.wms.core.vo.R;
import com.mt.wms.gateway.config.GatewayConfig;
import com.mt.wms.gateway.feign.PassportService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author jiff
* @date 2019/11/27
* @since 1.0
*/
@Slf4j
@WebFilter(urlPatterns = "/*", filterName = "gatewayFilter")
public class GatewayFilter implements Filter {
@Autowired
@Lazy()
private PassportService passportService;
@Autowired
@Lazy
private GatewayConfig gatewayConfig;
private static final String GATEWAY_PREFIX = "/api";
/**
* Called by the web container to indicate to a filter that it is being
* placed into service. The servlet container calls the init method exactly
* once after instantiating the filter. The init method must complete
* successfully before the filter is asked to do any filtering work.
* <p>
* The web container cannot place the filter into service if the init method
* either:
* <ul>
* <li>Throws a ServletException</li>
* <li>Does not return within a time period defined by the web
* container</li>
* </ul>
*
* @param filterConfig The configuration information associated with the
* filter instance being initialised
* @throws ServletException if the initialisation fails
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/**
* The <code>doFilter</code> method of the Filter is called by the container
* each time a request/response pair is passed through the chain due to a
* client request for a resource at the end of the chain. The FilterChain
* passed in to this method allows the Filter to pass on the request and
* response to the next entity in the chain.
* <p>
* A typical implementation of this method would follow the following
* pattern:- <br>
* 1. Examine the request<br>
* 2. Optionally wrap the request object with a custom implementation to
* filter content or headers for input filtering <br>
* 3. Optionally wrap the response object with a custom implementation to
* filter content or headers for output filtering <br>
* 4. a) <strong>Either</strong> invoke the next entity in the chain using
* the FilterChain object (<code>chain.doFilter()</code>), <br>
* 4. b) <strong>or</strong> not pass on the request/response pair to the
* next entity in the filter chain to block the request processing<br>
* 5. Directly set headers on the response after invocation of the next
* entity in the filter chain.
*
* @param request The request to process
* @param response The response associated with the request
* @param chain Provides access to the next filter in the chain for this
* filter to pass the request and response to for further
* processing
* @throws IOException if an I/O error occurs during this filter's
* processing of the request
* @throws ServletException if the processing fails for any other reason
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = ((HttpServletRequest) request);
String requestUri = httpRequest.getRequestURI();
if (requestUri.startsWith(GATEWAY_PREFIX)) {
requestUri = requestUri.substring(GATEWAY_PREFIX.length());
}
final String method = httpRequest.getMethod();
//忽略鉴权的地址
if (isIgnoreAuth(requestUri)) {
if (log.isDebugEnabled()) {
log.debug("忽略鉴权的地址={}", requestUri);
}
chain.doFilter(request, response);
return;
}
R<LoginUser> r = passportService.authorization(requestUri, method);
if (r != null && r.ok()) {
if (r.getData() != null) {
log.info("loginUser={}", JSON.toJSONString(r.getData()));
}
chain.doFilter(request, response);
} else {
r = r != null ? r : R.failed();
response.setContentType("application/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.getWriter().print(JSON.toJSONString(r));
}
}
/**
* Called by the web container to indicate to a filter that it is being
* taken out of service. This method is only called once all threads within
* the filter's doFilter method have exited or after a timeout period has
* passed. After the web container calls this method, it will not call the
* doFilter method again on this instance of the filter. <br>
* <br>
* <p>
* This method gives the filter an opportunity to clean up any resources
* that are being held (for example, memory, file handles, threads) and make
* sure that any persistent state is synchronized with the filter's current
* state in memory.
*/
@Override
public void destroy() {
}
private boolean isIgnoreAuth(String requestUri) {
for (String ignore : gatewayConfig.getIgnoreAuths()) {
if (log.isDebugEnabled()) {
log.debug("ignore auth url is {}", ignore);
}
// 编译正则表达式,忽略大小写的写法
Pattern pattern = Pattern.compile(ignore, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(requestUri);
// 查找字符串中是否有匹配正则表达式的字符/字符串
if (matcher.find()) {
return true;
}
}
return false;
}
}