diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8bd3863
--- /dev/null
+++ b/README.md
@@ -0,0 +1,1177 @@
+### 1. 技术选型
+
+----
+
+* 注册中心:nacos,替代方案eureka、consul、zookeeper
+
+* 配置中心: nacos ,替代方案sc config、consul config
+
+* 服务调用:feign,替代方案:resttempate
+
+* 熔断:sentinel、,替代方案:Resilience4j
+
+* 熔断监控:sentinel dashboard
+
+* 负载均衡:sc loadbalancer
+
+* 网关:spring cloud gateway
+
+* 链路:spring cloud sleuth+zipkin,替代方案:skywalking等。
+
+* 分时任务调度框架 xxl-job
+
+* admin 监控
+
+-----
+
+### 2.工程搭建
+
+
+
+#### 2.1 搭建父工程
+
+
+
+* mystyle-cloud-parent
+
+```xml
+
+
+
+ 4.0.0
+
+ com.zhangmeng
+ mystyle-cloud-parent
+ 1.0-SNAPSHOT
+
+
+ 1.8
+ 2.4.4
+ 2020.0.2
+ 2020.0.RC1
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+ com.alibaba.cloud
+ spring-cloud-alibaba-dependencies
+ ${spring-cloud-alibaba.version}
+ pom
+ import
+
+
+
+
+
+```
+
+
+#### 2.2 搭建用户中心(废除)
+
+* mystyle-cloud-user
+
+> 包结构 : com.zhangmeng.user
+
+[mystyle-cloud-user](http://localhost:8848/nacos/)
+
+```xml
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+```
+
+#### 2.3 搭建文件中心
+
+* mystyle-cloud-file
+
+> 包结构 :com.zhangmeng.file
+
+[file调用user](http://localhost:8763/file/name?name=转身的背影在心底里沉沦)
+
+
+
+
+
+-------
+
+```xml
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-loadbalancer
+
+
+```
+
+#### 2.4 搭建网关
+
+
+* mystyle-cloud-gateway
+
+> 包结构 :com.zhangmeng.gateway
+
+[测试](http://localhost:5000/mystyle-file/file/name?name=转身的背影在心底里沉沦)
+
+
+
+-------
+```xml
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+ org.springframework.cloud
+ spring-cloud-starter-gateway
+
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-loadbalancer
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-sentinel
+
+
+
+ com.alibaba.cloud
+ spring-cloud-alibaba-sentinel-gateway
+
+
+
+
+```
+
+* 创建一个网关分组和网关的限流规则
+
+```java
+@Configuration
+public class GatewayConfiguration {
+
+ private final List viewResolvers;
+ private final ServerCodecConfigurer serverCodecConfigurer;
+
+ public GatewayConfiguration(ObjectProvider> viewResolversProvider,
+ ServerCodecConfigurer serverCodecConfigurer) {
+ this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
+ this.serverCodecConfigurer = serverCodecConfigurer;
+ }
+
+ @Bean
+ @Order(Ordered.HIGHEST_PRECEDENCE)
+ public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
+ // Register the block exception handler for Spring Cloud Gateway.
+ return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
+ }
+
+ @Bean
+ @Order(-1)
+ public GlobalFilter sentinelGatewayFilter() {
+ return new SentinelGatewayFilter();
+ }
+
+ @PostConstruct
+ public void doInit() {
+ initCustomizedApis();
+ initGatewayRules();
+ }
+
+ private void initCustomizedApis() {
+ Set definitions = new HashSet<>();
+ ApiDefinition api1 = new ApiDefinition("consumer")
+ .setPredicateItems(new HashSet() );
+ ApiDefinition api2 = new ApiDefinition("provider")
+ .setPredicateItems(new HashSet() );
+ definitions.add(api1);
+ definitions.add(api2);
+ GatewayApiDefinitionManager.loadApiDefinitions(definitions);
+ }
+
+ private void initGatewayRules() {
+ Set rules = new HashSet<>();
+ rules.add(new GatewayFlowRule("consumer")
+ .setCount(10)
+ .setIntervalSec(1)
+ );
+ rules.add(new GatewayFlowRule("consumer")
+ .setCount(2)
+ .setIntervalSec(2)
+ .setBurst(2)
+ .setParamItem(new GatewayParamFlowItem()
+ .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_CLIENT_IP)
+ )
+ );
+ rules.add(new GatewayFlowRule("provider")
+ .setCount(10)
+ .setIntervalSec(1)
+ .setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)
+ .setMaxQueueingTimeoutMs(600)
+ .setParamItem(new GatewayParamFlowItem()
+ .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_HEADER)
+ .setFieldName("X-Sentinel-Flag")
+ )
+ );
+ rules.add(new GatewayFlowRule("provider")
+ .setCount(1)
+ .setIntervalSec(1)
+ .setParamItem(new GatewayParamFlowItem()
+ .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
+ .setFieldName("pa")
+ )
+ );
+ rules.add(new GatewayFlowRule("provider")
+ .setCount(2)
+ .setIntervalSec(30)
+ .setParamItem(new GatewayParamFlowItem()
+ .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
+ .setFieldName("type")
+ .setPattern("warn")
+ .setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_CONTAINS)
+ )
+ );
+
+ rules.add(new GatewayFlowRule("provider")
+ .setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)
+ .setCount(5)
+ .setIntervalSec(1)
+ .setParamItem(new GatewayParamFlowItem()
+ .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
+ .setFieldName("pn")
+ )
+ );
+ GatewayRuleManager.loadRules(rules);
+ }
+}
+```
+
+
+
+
+#### 2.5 sentinel dashboard
+
+[sentinel dashboard](http://localhost:8748)
+
+> java -Dserver.port=8748 -Dcsp.sentinel.dashboard.server=localhost:8748 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar
+
+添加流控规则 :
+
+
+
+
+
+
+#### 2.6 搭建注册中心
+
+
+
+[nacos](http://localhost:8848/nacos/#/login)
+
+
+
+#### 2.7 搭建 zipkin server
+
+[zipkin server](http://localhost:9411/zipkin/)
+
+
+
+
+
+
+
+
+批处理 启动
+
+```bat
+@echo off
+
+start /d "E:\nacos-server-2.0.2\nacos\bin\" startup.cmd
+
+start cmd /c "title sentinel-dashboard && java -jar E:\nacos-server-2.0.2\sentinel-dashboard-1.8.2.jar --server.port=8748 &"
+
+start cmd /c "title zipkin-server-2.23.4-exec && java -jar E:\nacos-server-2.0.2\zipkin-server-2.23.4-exec.jar --server.port=9411 &"
+
+pause
+
+```
+
+#### 2.8 搭建 model
+
+* mystyle-cloud-model
+
+> 包结构 :com.zhangmeng.model
+
+集成 jpa 及 通用 mapper
+
+
+
+```java
+@SpringBootApplication
+@EnableDiscoveryClient
+@EnableFeignClients
+@ComponentScan(basePackages = {"com.zhangmeng.model","com.zhangmeng.file"})
+public class FileApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(FileApplication.class,args);
+ }
+}
+```
+
+测试
+
+
+#### 2.8 搭建 管理后台
+
+* mystyle-cloud-admin-manager
+
+> 包结构 :com.zhangmeng.admin.manager
+
+
+
+#### 2.9 api 搭建 api
+
+* mystyle-cloud-api
+
+> 包结构 :com.zhangmeng.api
+>
+
+
+
+```java
+
+package com.zhangmeng.api.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.*;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.contexts.SecurityContext;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author zhangmeng
+ * @version 1.0
+ * @date 2021年7月8日09:12:01
+ */
+@EnableSwagger2
+@Configuration
+public class SwaggerConfig {
+
+ @Bean
+ public Docket docket() {
+ return new Docket(DocumentationType.SWAGGER_2).groupName("swagger接口文档")
+ .apiInfo(new ApiInfoBuilder().title("swagger接口文档")
+ .contact(new Contact("转身的背影在心底里沉沦", "", "1334717033.com")).version("1.0").build())
+ .securitySchemes(securitySchemes())
+ .securityContexts(securityContexts())
+ .select()
+ .apis(RequestHandlerSelectors.basePackage("com.zhangmeng"))
+ .paths(PathSelectors.any()).build();
+ }
+
+ private List securitySchemes() {
+ List apiKeyList= new ArrayList<>();
+ apiKeyList.add(new ApiKey("token", "token", "header"));
+ return apiKeyList;
+ }
+
+ private List securityContexts() {
+ List securityContexts=new ArrayList<>();
+ securityContexts.add(
+ SecurityContext.builder()
+ .securityReferences(defaultAuth())
+ .forPaths(PathSelectors.regex("^(?!auth).*$"))
+ .build());
+ return securityContexts;
+ }
+
+ private List defaultAuth() {
+ AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
+ AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
+ authorizationScopes[0] = authorizationScope;
+ List securityReferences=new ArrayList<>();
+ securityReferences.add(new SecurityReference("token", authorizationScopes));
+ return securityReferences;
+ }
+}
+
+```
+
+[admin_manager](http://localhost:31003/swagger-ui.html)
+
+
+
+
+#### 2.10 搭建 canal
+
+* mystyle-cloud-canal
+
+> 包结构 :com.zhangmeng.canal
+
+
+
+
+(2) 创建账号 用于测试使用,
+
+使用root账号创建用户并授予权限
+
+```properties
+create user canal@'%' IDENTIFIED by 'canal';
+GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT,SUPER ON *.* TO 'canal'@'%';
+FLUSH PRIVILEGES;
+```
+
+
+
+```java
+@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
+@EnableEurekaClient
+@EnableCanalClient
+public class CanalApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CanalApplication.class,args);
+ }
+}
+```
+
+
+
+
+#### 2.11 搭建 消息中间件 rabbit mq
+
+* mystyle-cloud-mq
+
+> 包结构 :com.zhangmeng.mq
+
+
+#### 2.12 搭建 授权中心
+
+* mystyle-cloud-oauth
+
+> 包结构 :com.zhangmeng.oauth
+
+* Encoded password does not look like BCrypt
+
+
+
+
+
+#### 2.13 搭建博客
+
+* mystyle-cloud-blog
+
+ > 包结构 :com.zhangmeng.blog
+
+#### 2.14 搭建定时任务
+
+思路 :
+>* quartz + rabbit_mq
+>
+>* xxl-job 分布式调度框架
+
+* mystyle-cloud-quartz
+ > com.zhangmeng.quartz
+ 
+
+后续调整为:
+
+* mystyle-cloud-xxl-job
+ > com.zhangmeng.job
+
+引入依赖
+
+```yaml
+
+ com.xuxueli
+ xxl-job-core
+ 2.2.0
+
+```
+
+#### 2.15 搭建邮件
+
+* mystyle-cloud-mail
+ > 包结构 :com.zhangmeng.mail
+
+```java
+
+ org.springframework.boot
+ spring-boot-starter-mail
+
+```
+
+#### 2.15 搭建小说
+
+* mystyle-cloud-fiction
+ > 包结构 :com.zhangmeng.fiction
+
+#### 2.16 搭建admin 监控
+
+* mystyle-cloud-admin-monitor
+ > 包结构 :com.zhangmeng.monitor
+
+```yaml
+management:
+ endpoints:
+ web:
+ exposure:
+ include: '*'
+ endpoint:
+ health:
+ show-details: ALWAYS
+ enabled: true
+```
+```xml
+
+ de.codecentric
+ spring-boot-admin-starter-client
+
+```
+
+```java
+ - /actuator/**
+ - /instances/**
+```
+
+
+
+
+
+
+
+### 3.接口说明
+
+#### 3.1 登录接口
+
+##### 3.1.1 验证码
+
+[验证码](http://localhost:9000/mystyle-cloud-admin-manager/verificationCode/generate)
+
+
+##### 3.1.2 查询当前用户
+
+[地址](http://localhost:9000/mystyle-cloud-admin-manager/user/current)
+
+##### 3.1.3 登录
+
+* 问题 跨域
+ 
+
+[地址](http://localhost:9000/mystyle-cloud-oauth/user/login)
+
+* 解决办法
+
+gate_way yml 配置
+
+```yaml
+server:
+ port: 9000
+spring:
+ application:
+ name: mystyle-cloud-gateway
+ zipkin:
+ sender:
+ type: web
+ base-url: http://localhost:9411/
+ service:
+ name: mystyle-cloud-gateway
+ sleuth:
+ sampler:
+ probability: 1
+ cloud:
+ sentinel:
+ transport:
+ port: 15000
+ dashboard: localhost:8748
+ nacos:
+ discovery:
+ server-addr: 127.0.0.1:8848
+ gateway:
+ globalcors:
+ corsConfigurations:
+ '[/**]': # 匹配所有请求
+ allowedOrigins: "*" #跨域处理 允许所有的域
+ allowedMethods: # 支持的方法
+ - GET
+ - POST
+ - PUT
+ - DELETE
+ allowedOriginPatterns: "*"
+ discovery:
+ locator:
+ enabled: false
+ lowerCaseServiceId: true
+ routes:
+ - id: mystyle-cloud-oauth
+ uri: lb://mystyle-cloud-oauth
+ predicates:
+ - Path=/mystyle-cloud-oauth/**
+ filters:
+ - StripPrefix=1
+ - id: mystyle-cloud-admin-manager
+ uri: lb://mystyle-cloud-admin-manager
+ predicates:
+ - Path=/mystyle-cloud-admin-manager/**
+ filters:
+ - StripPrefix=1
+
+```
+
+或者
+
+```java
+
+package com.zhangmeng.gateway.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.reactive.CorsWebFilter;
+import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
+
+
+/**
+ * @author zhangmeng
+ * @date 2021年11月8日15:52:27
+ * @version 1.0
+ */
+@Configuration
+public class CorsConfig {
+
+ @Bean
+ public CorsWebFilter corsWebFilter(){
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ //1、配置跨域
+ //允许哪些头进行跨域
+ corsConfiguration.addAllowedHeader("*");
+ //允许哪些请求方式进行跨域
+ corsConfiguration.addAllowedMethod("*");
+ //允许哪些请求来源进行跨域
+ corsConfiguration.addAllowedOriginPattern("*");
+ //是否允许携带cookie进行跨域,否则跨域请求会丢失cookie信息
+ corsConfiguration.setAllowCredentials(true);
+
+ source.registerCorsConfiguration("/**",corsConfiguration);
+
+ return new CorsWebFilter(source);
+ }
+}
+
+```
+
+> 提示 : 调用的具体服务去掉跨域配置
+
+[首页访问](http://localhost:31007/login.html)
+
+
+
+#### 3.2 首页
+
+-------
+>**获取鉴权信息**
+
+
+
+* 源码
+
+
+
+oauth2.0 获取鉴权
+
+```java
+
+/**
+ * Copyright 2006-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.springframework.security.oauth2.provider.authentication;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.authentication.AnonymousAuthenticationToken;
+import org.springframework.security.authentication.AuthenticationDetailsSource;
+import org.springframework.security.authentication.AuthenticationEventPublisher;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.InsufficientAuthenticationException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
+import org.springframework.util.Assert;
+
+/**
+ * A pre-authentication filter for OAuth2 protected resources. Extracts an OAuth2 token from the incoming request and
+ * uses it to populate the Spring Security context with an {@link OAuth2Authentication} (if used in conjunction with an
+ * {@link OAuth2AuthenticationManager}).
+ *
+ * @author Dave Syer
+ *
+ */
+public class OAuth2AuthenticationProcessingFilter implements Filter, InitializingBean {
+
+ private final static Log logger = LogFactory.getLog(OAuth2AuthenticationProcessingFilter.class);
+
+ private AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
+
+ private AuthenticationManager authenticationManager;
+
+ private AuthenticationDetailsSource authenticationDetailsSource = new OAuth2AuthenticationDetailsSource();
+
+ private TokenExtractor tokenExtractor = new BearerTokenExtractor();
+
+ private AuthenticationEventPublisher eventPublisher = new NullEventPublisher();
+
+ private boolean stateless = true;
+
+ /**
+ * Flag to say that this filter guards stateless resources (default true). Set this to true if the only way the
+ * resource can be accessed is with a token. If false then an incoming cookie can populate the security context and
+ * allow access to a caller that isn't an OAuth2 client.
+ *
+ * @param stateless the flag to set (default true)
+ */
+ public void setStateless(boolean stateless) {
+ this.stateless = stateless;
+ }
+
+ /**
+ * @param authenticationEntryPoint the authentication entry point to set
+ */
+ public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) {
+ this.authenticationEntryPoint = authenticationEntryPoint;
+ }
+
+ /**
+ * @param authenticationManager the authentication manager to set (mandatory with no default)
+ */
+ public void setAuthenticationManager(AuthenticationManager authenticationManager) {
+ this.authenticationManager = authenticationManager;
+ }
+
+ /**
+ * @param tokenExtractor the tokenExtractor to set
+ */
+ public void setTokenExtractor(TokenExtractor tokenExtractor) {
+ this.tokenExtractor = tokenExtractor;
+ }
+
+ /**
+ * @param eventPublisher the event publisher to set
+ */
+ public void setAuthenticationEventPublisher(AuthenticationEventPublisher eventPublisher) {
+ this.eventPublisher = eventPublisher;
+ }
+
+ /**
+ * @param authenticationDetailsSource The AuthenticationDetailsSource to use
+ */
+ public void setAuthenticationDetailsSource(
+ AuthenticationDetailsSource authenticationDetailsSource) {
+ Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
+ this.authenticationDetailsSource = authenticationDetailsSource;
+ }
+
+ public void afterPropertiesSet() {
+ Assert.state(authenticationManager != null, "AuthenticationManager is required");
+ }
+
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
+ ServletException {
+
+ final boolean debug = logger.isDebugEnabled();
+ final HttpServletRequest request = (HttpServletRequest) req;
+ final HttpServletResponse response = (HttpServletResponse) res;
+
+ try {
+
+ Authentication authentication = tokenExtractor.extract(request);
+
+ if (authentication == null) {
+ if (stateless && isAuthenticated()) {
+ if (debug) {
+ logger.debug("Clearing security context.");
+ }
+ SecurityContextHolder.clearContext();
+ }
+ if (debug) {
+ logger.debug("No token in request, will continue chain.");
+ }
+ }
+ else {
+ request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, authentication.getPrincipal());
+ if (authentication instanceof AbstractAuthenticationToken) {
+ AbstractAuthenticationToken needsDetails = (AbstractAuthenticationToken) authentication;
+ needsDetails.setDetails(authenticationDetailsSource.buildDetails(request));
+ }
+ Authentication authResult = authenticationManager.authenticate(authentication);
+
+ if (debug) {
+ logger.debug("Authentication success: " + authResult);
+ }
+
+ eventPublisher.publishAuthenticationSuccess(authResult);
+ SecurityContextHolder.getContext().setAuthentication(authResult);
+
+ }
+ }
+ catch (OAuth2Exception failed) {
+ SecurityContextHolder.clearContext();
+
+ if (debug) {
+ logger.debug("Authentication request failed: " + failed);
+ }
+ eventPublisher.publishAuthenticationFailure(new BadCredentialsException(failed.getMessage(), failed),
+ new PreAuthenticatedAuthenticationToken("access-token", "N/A"));
+
+ authenticationEntryPoint.commence(request, response,
+ new InsufficientAuthenticationException(failed.getMessage(), failed));
+
+ return;
+ }
+
+ chain.doFilter(request, response);
+ }
+
+ private boolean isAuthenticated() {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
+ return false;
+ }
+ return true;
+ }
+
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ public void destroy() {
+ }
+
+ private static final class NullEventPublisher implements AuthenticationEventPublisher {
+ public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) {
+ }
+
+ public void publishAuthenticationSuccess(Authentication authentication) {
+ }
+ }
+
+}
+
+```
+
+
+
+##### 3.2.1 先从请求头中获取
+
+```java
+ protected String extractToken(HttpServletRequest request) {
+ // first check the header...
+ --------------------------------------------------------------
+ String token = extractHeaderToken(request);
+ --------------------------------------------------------------
+ // bearer type allows a request parameter as well
+ if (token == null) {
+ logger.debug("Token not found in headers. Trying request parameters.");
+ token = request.getParameter(OAuth2AccessToken.ACCESS_TOKEN);
+ if (token == null) {
+ logger.debug("Token not found in request parameters. Not an OAuth2 request.");
+ }
+ else {
+ request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, OAuth2AccessToken.BEARER_TYPE);
+ }
+ }
+
+ return token;
+ }
+```
+
+
+
+```java
+
+/**
+ * Extract the OAuth bearer token from a header.
+ *
+ * @param request The request.
+ * @return The token, or null if no OAuth authorization header was supplied.
+ */
+ protected String extractHeaderToken(HttpServletRequest request) {
+ ---------------------------------------------------------------------------
+ Enumeration headers = request.getHeaders("Authorization");
+ ----------------------------------------------------------------------------
+ while (headers.hasMoreElements()) { // typically there is only one (most servers enforce that)
+ String value = headers.nextElement();
+ if ((value.toLowerCase().startsWith(OAuth2AccessToken.BEARER_TYPE.toLowerCase()))) {
+ String authHeaderValue = value.substring(OAuth2AccessToken.BEARER_TYPE.length()).trim();
+ // Add this here for the auth details later. Would be better to change the signature of this method.
+ request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE,
+ value.substring(0, OAuth2AccessToken.BEARER_TYPE.length()).trim());
+ int commaIndex = authHeaderValue.indexOf(',');
+ if (commaIndex > 0) {
+ authHeaderValue = authHeaderValue.substring(0, commaIndex);
+ }
+ return authHeaderValue;
+ }
+ }
+
+ return null;
+ }
+```
+
+
+
+##### 3.2.2 从请求参数中获取
+
+```java
+protected String extractToken(HttpServletRequest request) {
+ // first check the header...
+ String token = extractHeaderToken(request);
+
+ // bearer type allows a request parameter as well
+ if (token == null) {
+ logger.debug("Token not found in headers. Trying request parameters.");
+ -------------------------------------------------------------------
+ token = request.getParameter(OAuth2AccessToken.ACCESS_TOKEN);
+ -------------------------------------------------------------------
+ if (token == null) {
+ logger.debug("Token not found in request parameters. Not an OAuth2 request.");
+ }
+ else {
+ request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, OAuth2AccessToken.BEARER_TYPE);
+ }
+ }
+
+ return token;
+ }
+
+```
+
+
+
+-------------------------------------------
+
+
+##### 3.2.3 问题
+
+>首页不展示
+
+
+
+>控制台报错 Refused to display 'http://localhost:9000/' in a frame because it set 'X-Frame-Options' to 'deny'.
+
+> 解决办法
+
+```java
+http.headers().frameOptions().disable();
+```
+
+--------------------------
+
+-------------------------------
+> token 过期展示
+
+
+
+
+
+#### 3.3 文件上传
+
+
+> 解决办法
+
+```yaml
+spring:
+ servlet:
+ multipart:
+ max-file-size: 4GB
+ max-request-size: 4GB
+```
+
+
+
+#### 3.4 feign 远程调用
+
+> 报错 :nested exception is feign.RetryableException: too many bytes written executing
+
+>* 解决办法
+>
+```java
+ // 跳过 content-length
+ if (element.equals("content-length")){
+ continue;
+ }
+```
+```java
+@Configuration
+public class FeignOauth2RequestInterceptor implements RequestInterceptor {
+ @Override
+ public void apply(RequestTemplate requestTemplate) {
+ // 获取的全部请求信息
+ ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+ if (attributes != null){
+ HttpServletRequest request = attributes.getRequest();
+ // 获取所有的请求头信息
+ Enumeration headerNames = request.getHeaderNames();
+ if (headerNames != null){
+ while (headerNames.hasMoreElements()){
+ // 获取请求头的key
+ String element = headerNames.nextElement();
+ // 获取请求头的value
+ String value = request.getHeader(element);
+ ----------------------------------------------------------------------------------------------------------------
+ // 跳过 content-length
+ if (element.equals("content-length")){
+ continue;
+ }
+ ----------------------------------------------------------------------------------------------------------------
+ // 将请求头信息放入到请求头
+ requestTemplate.header(element,value);
+ }
+ }
+ }
+ }
+}
+
+```
+
+### 4. 博客展示
+
+
+
+#### 4.1 详情
+
+
+
+#### 4.2 关于我
+
+
+
+### 5.小说展示
+
+
+
+#### 5.2 小说展示
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/snipaste_20211030_152133.png b/images/snipaste_20211030_152133.png
new file mode 100644
index 0000000..d9b5f47
Binary files /dev/null and b/images/snipaste_20211030_152133.png differ
diff --git a/images/snipaste_20211030_155720.png b/images/snipaste_20211030_155720.png
new file mode 100644
index 0000000..f95db28
Binary files /dev/null and b/images/snipaste_20211030_155720.png differ
diff --git a/images/snipaste_20211030_164359.png b/images/snipaste_20211030_164359.png
new file mode 100644
index 0000000..17766b4
Binary files /dev/null and b/images/snipaste_20211030_164359.png differ
diff --git a/images/snipaste_20211030_164909.png b/images/snipaste_20211030_164909.png
new file mode 100644
index 0000000..a032463
Binary files /dev/null and b/images/snipaste_20211030_164909.png differ
diff --git a/images/snipaste_20211030_175939.png b/images/snipaste_20211030_175939.png
new file mode 100644
index 0000000..3a6c6bb
Binary files /dev/null and b/images/snipaste_20211030_175939.png differ
diff --git a/images/snipaste_20211030_180038.png b/images/snipaste_20211030_180038.png
new file mode 100644
index 0000000..cc8a86c
Binary files /dev/null and b/images/snipaste_20211030_180038.png differ
diff --git a/images/snipaste_20211101_112449.png b/images/snipaste_20211101_112449.png
new file mode 100644
index 0000000..736319f
Binary files /dev/null and b/images/snipaste_20211101_112449.png differ
diff --git a/images/snipaste_20211101_112721.png b/images/snipaste_20211101_112721.png
new file mode 100644
index 0000000..361ea28
Binary files /dev/null and b/images/snipaste_20211101_112721.png differ
diff --git a/images/snipaste_20211101_145433.png b/images/snipaste_20211101_145433.png
new file mode 100644
index 0000000..428768e
Binary files /dev/null and b/images/snipaste_20211101_145433.png differ
diff --git a/images/snipaste_20211101_145754.png b/images/snipaste_20211101_145754.png
new file mode 100644
index 0000000..9d76a5e
Binary files /dev/null and b/images/snipaste_20211101_145754.png differ
diff --git a/images/snipaste_20211101_145937.png b/images/snipaste_20211101_145937.png
new file mode 100644
index 0000000..2852aba
Binary files /dev/null and b/images/snipaste_20211101_145937.png differ
diff --git a/images/snipaste_20211101_172314.png b/images/snipaste_20211101_172314.png
new file mode 100644
index 0000000..74ca058
Binary files /dev/null and b/images/snipaste_20211101_172314.png differ
diff --git a/images/snipaste_20211101_172449.png b/images/snipaste_20211101_172449.png
new file mode 100644
index 0000000..e7cc9ef
Binary files /dev/null and b/images/snipaste_20211101_172449.png differ
diff --git a/images/snipaste_20211102_151056.png b/images/snipaste_20211102_151056.png
new file mode 100644
index 0000000..240fc0a
Binary files /dev/null and b/images/snipaste_20211102_151056.png differ
diff --git a/images/snipaste_20211104_104922.png b/images/snipaste_20211104_104922.png
new file mode 100644
index 0000000..a3251b4
Binary files /dev/null and b/images/snipaste_20211104_104922.png differ
diff --git a/images/snipaste_20211104_105055.png b/images/snipaste_20211104_105055.png
new file mode 100644
index 0000000..e4725e6
Binary files /dev/null and b/images/snipaste_20211104_105055.png differ
diff --git a/images/snipaste_20211106_144846.png b/images/snipaste_20211106_144846.png
new file mode 100644
index 0000000..2340ba3
Binary files /dev/null and b/images/snipaste_20211106_144846.png differ
diff --git a/images/snipaste_20211106_154833.png b/images/snipaste_20211106_154833.png
new file mode 100644
index 0000000..8667d62
Binary files /dev/null and b/images/snipaste_20211106_154833.png differ
diff --git a/images/snipaste_20211108_160302.png b/images/snipaste_20211108_160302.png
new file mode 100644
index 0000000..6187ba4
Binary files /dev/null and b/images/snipaste_20211108_160302.png differ
diff --git a/images/snipaste_20211108_163411.png b/images/snipaste_20211108_163411.png
new file mode 100644
index 0000000..8532563
Binary files /dev/null and b/images/snipaste_20211108_163411.png differ
diff --git a/images/snipaste_20211108_163640.png b/images/snipaste_20211108_163640.png
new file mode 100644
index 0000000..41c10d2
Binary files /dev/null and b/images/snipaste_20211108_163640.png differ
diff --git a/images/snipaste_20211108_163901.png b/images/snipaste_20211108_163901.png
new file mode 100644
index 0000000..9cbbd32
Binary files /dev/null and b/images/snipaste_20211108_163901.png differ
diff --git a/images/snipaste_20211108_165356.png b/images/snipaste_20211108_165356.png
new file mode 100644
index 0000000..bd520ae
Binary files /dev/null and b/images/snipaste_20211108_165356.png differ
diff --git a/images/snipaste_20211109_150329.png b/images/snipaste_20211109_150329.png
new file mode 100644
index 0000000..5499d69
Binary files /dev/null and b/images/snipaste_20211109_150329.png differ
diff --git a/images/snipaste_20211109_150805.png b/images/snipaste_20211109_150805.png
new file mode 100644
index 0000000..274613d
Binary files /dev/null and b/images/snipaste_20211109_150805.png differ
diff --git a/images/snipaste_20211109_151003.png b/images/snipaste_20211109_151003.png
new file mode 100644
index 0000000..8b5406b
Binary files /dev/null and b/images/snipaste_20211109_151003.png differ
diff --git a/images/snipaste_20211109_162244.png b/images/snipaste_20211109_162244.png
new file mode 100644
index 0000000..feb6285
Binary files /dev/null and b/images/snipaste_20211109_162244.png differ
diff --git a/images/snipaste_20211110_141127.png b/images/snipaste_20211110_141127.png
new file mode 100644
index 0000000..8db4b99
Binary files /dev/null and b/images/snipaste_20211110_141127.png differ
diff --git a/images/snipaste_20211112_143604.png b/images/snipaste_20211112_143604.png
new file mode 100644
index 0000000..c75add3
Binary files /dev/null and b/images/snipaste_20211112_143604.png differ
diff --git a/images/snipaste_20211117_153059.png b/images/snipaste_20211117_153059.png
new file mode 100644
index 0000000..bb73f44
Binary files /dev/null and b/images/snipaste_20211117_153059.png differ
diff --git a/images/snipaste_20211117_153239.png b/images/snipaste_20211117_153239.png
new file mode 100644
index 0000000..1c2369e
Binary files /dev/null and b/images/snipaste_20211117_153239.png differ
diff --git a/images/snipaste_20211117_153517.png b/images/snipaste_20211117_153517.png
new file mode 100644
index 0000000..2f043fc
Binary files /dev/null and b/images/snipaste_20211117_153517.png differ
diff --git a/images/snipaste_20211213_160516.png b/images/snipaste_20211213_160516.png
new file mode 100644
index 0000000..755e268
Binary files /dev/null and b/images/snipaste_20211213_160516.png differ
diff --git a/images/snipaste_20211213_160628.png b/images/snipaste_20211213_160628.png
new file mode 100644
index 0000000..e9d0c70
Binary files /dev/null and b/images/snipaste_20211213_160628.png differ
diff --git a/images/snipaste_20211213_160806.png b/images/snipaste_20211213_160806.png
new file mode 100644
index 0000000..36d4984
Binary files /dev/null and b/images/snipaste_20211213_160806.png differ
diff --git a/images/snipaste_20211213_161208.png b/images/snipaste_20211213_161208.png
new file mode 100644
index 0000000..d8e6835
Binary files /dev/null and b/images/snipaste_20211213_161208.png differ
diff --git a/images/snipaste_20211213_170643.png b/images/snipaste_20211213_170643.png
new file mode 100644
index 0000000..666adb7
Binary files /dev/null and b/images/snipaste_20211213_170643.png differ
diff --git a/images/snipaste_20211213_170811.png b/images/snipaste_20211213_170811.png
new file mode 100644
index 0000000..ba64aec
Binary files /dev/null and b/images/snipaste_20211213_170811.png differ
diff --git a/images/snipaste_20220809_115027.png b/images/snipaste_20220809_115027.png
new file mode 100644
index 0000000..0c9256f
Binary files /dev/null and b/images/snipaste_20220809_115027.png differ
diff --git a/images/snipaste_20220810_101810.png b/images/snipaste_20220810_101810.png
new file mode 100644
index 0000000..efbab7d
Binary files /dev/null and b/images/snipaste_20220810_101810.png differ
diff --git a/images/snipaste_20220810_102320.png b/images/snipaste_20220810_102320.png
new file mode 100644
index 0000000..2d23089
Binary files /dev/null and b/images/snipaste_20220810_102320.png differ
diff --git a/mystyle-cloud-admin-manager/src/main/java/com/zhangmeng/admin/manager/config/web/WebMvcConfig.java b/mystyle-cloud-admin-manager/src/main/java/com/zhangmeng/admin/manager/config/web/WebMvcConfig.java
new file mode 100644
index 0000000..876ef18
--- /dev/null
+++ b/mystyle-cloud-admin-manager/src/main/java/com/zhangmeng/admin/manager/config/web/WebMvcConfig.java
@@ -0,0 +1,30 @@
+package com.zhangmeng.admin.manager.config.web;
+
+import com.zhangmeng.admin.manager.interceptor.RequestInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * @author zhangmeng
+ * @version 1.0
+ * @date 2024-05-15 10:18
+ */
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+
+
+ @Autowired
+ private RequestInterceptor indexInterceptor;
+
+ /**
+ * 注册拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ //请求拦截器
+ registry.addInterceptor(indexInterceptor).addPathPatterns("/**");
+ }
+
+}
diff --git a/mystyle-cloud-admin-manager/src/main/java/com/zhangmeng/admin/manager/interceptor/MybatisLogInterceptor.java b/mystyle-cloud-admin-manager/src/main/java/com/zhangmeng/admin/manager/interceptor/MybatisLogInterceptor.java
new file mode 100644
index 0000000..d7818fe
--- /dev/null
+++ b/mystyle-cloud-admin-manager/src/main/java/com/zhangmeng/admin/manager/interceptor/MybatisLogInterceptor.java
@@ -0,0 +1,112 @@
+package com.zhangmeng.admin.manager.interceptor;
+
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.ParameterMapping;
+import org.apache.ibatis.plugin.*;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.session.Configuration;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+import org.apache.ibatis.type.TypeHandlerRegistry;
+import org.springframework.stereotype.Component;
+
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Properties;
+
+/**
+ * @author zhangmeng
+ * @version 1.0
+ * @date 2021年5月24日20:45:21
+ */
+@Component
+@Slf4j
+@Intercepts({
+ @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
+ @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class MybatisLogInterceptor implements Interceptor {
+
+ @Override
+ public Object intercept(Invocation invocation) throws Throwable {
+ MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
+ Object parameter = null;
+ if (invocation.getArgs().length > 1) {
+ parameter = invocation.getArgs()[1];
+ }
+ String sqlId = mappedStatement.getId();
+ BoundSql boundSql = mappedStatement.getBoundSql(parameter);
+ Configuration configuration = mappedStatement.getConfiguration();
+ long start = System.currentTimeMillis();
+ Object returnValue = invocation.proceed();
+ long time = System.currentTimeMillis() - start;
+ showSql(configuration, boundSql, time, sqlId);
+ return returnValue;
+ }
+
+ private static void showSql(Configuration configuration, BoundSql boundSql, long time, String sqlId) {
+ Object parameterObject = boundSql.getParameterObject();
+ List parameterMappings = boundSql.getParameterMappings();
+ //替换空格、换行、tab缩进等
+ String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
+ if (parameterMappings.size() > 0 && parameterObject != null) {
+ TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
+ if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
+ sql = sql.replaceFirst("\\?", getParameterValue(parameterObject));
+ } else {
+ MetaObject metaObject = configuration.newMetaObject(parameterObject);
+ for (ParameterMapping parameterMapping : parameterMappings) {
+ String propertyName = parameterMapping.getProperty();
+ if (metaObject.hasGetter(propertyName)) {
+ Object obj = metaObject.getValue(propertyName);
+ sql = sql.replaceFirst("\\?", getParameterValue(obj));
+ } else if (boundSql.hasAdditionalParameter(propertyName)) {
+ Object obj = boundSql.getAdditionalParameter(propertyName);
+ sql = sql.replaceFirst("\\?", getParameterValue(obj));
+ }
+ }
+ }
+ }
+ logs(time, sql, sqlId);
+ }
+
+ private static String getParameterValue(Object obj) {
+ String value;
+ if (obj instanceof String) {
+ value = "'" + obj.toString() + "'";
+ } else if (obj instanceof Date) {
+ DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
+ value = "'" + formatter.format(new Date()) + "'";
+ } else if (obj instanceof Enum) {
+ int ordinal = ((Enum) obj).ordinal();
+ value = String.valueOf(ordinal);
+ } else {
+ if (obj != null) {
+ value = obj.toString();
+ } else {
+ value = "";
+ }
+ }
+ return value.replace("$", "\\$");
+ }
+
+ private static void logs(long time, String sql, String sqlId) {
+ sql = "耗时:" + time + "ms - ID: " + sqlId + sql;
+ log.info(sql);
+ }
+
+ @Override
+ public Object plugin(Object target) {
+ return Plugin.wrap(target, this);
+ }
+
+ @Override
+ public void setProperties(Properties properties0) {
+ }
+}
diff --git a/mystyle-cloud-admin-manager/src/main/java/com/zhangmeng/admin/manager/interceptor/RequestInterceptor.java b/mystyle-cloud-admin-manager/src/main/java/com/zhangmeng/admin/manager/interceptor/RequestInterceptor.java
new file mode 100644
index 0000000..9dddbd1
--- /dev/null
+++ b/mystyle-cloud-admin-manager/src/main/java/com/zhangmeng/admin/manager/interceptor/RequestInterceptor.java
@@ -0,0 +1,48 @@
+package com.zhangmeng.admin.manager.interceptor;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author zhangmmeng
+ * @version 1.0
+ * @date 2021年6月17日11:08:27
+ *
+ */
+@Component
+@Slf4j
+public class RequestInterceptor implements HandlerInterceptor {
+
+ @Value("${spring.application.name}")
+ private String name;
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ return true;
+ }
+
+ @Override
+ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
+ ModelAndView modelAndView) throws Exception {
+ String requestType = request.getHeader("X-Requested-With");
+ String base_url = request.getScheme() + "://" + request.getLocalAddr() + ":" + request.getServerPort();
+ //非ajax请求
+ if (modelAndView != null){
+ log.info("webpath=" + base_url);
+ // 工具类
+ modelAndView.addObject("webPath",base_url );
+ modelAndView.addObject("application_name",name );
+ }
+ }
+
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
+ throws Exception {
+ }
+}
diff --git a/mystyle-cloud-admin-manager/src/main/resources/application.yml b/mystyle-cloud-admin-manager/src/main/resources/application.yml
index 84118e4..af07307 100644
--- a/mystyle-cloud-admin-manager/src/main/resources/application.yml
+++ b/mystyle-cloud-admin-manager/src/main/resources/application.yml
@@ -40,6 +40,7 @@ spring:
cache: false
enabled: true
request-context-attribute: request
+
feign:
sentinel:
enabled: true
diff --git a/mystyle-cloud-admin-manager/src/main/resources/static/system/admin/js/mystyle-admin.js b/mystyle-cloud-admin-manager/src/main/resources/static/system/admin/js/mystyle-admin.js
index dc9b613..2fa4a35 100644
--- a/mystyle-cloud-admin-manager/src/main/resources/static/system/admin/js/mystyle-admin.js
+++ b/mystyle-cloud-admin-manager/src/main/resources/static/system/admin/js/mystyle-admin.js
@@ -1,7 +1,7 @@
//网关地址
var gate_way_url = "http://localhost:9000";
//后台管理微服务
-var admin_manager_url = "admin";
+var admin_manager_url = "mystyle-cloud-admin-manager";
//授权微服务
var user_oauth_url = "mystyle-cloud-oauth";
//博客微服务
diff --git a/mystyle-cloud-admin-manager/src/main/resources/static/system/config/pear.config.yml b/mystyle-cloud-admin-manager/src/main/resources/static/system/config/pear.config.yml
index 6e1ddc9..df316a0 100644
--- a/mystyle-cloud-admin-manager/src/main/resources/static/system/config/pear.config.yml
+++ b/mystyle-cloud-admin-manager/src/main/resources/static/system/config/pear.config.yml
@@ -4,11 +4,11 @@ logo:
## 网站名称
title: "MY Style"
## 网站图标
- image: "/admin/system/admin/images/logo.png"
+ image: "/mystyle-cloud-admin-manager/system/admin/images/logo.png"
## 菜单配置
menu:
## 菜单数据来源
- data: "/admin/user/menuList"
+ data: "/mystyle-cloud-admin-manager/user/menuList"
## 菜单接口的请求方式 GET / POST
method: "GET"
## 是否同时只打开一个菜单目录
@@ -34,7 +34,7 @@ tab:
## 首页
index:
id: "0" ## 标识 ID , 建议与菜单项中的 ID 一致
- href: "/admin/home" ## 页面地址
+ href: "/mystyle-cloud-admin-manager/home" ## 页面地址
title: "首页" ## 标题
## 主题配置
theme:
@@ -70,4 +70,4 @@ other:
## 头部配置
header:
## 站内消息,数据来源,通过 false 设置关闭
- message: "admin/data/message.json"
\ No newline at end of file
+ message: "mystyle-cloud-admin-manager/data/message.json"
\ No newline at end of file
diff --git a/mystyle-cloud-admin-manager/src/main/resources/templates/admin/article/add.ftl b/mystyle-cloud-admin-manager/src/main/resources/templates/admin/article/add.ftl
index e41dcf7..cb27faa 100644
--- a/mystyle-cloud-admin-manager/src/main/resources/templates/admin/article/add.ftl
+++ b/mystyle-cloud-admin-manager/src/main/resources/templates/admin/article/add.ftl
@@ -3,9 +3,9 @@
文章添加
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
-
-
+
+
+
-
-
+
+
+
-
-
-
+
+
+
-
-
+
+
+
-
+
+
diff --git a/mystyle-cloud-admin-manager/src/main/resources/templates/admin/code/hash.ftl b/mystyle-cloud-admin-manager/src/main/resources/templates/admin/code/hash.ftl
index cbc9f31..2240eb9 100644
--- a/mystyle-cloud-admin-manager/src/main/resources/templates/admin/code/hash.ftl
+++ b/mystyle-cloud-admin-manager/src/main/resources/templates/admin/code/hash.ftl
@@ -3,7 +3,7 @@
-
+
@@ -117,8 +117,8 @@
-
-
+
+
-
+
+
diff --git a/mystyle-cloud-admin-manager/src/main/resources/templates/admin/error/404.ftl b/mystyle-cloud-admin-manager/src/main/resources/templates/admin/error/404.ftl
index a952768..2eca0c5 100644
--- a/mystyle-cloud-admin-manager/src/main/resources/templates/admin/error/404.ftl
+++ b/mystyle-cloud-admin-manager/src/main/resources/templates/admin/error/404.ftl
@@ -3,19 +3,19 @@
-
-
+
+
-

+
404
抱歉,你访问的页面不存在或仍在开发中
-
-
+
+