原则

1.service层编写原则

小心service组件循环依赖问题!!!

  1. Controller调用Service层是:一对一接口调用,且Controller层不做任何业务处理,目的是为了后续拓展直接替换Controller为RPC框架而准备
  2. 同一模块下Service层避免互相调用:一般情况下事物配置在service层,为了避免事物嵌套或单个事物过大等问题的
  3. 同一模块下service层调用dao层:除了尽量控制事物大小,即控制Service调用dao层的复杂度,将单个事物经量控制在100ms之内
  4. 对第二条进行补充,同一模块下避免互相调用service而选择调用dao不同模块下尽量互相调用service
  5. 加锁范围一定要大于事务范围!!!事务范围不能比加锁范围大
  6. 调用其它模块的service时,尽量不要用到其它模块的模型对象
  7. 同一个service的方法相互调用时,aop一般不会生效,我们需要手动获取其代理对象再进行同一个service的方法相互调用
  8. 解析前先判断,可以手动避免抛出异常
  9. 优先使用 ThreadPoolTaskExecutor 而不是 ThreadPoolExecutor 。

2.Mysql使用原则

  1. 尽量不要在mysql层面使用唯一校验。因为我们会有isDelete字段的存在,当isDelete为true时认为要忽略这条记录,保证未删除记录字段的唯一,即删除记录的字段是可以与未删除记录字段重复的,但mysql无法实现这个功能(或者说实现起来需要认为添加一个联合唯一索引,且必须在删除时更新维护一个多余的字段,比较麻烦)。而且数据库校验很不灵活,会增加数据库负担。
  2. 尽量在后端service层实现唯一校验、存在校验、操作校验、子节点校验等等!实现方便且可以编写灵活复杂的校验逻辑,当然缺点就是与数据库的交互会急剧增加。

3.前端原则

  1. 前端代码比较“兼容”,一个json对象多了几个属性还是可以赋值给少了这些属性的变量,同理一个json对象少了几个属性还是可以赋值给多了这些属性的变量。即赋值没有严格的属性一致性
  2. async异步函数内部一定要try-catch。以处理异常回调。

springMVC

1.java web项目 springmvc.xml 配置文件错误

==问题提示:==java web项目 springmvc.xml 配置文件错误。抛出异常Cannot resolve reference to bean ‘cacheManager‘ while setting bean property ‘cacheManager‘

==解决办法:==检查 springmvc.xml 配置文件的命名空间,将自动导入的cache改为mvc。

image-20240214165413128

2.java web项目配置 Tomcat 错误

==问题提示:==请求一直404。其实是请求路径前缀问题。

==解决办法:==检查IDEA中的Tomcat如下 Application Context设置,会给url带指定的路径前缀,如果你的请求路径所带的前缀不一致就会一直404。

image-20240313195603777

另一个请求路径相关的设置,以下路径设置与项目无关。

image-20240313200019345

Spring

1.关于Spring Cache的错误

==问题提示:==EL1007E: Property or field ‘id’ cannot be found on null。id属性不能从null对象中找到。

==解决办法:==注意Spring Cache的使用,其注解的 key 属性不能指定为方法返回值的属性或相关内容,否则为null。所以报错空指针。

@Transcational会生成代理对象,原理是AOP动态代理。


Mybatis-plus

1.mybatis与mybatis-plus版本不兼容问题NoSuchMethodError

==问题提示:==java.lang.NoSuchMethodError: org.apache.ibatis.session.Configuration.setArgNameBasedConstructorAutoMapping(Z)V

==解决办法:==在mybatis-plus源码中找其依赖的mybatis版本!!!

2.Mybatis-plus批量操作

不要使用Iservice提供的saveBatch,耗时最多循环插入都比它快。各种批量插入方式效率分析

