一、项目启动相关问题
1、项目启动一直卡在Initializing Spring embedded WebApplicationContext
1.1 分析
项目启动不报错,一直卡着不动;若是无缘无故出现,可能是断点断到方法上了;
1.2 原因
方法断点会降低调试器的速度,方法断点的使用成本很高尽量不要用;
1.3 解决
取消方法断点,或者直接把所有断点设为失效,不使用方法断点,可直接断点方法内代码。
2、错误: 找不到或无法加载主类 com.ruoyi.*Application
2.1 分析
移动了启动类的位置,class里没有重新编译;
2.2 解决
使用maven clean,清理一下,maven test测试成功即可;也可直接删除target目录,build -> rebuild project重新生成target即可。
3、(前后端分离版)启动成功后报错:dynamic-datasource can not find primary datasource
3.1 报错
com.baomidou.dynamic.datasource.exception.CannotFindDataSourceException: dynamic-datasource can not find primary datasource
3.2 分析
在pom.xml里面引入了动态数据源,可能没有直接引入:dynamic-datasource-spring-boot-starter,在pom.xml引入了ruoyi-common-datasource,而这个pom中引入了dynamic-datasource-spring-boot-starter;引入了没有使用,没有指定primary,则报出警告。
3.3 解决
1、如果要使用动态数据源,在yml文件中配置dynamic节点,具体可参考ruoyi-system.yml,下面简单举个例子:
spring:
application:
name: test
datasource:
dynamic:
primary: master
strict: true
datasource:
master:
url: xxxxx
username: xxx
password: xxx
2、若不需要使用动态数据源,在pom.xml中删除坐标引入即可。
4、(微服务版)启动成功后报错:dynamic-datasource can not find primary datasource
4.1 报错
error: com.baomidou.dynamic.datasource.exception.CannotfindDataSourceException: dynamic-datasource can not find primary datasource.
4.2 原因
后端代码里引入了动态数据源的Jar包,且代码中使用了动态数据源,而找不到对应yml配置的动态数据源
4.3 解决
1、检查bootstrap.yml中应用名称,对应在nacos中相同名称的.yml配置文件,找到dynamic > datasource > master,看是否正确配置了master主数据源;
2、如果上一步配置正确,且报错无任何变化,检查Nacos的命名空间,是否与当前项目的pom.xml的命名空间一致,且pom.xml中Nacos服务地址要保持一致(例如:本地nacos地址127.0.0.1:8848,命名空间为test,则pom.xml对应的<nacos.server.address>地址就是127.0.0.1:8848;<nacos.server.namespace>就是test),不然无法访问Nacos对应的命名空间,就会报错无法找到动态数据源配置。
5、java -jar启动jar包报错:YAMLException: java.nio.charset.MalformedInputException: Input length = 1
5.1 报错
YAMLException: java.nio.charset.MalformedInputException: Input length = 1
5.2 分析
编码问题
5.3 解决
加上编码设置:-Dfile.encoding=UTF-8
java -Dfile.encoding=UTF-8 -jar springboot.jar
6、java -jar启动报错:Consider defining a bean of type ‘springfox.documentation.schema.TypeNameExtractor’ in your configuration.
6.1 报错
Consider defining a bean of type ‘springfox.documentation.schema.TypeNameExtractor’ in your configuration.
6.2 分析
knife4j报错
6.3 解决
注释掉yaml里面的knife4j相关配置即可,如下:
7、启动报错:No enum constant org.springframework.web.bind.annotation.Request.*
7.1 报错
No enum constant org.springframework.web.bind.annotation.Request.UPDATE
7.2 分析
整合swagger出现,由于注解写错,不识别导致;
目前接受的类型:"GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS" and "PATCH"
7.3 解决
全局搜索一下项目内,httpMethod = "UPDATE",根据你报错的注解搜,例如 httpMethod = "Get",小写Get不识别,改成大写即可。
二、新建子模块相关问题
1、接口报404或Whitelabel Error Page(也是404)
1.1 报错
没有找到对应controller的RequestMapping;
1.2 解决(前后端分离版)
①在父项目中的pom.xml添加对应的模块<modules>和<dependency>,参考ruoyi-generator;
②在子模块ruoyi-admin中的pom.xml,添加对应模块的<dependency>,参考ruoyi-generator;
③(※重要)将父项目的pom.xml,子模块admin的pom.xml,新建的子模块的pom.xml,分别右键->maven->Reload Project,然后整个项目 Rebuild Project,期间先关闭服务再操作,若仍然404,可关闭并重新打开开发工具,重新操作一遍该步骤。
1.3 解决(微服务版)
①保证modules的pom.xml添加了新建的子模块依赖
② 在限流策略里面添加新增模块配置(可直接复制system的,记得改resource):
③在网关配置里添加新模块的路由配置(可直接复制system的,记得改名称):
若仍然有问题,继续看下面:
④在vue的新模块api.js里,前缀与第③步前缀不一致,可以改成一致,也可以在api.js里增加前缀,但是保证整个url能与controller的@RequestMapping对应(注意:第③步网关配置的filters -StripPrefix=1,会过滤第一个字符串,即图中的'/xiaoya',到后台请求url,则不会再有'/xiaoya',参考下方api.js、controller),
若再有问题,请检查你的路径:前端访问路径 和 接口路径 是不是一样的(大小写等等情况)
2、接口访问报403错误(权限问题),只调postman调用/浏览器直接调用无问题,前端调用403错误
2.1 解决(前后端分离版)
去掉在:SecurityConfig.java 自定义的 .antMatchers("/test/**").anonymous(), 若依前端访问不是匿名,带有token,所以不使用anonymous(),默认的 authenticated 即可。
3、*Mapper.xml扫描不到(Invalid bound statement (not found))
3.1 分析
Invalid bound statement (not found): com.xxx.xxx.mapper.xxxMapper.selectList
准备将生成的*Mapper.xml放入至其他子模块试一下,发现文件名不对
这里没有合并,就看出问题来了 ,文件名称有问题
3.2 解决
这里的mapper.family,是一个文件名,family并不是一个子文件夹,将文件名修改好就行了。
4、启动后报错:dynamic-datasource can not find primary datasource
4.1 原因
新建模块直接复制了system的pom文件,里面使用了多数据源,而新建的模块里面不需要使用多数据源,或者没有用到多数据源,导致的这个问题。
4.2 解决
要么使用多数据源,要么删除依赖
删除依赖:ruoyi-common-datasource(而这个依赖引用的是common模块内的dynamic-datasource-spring-boot-starter依赖)
5、启动后报错(但是不影响启动):Server check fail, please check server 127.0.0.1 ,port 9848 is available
5.1 原因
nacos2.0版本,新增了gRPC 的通信方式(用于客户端向服务端发起连接请求),新增了两个端口。这两个端口在nacos原先的端口上(默认8848),进行一定偏移量自动生成;
客户端向服务端发起连接请求失败:
服务端:端口是否开放问题; 本地:几个服务同时启动,导致等待时间超过3秒
5.2 解决
【服务端】
①防火墙增加端口开放:8848、9848、9849;②服务器上启动的时候加上这句 -p 8848:8848 -p 9848:9848 -p 9849:9849 --privileged=true
【本地】:
1>直接忽略
8848是nacos默认端口,当应用类启动,会默认连接这个端口。如同一时间,多个应用同时启动,连接这个端口,服务器会卡,连接3秒超时后,连接失败的应用会尝试访问新端口9848,如果依然不行,会再去访问8848端口,反复连上后,就不会再报错了,也就启动成功了。
2>处女座请看这里
把GrpcClient.class源码弄下来,将超时时间改长即可,3秒可改成30秒:
(PS:如何修改源码:找到该源码的全路径,在自己项目路径下新建一个相同全路径的类,将源码粘贴至新建的类中,然后在该类中对相应代码进行正确修改即可,需要注意的一个问题,后面版本升级时需要注意该类的升级(本地类的加载,优先于依赖引入))
6、启动后报错:APPLICATION FAILED TO START
6.1 报错
Field *Mapper in com.*.*.service.impl.*ServiceImpl required a bean of type 'com.*.*.mapper.*Mapper' that could not be found.
6.2 原因
无法扫描到Mapper文件;一般是由于改了包名称引起,改了名称后,仍然是扫描原来所在的目录,所以无法扫描到Mapper文件,所以要将新的地址交给Spring扫描。
6.3 解决
在com.ruoyi.common.security.annotation.EnableCustomConfig 接口中(由于改了包名,所以直接文件搜索 EnableCustomConfig.java 即可),修改扫描注解:
@MapperScan({"com.ruoyi.**.mapper", "com.你的新包名.**.mapper"}) 或增加: @MapperScan("com.你的新包名.**.mapper")
7、启动后报错:Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
7.1 报错
APPLICATION FAILED TO START:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
7.2 原因
没有配置数据源。
7.3 解决
SpringBoot:
①检查是否启动了nacos、redis;
②检查nacos里是否正确配置了该子模块的名称,端口号别和其他模块冲突了:
③检查该子模块的pom.xml里是否引入了数据源的坐标:
8、启动后报错:Error parsing Mapper XML. The XML location is 'file [E:*\RuoYi-Cloud\ruoyi-modules\*\target\classes\mapper\*\*Mapper.xml]'.Could not resolve type alias '*'. Cause: java.lang.ClassNotFoundException: Cannot find class: *
8.1 原因
在*Mapper.xml里面,无法扫描到自定义类型的类所在包(没有配置实体类包扫描)。
8.2 解决
①将type类型,实体类指定具体的包名;
<resultMap type="com.你的com.domain.你的实体类" id="">...
包括Mapper.xml内,所有的自定义实体类型,包括 parameterType,都需要加上包名;
②修改设置Mybatis>typeAliasesPackage: com.你的com.**.domain(你的模块下的.yml文件,微服务在nacos里修改)
9、启动后报错:Field *Mapper in com.nview.*.service.impl.*ServiceImpl required a bean of type 'com.nview.*.mapper.*Mapper' that could not be found.
9.1 报错
Description:
Field *Mapper in com.nview.*.service.impl.*ServiceImpl required a bean of type 'com.nview.*.mapper.*Mapper' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.nview.*.mapper.*Mapper' in your configuration.
9.2 原因
由于未扫描到指定的Mapper导致,检查配置包扫描路径。
9.3 解决
①找到启动类,注解:@EnableCustomConfig,点击进入:
②修改Mapper包扫描路径:
三、权限相关问题
1、获取用户信息异常
是由于权限控制,必须登录获取当前用户信息所致:@PreAuthorize("@ss.hasPermi('test:test:list')")
1.1 解决
若不需要登录就能访问,可以直接注释这个权限。
四、任务调度(定时任务)相关问题
1、自定义定时任务的bean无法访问:No bean named '*********Task' available
1.1 原因
新增的子模块,子模块内的bean无法被ruoyi-job加载到。
1.2 解决(微服务版)
①可直接在ruoyi-job模块内,在task包下,增加自定义定时任务类,增加 @Component 或 @Service,将类加载bean即可(参考RyTask.java)(否则需要在启动类里面指定加载注入bean);
②将Bean调用方式改成Class类调用:完整包名.类名.方法名()(有参则加括号,无参可加括号可不加)(注意:新增的模块,需要引入到ruoyi-job模块中,不然无法被加载上)
2、新增/修改定时任务时,提示:新增/修改任务'*****'失败,目标字符串不在白名单内
2.1 原因
若依框架在Contants里面设置了定时任务包名前缀的白名单数组:JOB_WHITELIST_STR,不在数组内的会被拦截;
2.2 解决
找到Constants.java,在常量数组JOB_WHITELIST_STR内增加你新增的子模块包名前缀。
3、定时任务里面调用其他模块的service,使用@Autowire自动注入,注入对象为null,调用里面的方法报错:空指针异常java.lang.NullPointerException,使用SpringUtils.getBean()也无法获取bean
3.1 原因
其他模块没有被依赖,spring没有加载bean;
3.2 解决:(前后端分离版)
若需要调用其他模块的service,则需要引入其他模块的依赖,且启动类需要添加scanBasePackages,要扫描Mapper文件需要添加MapperScan;
3.3 解决:(微服务版)
使用Feign调用其他服务接口api的方式:
①添加依赖(核心模块core默认已有)
<!-- spring cloud openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
②新建RemoteUserService.java
服务接口
注意:@FeignClient的value值,对应被调用方的应用名称
(bootstrap.yml的spring:application:name)
package com.ruoyi.system.api;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.factory.RemoteUserFallbackFactory;
import com.ruoyi.system.api.model.LoginUser;
/**
* 用户服务
*
* @author ruoyi
*/
@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteUserService
{
/**
* 通过用户名查询用户信息
*
* @param username 用户名
* @return 结果
*/
@GetMapping(value = "/user/info/{username}")
public R<LoginUser> getUserInfo(@PathVariable("username") String username);
}
③新建RemoteUserFallbackFactory.java
降级实现
package com.ruoyi.system.api.factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.model.LoginUser;
import feign.hystrix.FallbackFactory;
/**
* 用户服务降级处理
*
* @author ruoyi
*/
@Component
public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserService>
{
private static final Logger log = LoggerFactory.getLogger(RemoteUserFallbackFactory.class);
@Override
public RemoteUserService create(Throwable throwable)
{
log.error("用户服务调用失败:{}", throwable.getMessage());
return new RemoteUserService()
{
@Override
public R<LoginUser> getUserInfo(String username)
{
return R.fail("获取用户失败:" + throwable.getMessage());
}
};
}
}
④消费者TestUserController.java
新增info
查询用户方法
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestUserController
{
@Autowired
private RemoteUserService remoteUserService;
/**
* 获取当前用户信息
*/
@GetMapping("/user/{username}")
public Object info(@PathVariable("username") String username)
{
return remoteUserService.getUserInfo(username);
}
}
⑤启动类添加@EnableRyFeignClients
注解,默认的@EnableRyFeignClients
扫描范围com.ruoyi(其他不在此目录下,在EnableRyFeignClients.java里修改)
。
⑥启动后访问http://localhost:8888/user/admin
,返回正确数据表示测试通过。
五、前后端接口访问问题(api/controller访问问题)
1、Feign使用@RequestBody传值报错:com.ruoyi.common.core.exception.ServiceException: JSON parse error: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens; nested exception is com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens
at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 2]
1.1 原因
由于接口参数值内容过大/数量过多后,默认使用gzip压缩,然后解码时乱码无法解码导致这个问题;
1.2 分析
参数使用List传值,少量条数正常, 大量条数能复现问题;
花了一上午,使用了各种方案,为了各位少走弯路,特意贴出解决办法(②可以解决,但不合适,直接使用第③个解决):
1.3 解决
过程:
①在application-dev.yml中设置feign.compression.response.useGzipDecoder=true(设置Gzip解码方式,feign 2.2.x版本之后 默认已经支持 gzip解码了)
②在application-dev.yml中设置feign.compression.request.min-request-size=10240(size要大到过滤掉你的数据大小,原理:设置压缩数据大小的下限,传输数据大小低于这个值则不会压缩)
③分析过程:将List改为String类型接收后,能看出控制台日志是乱码导致无法解码:
controller:
console:
解决方案:在feign配置api接口中,post接口设置消费者类型:
consumes = "application/json;charset=UTF-8"
2、微服务api调用其他服务报错:没有访问权限,请联系管理员授权
2.1 原因
由于Mapping不一致导致无权限;
2.2 解决
检查Feign接口内方法Mapper类型和Controller方法上的Mapper类型是否一致。
3、Feign服务间调用接口报404/本地没问题,部署后报404
3.1 问题
{"msg":"[404] during [GET] to [http://***/****] [RemoteTestService#getList(String)]: [{\"timestamp\":\"2024-12-05T10:47:45.444+08:00\",\"status\":404,\"error\":\"Not Found\",\"path\":\"/testAPI/getList\"}]","code":500}
3.2 原因
当前服务调用其他服务的接口,feign的客户端@FeignClient中的方法,在目标服务(提供端)不存在,即Mapping的路径无法找到对应的方法,检查方法是否定义;如果是本地没问题,部署后报404,则是目标服务没有部署该方法。
3.3 解决
检查提供端服务对应的方法是否存在;部署后出现问题,则直接用api测试工具调用目标接口,调不通/404,则表示提供端的服务没有正确部署该方法。
4、前后端传值,对象里包含对象,请求报错:Property referenced in indexed property path 'readRecord[userId]' is neither an array nor a List nor a Map.
4.1 问题重现
4.1.1 前端:参数对象
4.1.2 后端:实体、控制器
4.2 报错
Property referenced in indexed property path 'readRecord[userId]' is neither an array nor a List nor a Map.
4.3 解决
修改前端:传值方式修改成(内部对象改为字符串方式):
方法①
或
方法②
5、knife4j接口文档没有排序,设置@ApiOperationSupport(order = 1)不生效
5.1 问题
对应版本:knife4j v2.0.4,接口方法增加了@ApiOperationSupport(order = 1),仍然不排序
5.2 原因
没有开启增强模式
5.3 解决
在application-dev.yml 和 自己相应模块的yaml里增加配置:
knife4j:
# 开启增强配置
enable: true
# 开启生产环境屏蔽 production: true时就访问不了swagger了
production: false
5.4 示例
6、使用Docker部署后,验证码无法出来,接口报错:内部服务器错误
6.1 问题
本地环境正常,部署在服务器上,就不出来验证码,而且还报错:
6.2 原因
本地使用的是jdk8,服务器使用的是openjdk
6.3 解决
①服务器将openjdk卸载掉,重新安装oracle jdk8
②(临时解决)直接先关闭验证码,先能进系统再说:
打开nacos,找到服务器上的csuxy-gateway.yml文件,修改:
# 安全配置
security:
# 验证码
captcha:
enabled: true
type: math
修改为:
# 安全配置
security:
# 验证码
captcha:
enabled: false
type: math
六、前端相关问题
1、下拉框数据回显问题
1.1 问题
自定义的下拉框数据集,点击修改时,数据回显仍然是ID,不是想要的label
1.2 原因
自定义的id,在获取数据时,被当做字符串类型了,所以没法回显。
1.3 解决
在获取数据时,将该ID字段,转成数字类型(直接*1,js为弱语法,会自动转成数字类型)。
七、CRUD问题
1、保存/修改报错:updating database. Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
1.1 问题
### Error updating database. Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
1.2 原因
在保存/更新时,判断为空时,涉及到日期判断,误将日期与字符串判断,两种类型不符,故报错;
例如:
<if test="startDate != null and startDate != ''">
1.3 解决
参考上面例子,去除startDate != ''
八、工具类相关问题
1、文件上传下载
1.1 文件上传
后台报错:Content type 'multipart/form-data;boundary=----WebKitFormBoundarymn2IDPynGhlHwALI;charset=UTF-8' not supported;
解决:去掉:@RequestBody,body不会接收file。
2、日志
2.1 SQL日志打印
2.1.1 解决
需要SQL日志打印的模块添加mybatis配置(.yml):
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3、数据字典
3.1 若依接口
文件:data.js
①查询字典数据列表:/system/dict/data/list
②查询字典数据详细:/system/dict/data/{dictCode}
③根据字典类型查询字典数据信息:/system/dict/data/type/{dictType}
3.2 自定义多级数据字典
①方式一:数据字典数据分割方式(前端根据数据值进行分组):
一级数据字典:dict_value:11、12、13
二级数据字典:dict_value:1101、1102、1201、1202、1203、1301
三级数据字典:dict_value:110101、110102、110201
......
②方式二:树表方式(可参考sys_dept部门表树结构)
(1、若不设置children,则前端根据数据parent_id进行分组;2、若设置children,则前端直接可取到树状的data):
create table test (
id bigint(20),
parent_id bigint(20),
name varchar(30)
)