默认BaseMapper没有insertBatch()方法,实现方式有:

  1. 编写Mapper接口和Mapper.xml。自定义insertBatch()方法
  2. 使用mybatis-plus提供了InsertBatchSomeColumn批量insert方法
    1. 自定义sql注入类继承DefaultSqlInjector
    2. mybatiplus配置类配置自定义sql注入新类的bean
    3. 创建MyBaseMapper接口继承BaseMapper接口,并添加抽象方法 int insertBatchSomeColumn(List<T> entityList);
    4. 自定义的Mapper继承MyBaseMapper
    5. service调用
  3. 官网提供的MybatisBatch实现批量操作,支持insert、update、delete

可以开启mysql的批处理支持jdbc:mysql://localhost:3306/wzyapi?rewriteBatchedStatements=true提高批处理速度。

还可以开启mybatis-plus的批处理模式。在application.yaml中配置

1
2
mybatis-plus:
executor-type: batch

3、mysql账号密码错误而导致的无法连接

==问题提示==:突然不能连接数据库了。

==解决办法==:查看账号修改密码。并设置root用户 'root'@'%' 任意ip可访问。小心不是‘root‘@’0.0.0.0’!!!这样不生效!!!

4、mybtais-plus是如何通过lambda方法引用获取字段名的

参考博客:https://blog.csdn.net/justry_deng/article/details/124059375

原理:方法引用的序列化机制,读取其方法名再解析出属性名就是字段名

源码:

Person::getName方法引用会被动态生成下述类:其中重要的是 writeReplace() 方法,这是序列化的lambda表达式信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//JVM自动生成的类,运行时直接dump class出来后反编译出来
final class MainTests$$Lambda$1 implements SFunction {
@Hidden
public Object apply(Object var1) {
return ((Person)var1).getName();
}

private final Object writeReplace() {
return new SerializedLambda(
MainTests.class,
"com/example/lambda/demo/SFunction",
"apply",
"(Ljava/lang/Object;)Ljava/lang/Object;",
5,
"com/example/lambda/test/Person",
"getName",
"()Ljava/lang/String;",
"(Lcom/example/lambda/test/Person;)Ljava/lang/Object;",
new Object[0]
);
}
}

AbstractLambdaWrapper 类中的 getColumnCache 方法会调用 LambdaUtils.extract(column);。通过反射调用 column 的 writeReplace 方法获取 SerializedLambda 对象,并将其包装为 ReflectLambdaMeta ,最终还是从 SerializedLambda 获取 ImplMethodName

  1. LambdaUtils.extract(column) 根据lambda表达反射调用 writeReplace 方法获取 SerializedLambda 对象
  2. 将 SerializedLambda 包装为 ReflectLambdaMeta 返回
  3. 通过 ReflectLambdaMeta 获取 SerializedLambda 的 implMethodName 属性就是lambda方法引用的方法名称
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//AbstractLambdaWrapper.java
protected ColumnCache getColumnCache(SFunction<T, ?> column) {
//1.通过反射获取
LambdaMeta meta = LambdaUtils.extract(column);
//3.获取字段名
String fieldName = PropertyNamer.methodToProperty(meta.getImplMethodName());
Class<?> instantiatedClass = meta.getInstantiatedClass();
tryInitCache(instantiatedClass);
return getColumnCache(fieldName, instantiatedClass);
}

//LambdaUtils.java
public static <T> LambdaMeta extract(SFunction<T, ?> func) {
。。。
// 2. 反射读取
try {
//2.1反射调用 lambda生成的类的 writeReplace 方法获取到 SerializedLambda 对象(见生成类的源码)
Method method = func.getClass().getDeclaredMethod("writeReplace");
method.setAccessible(true);
//2.2
return new ReflectLambdaMeta((SerializedLambda) method.invoke(func), func.getClass().getClassLoader());
} catch (Throwable e) {
。。。
}
}

5.自定义TypeHandler类型解析器

1
2
3
4
5
6
7
8
@TableName(autoResultMap = true)//一定要开启映射注解,否则不会生效
@TableName(value ="tenant_package",autoResultMap = true)
@Data
public class TenantPackage implements Serializable {

@TableField(value = "menuIds",typeHandler = LongSetTypeHandler.class)
private Set<Long> menuIds;
}
  1. **@TableName(autoResultMap = true)**注解的autoResultMap 属性一定要置为true
  2. @TableField(value = “menuIds”,typeHandler = LongSetTypeHandler.class)entity对象属性上一定要指定typeHandler
  3. Mapper.xml中如果写了ResultMap一定要标明字段的typeHandler
1
<result property="menuIds" column="menuIds" jdbcType="VARCHAR" typeHandler="com.wzy.project.framework.mybatis.type.LongSetTypeHandler"/>

6.自定义批量插入要判断集合是否为空,否则sql出错

多租户情况下,新租户最易出现这种情况。


OpenFeign

1.关于OpenFeign的controller层参数校验

==问题提示==:A method overriding another method must not redefine the parameter constraint configuration。

==解决办法==:继承模式下,参数校验写在接口文件中,controller层实现只留实现,在controller层写@Vlidated注解在类上就行,其它校验注解不要写否则会报错

2.OpenFeign调用的服务配置了server.servlet.context-path时,调用出现404

==问题提示==:feign.FeignException$NotFound: [404] during [GET] to [XXXXXXX]

==解决办法==:这是由于 server.servlet.context-path 配置会自动为controller层的路径再次添加前缀导致的,无论我们interface文件的方法上注解的请求路径怎么写都无济于事,实现方微服务都会在前面添加前缀,所以我们需要在 @FeignClient(name = "XXX",path = "/api") 添加Feign远程调用请求的前缀,即客户端远程调用请求前缀由@FeignClient指定,服务端远程调用请求前缀由server.servlet.context-path配置指定,这两者必须相同,否则404。

3.


前端

前端打印对象 JSON.stringfy(obj)

if (actionRef.current) {
actionRef.current.reload()
}

actionRef.current?.reload()

是等价的

1.npm认证过期,证书过期

==问题提示:==npm ERR! code CERT_HAS_EXPIRED 。npm认证过期,证书过期问题。

==解决办法:==CERT_HAS_EXPIRED是一个由Node.js和npm抛出的错误,表示你正在尝试访问的服务器的SSL证书已经过期。

  1. 清除npm缓存:npm cache clean --force

  2. 取消ssl验证:npm config set strict-ssl false

  3. 之后再npm install 你想安装的东西

2.echarts-for-react做图时,图数据不实时变化

困扰1小时!!!

==问题提示:==定义了一个const option变量传递给图,其中option.tilte.text是一个字面量。因为定义的为常量,所以后续js中改变option.title.text就会失效。

==解决办法:==定义const option变量时将option.tilte.text也定义为变量。通过setTiltle实时变化数据!!!

3.HttpMessageNotReadableException

==问题提示:==HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type java.lang.String from Object value (token JsonToken.START_OBJECT)

前端json对象(HttpMessage)无法反序列化为后端String对象。因为这样的话需要先反序列化,再序列化,但是默认HTTP请求处理只会反序列化。

==解决办法:==前端数据输入修改正常。

4.Ant Design图标

参考文章:https://github.com/ant-design/ant-design/issues/20668

三种表示图标的方法:

  1. <MessageOutlined />

  2. icon={MessageOutlined}

  3. icon="message"

image-20240301164748532
1
2
3
// 获取全局属性。用户信息
const { initialState } = useModel('@@initialState');
const { loginUser } = initialState || {};

5.ant-design-pro修改前端项目的路径后,运行后报错

==问题提示:== Can not resolve dependence ‘ant-design-pro/node_modules/@umijs/renderer-react’, please install it.

==解决办法:==删除新路径中的 如:E:\dev\new-ant-design-pro\node_modules\ 的文件夹 .cache。 再重新运行项目

6.前端在打包构建时报错冲突

==解决办法:==删除原来dist文件

7.Ant Design Pro前端上线后出现404页面请求

==解决办法:==将umi路由方式从默认的browser改为hash路由

8.浏览器前端请求本质

将nginx中的前端代码获取到浏览器中渲染。

umi框架在使用build时自动传入了NODE_ENV == prod

9.React的setState是异步执行的

10.前端向后端传递日期问题

==问题提示:== springboot中报错Invalid character found in the request。浏览器option请求直接400。浏览器响应信息提示String无法转LocalDateTime。问题一:Tomcat不接受[]字符的url。问题二:日期字符串在mvc不能自动转换为LocalDateTime。

==解决办法:==针对问题一:配置文件配置Tomcat,让Tomcat允许[]字符。

1
2
3
4
5
server:
tomcat:
relaxed-query-chars:
- "["
- "]"

针对问题二:VO层的实体类上在日期字段上添加注解@DateTimeFormat(pattern = DATETIME_FORMAT)告诉后端你要如何解析日期字符串

11.Ant Desgin Pro使用时更新对话框没有携带id字段

==问题提示:==没有更新时后端报错没有id,即前端没有传递 id字段。究其原因是对话框没有设置id字段。

==解决办法:==在前端执行API更新请求时,指定id字段。

12.Ant Desgin Pro中的Form.Item问题

参考文章:https://blog.csdn.net/qq_43720551/article/details/131502261

==问题提示:==input框里面的数值消失。前端提交不到表单。

==解决办法:==原因是Form.Item在设置name属性后,input框的value属性值会被覆盖,即 Form.Item 来管理输入框中的内容,这时我们去Form.Item中设置初始值属性就好了。

13.后端接收不到前端的数据

==问题提示:==数据正常发送,格式也没有问题。最后问题是出在后端注解,没有使用 @RequestBody 注解来处理前端传来的参数。导致校验Bean Vlidation报错。

==解决办法:==后端检查注解,确保正确被处理。

14.日期字符串在前端页面格式化

1
2
3
4
5
6
7
8
9
10
11
/**
* 日期字符串格式化
* @param val
* @param params
*/
const formatDate = (val:string|undefined,params='YYYY年MM月DD日 HH:mm:ss') => {
if (!val) {
return null;
}
return moment(val).format(params);
}

15.页面组件的子组件加载问题【useEffect(,[])方法】

==注意:==页面组件在第一次加载时会调用useEffect(,[])方法,也同时会所有调用子组件的useEffect(,[])方法。而且子组件在显示时不会再次调用useEffect()方法!!!

==注意:==但是我们**稍微改变一下将其变为useEffect(,[监听对象])**,一旦对象变化就会监听到并执行useEffect(,[监听对象])。这样就可以多次调用了。

总结:useEffect()函数是一个非常好用的函数!!!

列表的 initialValue 就是初始值,会被动态的覆盖,或者说一直就是这个值不会改变。我们要使用 useEffect()函数函数来动态的改变对话框里面的input标签的值

16.文件上传问题

参考博客:https://blog.csdn.net/java0506/article/details/108078867

==问题提示:==Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part ‘multipartFile’ is not present]

情况描述:ant desgin文件上传时,直接使用表格封装的value对象来取 file 会取不到真正的file文件对象。

==解决办法:==1.首先上传标签的 beforeUpload 属性设置返回false阻止文件自动上传。2.其次使用表单的表单项标签 getValueFromEvent 属性获取真正的文件对象{file: ,fileList: },并创建 FormData 对象(这是最终请求体里面的对象非常重要)将file保证到里面。3.发送请求时请求体携带 formdata 对象即可。

注意:ant desgin pro会根据你构造的请求对象,自动填充请求头的Content-Type值。

==问题提示:==Springboot报错Required request part ‘file‘ is not present

==解决办法:==这是由于设置到 FormData 对象的文件对象不正确导致的,即设置的不是真正的文件对象。需要将file对象设置进去。

1
2
3
4
5
6
7
8
//用于获取文件对象,并保存到 formData 中
const normFile = (e: any) => {
formData.append('multipartFile', e.file) <------*
if (Array.isArray(e)) {
return e
}
return e && e.fileList;
}

17.Form.Item里面checkBox赋值后不生效问题

==问题提示:==checkBox选中后,并没有传到Form.Item被其管理,表单结果没有选中的值。

==解决办法:==语法问题。如下表单项就无法管理到 checkBox 的值。

1
2
3
4
<Form.Item name={"updateSupport"} valuePropName={'checked'} initialValue={false}>
<Checkbox>是否更新已经存在的用户数据</Checkbox>
<div>仅允许导入xls、xlsx格式文件。<a>下载模板</a></div>
</Form.Item>

必须改为

1
2
3
4
<Form.Item name={"updateSupport"} valuePropName={'checked'} initialValue={false}>
<Checkbox>是否更新已经存在的用户数据</Checkbox>
</Form.Item>
<div>仅允许导入xls、xlsx格式文件。<a>下载模板</a></div>

18.对话框结束后Dragger标签清空问题

无法双向绑定清空Dragger标签数据???

19.TreeSelect标签初始时传入了初始值但checkBox没有显示选中

==问题提示:==TreeSelect标签初始时传入了初始值但checkBox没有显示选中

==解决办法:==数据类型不匹配问题,options传入的类型为{value:string,title:string},但是传入的初始值数据是number[]类型就会导致checkBox没有显示选中。解决方案一:将options传入的类型改为{value:number,title:string},解决方案一:将初始值改为string[]

20.使用antd的openapi报错

==问题提示:==TypeError: Cannot read properties of undefined (reading ‘version’)

==解决办法:==这种情况一般是前端无法访问后端此url路径:/v3/api-docs导致的。

Java

1.json字符串转具体泛型对象,例如BaseResopnse<String>

困扰1小时!!!

==问题提示:==1.使用原始泛型类型为变量类型报警。2.BaseResopnse类型值不能赋值到BaseResopnse<String>变量上。

image-20240206203540636

image-20240206203756240

==解决办法:==使用方法JSONUtil.toBean(result, new TypeReference<BaseResponse<String>>() {},false)。即可返回泛型类型的对象值。

2.java.lang.LinkageError【devtools导致】

困扰1小时!!!

==问题提示:==两个类加载器RestartClassLoaderLauncher$AppClassLoader加载同一个方法签名冲突。devtools两个类加载器加载同一个类导致的LinkageError。

1
2
3
4
5
java.lang.LinkageError: loader constraint violation: 
when resolving method "com.wzy.wzyapiclientsdk.client.WzyApiClient.getUserNameByPost(Lcom/wzy/wzyapiclientsdk/model/User;)Lcom/wzy/wzyapicommon/common/BaseResponse;"
the class loader (instance of org/springframework/boot/devtools/restart/classloader/RestartClassLoader) of the current class, com/wzy/project/controller/InterfaceInfoController,
and the class loader (instance of sun/misc/Launcher$AppClassLoader) for the method's defining class, com/wzy/wzyapiclientsdk/client/WzyApiClient,
have different Class objects for the type com/wzy/wzyapicommon/common/BaseResponse used in the signature

LinkageError: loader constraint violation: when resolving method the class loader of the current class,and the class loader for the method have different Class objects for the type used in the signature

==解决办法:==LinkageError出现的情况复杂,一般发生在被多个类加载器加载的类发生交互时出现。这里是由于springboot装配devtools后,类被加载两次导致。

devtools加载了两次后,导致有两个类型的BaseResponse,最终导致调用方法getUserNameByPost时类型转换异常。解决办法就是去掉devtools依赖。https://blog.csdn.net/tongyimplin/article/details/80983272

3.java 反射调用函数问题(实际是HttpUtil客户端使用错误抛出的异常)

==问题提示:==java.lang.reflect.InvocationTargetException调用失败

==解决办法:==此异常是被调用函数抛出的异常。需要检查被调用函数逻辑。注意使用Hutool发送请求时,不要设置int[]类型的参数,不要使用原始类似数组,否则会报异常,如果传入了原始类型数组,转换一下为包装类似数组。Hutool源码如下:

image-20240209183009094

List.toArray(需要输入数组对象)。否则创建的是 Object[] 对象

==JSONArray里面只包括JSONObject、JSONArray和原始数据类型!!!==JSON对象很方便转换解析为为Bean对象,而JSON数组不方便转换为Bean对象。

4.云服务器上的mysql不允许连接

==问题提示:==mysql不允许链接

==解决办法:==

  1. 云服务器防火墙开通3306
  2. mysql的root用户权限默认本地登录访问。改为远程登录访问。
  3. mysql配置的bind-address改为 0.0.0.0

5.云服务器上Nacos后端无法连接

==问题提示:==NacosException: Client not connected, current status:STARTING

==解决办法:==nacos需要开放三个端口8848、9848、9849。

6.IDEA中java代码打包问题

==问题提示:==java打包后只有.jar文件。没有.jar.original文件。且打包后的文件内容格式混乱,打开后不是org/META_INF/BOOT_INF三个文件夹。

==解决办法:==

修改pom.xml文件将spring-boot-maven-plugin插件配置好。配置主类加executions标签、去掉skip标签。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!--     war包打包插件       -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!--jar包打包插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.wzy.wzyapiinterface.WzyapiInterfaceApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>

7.上线错误缺失类com.google.protobuf.Message

==问题提示==:缺失类com.google.protobuf.Message(缺失protobuf-java的依赖)

==解决办法:==安装依赖包protobuf-java,重新打包。

8、上线报错ConnectTimeoutException

==问题提示==:网关报错io.netty.channel.ConnectTimeoutException: connection timed out: /111.231.72.191:8123

==解决办法==:网关请求不到此端口。云服务器防火墙开放端口8123

9、SpringBoot读取依赖模块中application.yml配置失效问题

==问题提示==:A项目依赖B.jar包,其中B.jar包装包含配置文件application.yaml,同时A项目中也包含配置文件application.yaml。运行A项目报错 IllegalArgumentException: Could not resolve placeholder 配置的属性。https://blog.lonelyman.site/archives/36

==解决办法==:springboot 如果自身有application.yml,就会覆盖依赖模块的同名配置文件。由于在client-service模块创建了application.yml,导致common模块的application.yml被覆盖。所以将配置转移到依赖模块中或者重命名配置文件名。

10.多租户下,租户切换用户权限校验问题

如果切换租户时,进行了手动权限校验,就会导致报错。这是因为需要校验的是原租户的用户权限,而不是切换后租户用户的权限。

Maven

1.IDEA_NoSuchMethodError: DefaultModelValidator: method <init>()V not found

==问题提示==:NoSuchMethodError: DefaultModelValidator: method ()V not found at CustomModelValidator

==解决办法==:是由于Maven版本过高,IDEA不兼容导致的。

注意:针对一些老项目 还是尽量采用 3.6.3版本,针对idea各个版本的兼容性就很兼容
0.IDEA 2022 兼容maven 3.8.1及之前的所用版本
1.IDEA 2021 兼容maven 3.8.1及之前的所用版本
2.IDEA 2020 兼容Maven 3.6.3及之前所有版本
3.IDEA 2018 兼容Maven3.6.1及之前所有版本


RabbitMQ

1、配置RabbitMQ导致循环依赖问题

==问题提示==:RabbitmqConfig->依赖->RabbitTemplate->依赖->RabbitTemplateConfigurer->依赖->MessageConverter。而自定义的MessageConverter组件放在了RabbitmqConfig就会导致循环依赖!!!

==解决办法==:将MessageConverter抽取出来新建一个配置类。

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class MessageConverterConfig {

/**
* 消息转换器。默认消息只能传输字符串
* @return
*/
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}

2、云服务器部署连接不上

==问题提示==:springboot连接rabbitmq报错:Failed to check/redeclare auto-delete queue(s)

==解决办法==:这是因为spring boot程序无法连接到rabbitmq,如果端口开放了,用户密码正确了,就使用面板localhost:15672检查用户权限开启用户的权限。


IDEA

1.一个项目启动多个实例

==问题提示:==允许多个实例运行后,直接修改原配置文件。导致原java进程也改变了服务端口,原java进程是基于target文件夹未压缩的class文件运行的。

==解决办法:==

  1. 设置允许多实例运行。

image-20240204233858018

  1. 在service窗口复制配置。

image-20240204233957103

  1. 在环境变量修改服务端口号和其它使用到的端口号。

image-20240204234148489

  1. 运行该配置。

2.xml文件未引入spring boot项目

==问题提示:==spring boot项目下编写xml文件到resources目录提示Application context not configured for this file

image-20240205091824617

==解决办法:==原因是idea识别到xml文件未引入项目。需要在spring boot启动类上加注解@ImportResource({"classpath:dubbo-consumer.xml"})用于引入在.xml文件中定义的beans。

跨域配置方案

1.微服务跨域配置

参考博客:https://blog.csdn.net/leijie0322/article/details/127415396

https://www.cnblogs.com/cndarren/p/17265441.html

方案一:使用 Spring MVC 提供的 WebMvcConfigurer 提供的跨域解决方案。这时会在DispatcherServlet的拦截器CorsInterceptor中校验请求并设置响应的响应头。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
public class CorsConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
// 覆盖所有请求
registry.addMapping("/**")
// 允许发送 Cookie
.allowCredentials(true)
// 放行哪些域名(必须用 patterns,否则 * 会和 allowCredentials 冲突)
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.exposedHeaders("*");
}
}

方案二:使用 Servlet Filter 支持的Spring 提供的CorsFilter跨域解决方案。这时在过滤器层面就解决了跨域设置了响应头。(推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Configuration
public class MyCorsFilter {

/**
* cors跨域处理过滤器
* 优先级最高
*/
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOriginPattern(CorsConfiguration.ALL);
corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);
corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
corsConfiguration.addExposedHeader(CorsConfiguration.ALL);

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**",corsConfiguration);
return createFilterRegistrationBean(new CorsFilter(source),CORS_FILTER);
}

public static <T extends Filter> FilterRegistrationBean<T> createFilterRegistrationBean(T filter, int order) {
FilterRegistrationBean<T> registrationBean = new FilterRegistrationBean<>(filter);
registrationBean.setOrder(order);
return registrationBean;
}
}

2.gateway网关跨域配置

注意:网关要使用 lb://微服务名 一定要添加loadbalance依赖。

方案一:直接通过application.yaml文件进行配置(推荐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
spring:
cloud:
gateway:
# 解决双重跨域
default-filters:
- DedupeResponseHeader=Vary Access-Control-Allow-Origin Access-Control-Allow-Headers Access-Control-Allow-Credentials,RETAIN_UNIQUE
globalcors:
# 解决options请求被拦截问题
add-to-simple-url-handler-mapping: true
# 全局的跨域配置
cors-configurations:
# 拦截的请求
'[/**]':
allowedOriginPatterns: "*"
# 允许请求中携带的头信息
allowedHeaders: "*"
# 运行跨域的请求方式
allowedMethods: "*"
# 是否允许携带cookie
allowCredentials: true
# 跨域检测的有效期,单位s
maxAge: 36000

如果**在 Spring Cloud 网关处配置跨域处理,则需要注入 CorsWebFilter**,这是因为 Spring Cloud Gateway 是 WebFlux 的,并不采用 Servlet 体系。

方案二:使用 Spring 提供的 CorsWebFilter 实现gateway跨域问题解决。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Configuration
public class MyCorsConfiguration {

@Bean
public CorsWebFilter corsWebFilter(){
//1.配置跨域
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 1.1这里仅为了说明问题,配置为放行所有域名,生产环境请对此进行修改
corsConfiguration.addAllowedOriginPattern(CorsConfiguration.ALL);//坑
// 1.2放行的请求头
corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
// 暴露头部信息
corsConfiguration.addExposedHeader(CorsConfiguration.ALL);
// 1.3放行的请求方式,主要有:GET, POST, PUT, DELETE, OPTIONS
corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);
// 1.4是否发送cookie
corsConfiguration.setAllowCredentials(true);

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**",corsConfiguration);

return new CorsWebFilter(source);
}
}

最近遇到的数据库被勒索😈😈😈

image-20240214110013598

笑嘻嘻,建议大家数据库密码还是要设置复制一些

永久修改CMD窗口编码:https://learnku.com/articles/55553

image-20240401151813867

https://blog.csdn.net/ccboy2009/article/details/127142652