没有找到对应controller的RequestMapping;
解决(前后端分离版):
①在父项目中的pom.xml添加对应的模块
②在子模块ruoyi-admin中的pom.xml,添加对应模块的
③(※重要)将父项目的pom.xml,子模块admin的pom.xml,新建的子模块的pom.xml,分别右键->maven->Reload Project,然后整个项目 Rebuild Project,期间先关闭服务再操作,若仍然404,可关闭并重新打开开发工具,重新操作一遍该步骤。
解决(微服务版):
①保证modules的pom.xml添加了新建的子模块依赖
② 在限流策略里面添加新增模块配置(可直接复制system的,记得改resource):
③在网关配置里添加新模块的路由配置(可直接复制system的,记得改名称):
若仍然有问题,继续看下面:
④在vue的新模块api.js里,前缀与第③步前缀不一致,可以改成一致,也可以在api.js里增加前缀,但是保证整个url能与controller的@RequestMapping对应(注意:第③步网关配置的filters -StripPrefix=1,会过滤第一个字符串,即图中的'/xiaoya',到后台请求url,则不会再有'/xiaoya',参考下方api.js、controller),
解决(前后端分离版):去掉在:SecurityConfig.java 自定义的 .antMatchers("/test/**").anonymous(), 若依前端访问不是匿名,带有token,所以不使用anonymous(),默认的 authenticated 即可。
准备将生成的*Mapper.xml放入至其他子模块试一下,发现文件名不对
解决: 这里的mapper.family,是一个文件名,family并不是一个子文件夹,将文件名修改好就行了。
原因:新建模块直接复制了system的pom文件,里面使用了多数据源,而新建的模块里面不需要使用多数据源,或者没有用到多数据源,导致的这个问题。
解决:要么使用多数据源,要么删除依赖
删除依赖:ruoyi-common-datasource(而这个依赖引用的是common模块内的dynamic-datasource-spring-boot-starter依赖)
原因:nacos2.0版本,新增了gRPC 的通信方式(用于客户端向服务端发起连接请求),新增了两个端口。这两个端口在nacos原先的端口上(默认8848),进行一定偏移量自动生成;
客户端向服务端发起连接请求失败:
服务端:端口是否开放问题; 本地:几个服务同时启动,导致等待时间超过3秒
解决:
【服务端】:①防火墙增加端口开放: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:如何修改源码:找到该源码的全路径,在自己项目路径下新建一个相同全路径的类,将源码粘贴至新建的类中,然后在该类中对相应代码进行正确修改即可,需要注意的一个问题,后面版本升级时需要注意该类的升级(本地类的加载,优先于依赖引入))
Description:
Field *Mapper in com.*.*.service.impl.*ServiceImpl required a bean of type 'com.*.*.mapper.*Mapper' that could not be found.
原因:无法扫描到Mapper文件
解决:在com.ruoyi.common.security.annotation.EnableCustomConfig 接口中,
修改扫描注解:
@MapperScan({"com.ruoyi.**.mapper", "com.你的com名.**.mapper"})
或增加:
@MapperScan("com.你的com名.**.mapper")
原因:在*Mapper.xml里面,无法扫描到自定义类型的类所在包(没有配置实体类包扫描)
解决:
①将type类型,实体类指定具体的包名;
...
包括Mapper.xml内,所有的自定义实体类型,包括 parameterType,都需要加上包名;
②修改设置Mybatis>typeAliasesPackage: com.你的com.**.domain(你的模块下的.yml文件,微服务在nacos里修改)
是由于权限控制,必须登录获取当前用户信息所致:@PreAuthorize("@ss.hasPermi('test:test:list')")
解决:若不需要登录就能访问,可以直接注释这个权限。
原因:新增的子模块,子模块内的bean无法被ruoyi-job加载到
解决(微服务版):
①可直接在ruoyi-job模块内,在task包下,增加自定义定时任务类,增加 @Component 或 @Service,将类加载bean即可(参考RyTask.java)(否则需要在启动类里面指定加载注入bean);
②将Bean调用方式改成Class类调用:完整包名.类名.方法名()(有参则加括号,无参可加括号可不加)(注意:新增的模块,需要引入到ruoyi-job模块中,不然无法被加载上)
原因:若依框架在Contants里面设置了定时任务包名前缀的白名单数组:JOB_WHITELIST_STR,不在数组内的会被拦截;
解决:找到Constants.java,在常量数组JOB_WHITELIST_STR内增加你新增的子模块包名前缀。
原因:其他模块没有被依赖,spring没有加载bean;
解决(前后端分离版):若需要调用其他模块的service,则需要引入其他模块的依赖,且启动类需要添加scanBasePackages,要扫描Mapper文件需要添加MapperScan;
解决(微服务版):使用Feign调用其他服务接口api的方式:
①添加依赖(核心模块core默认已有)
org.springframework.cloud
spring-cloud-starter-openfeign
②新建RemoteUserService.java
服务接口
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 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
{
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 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
,返回正确数据表示测试通过。
原因:由于接口参数值内容过大/数量过多后,默认使用gzip压缩,然后解码时乱码无法解码导致这个问题;
分析:参数使用List传值,少量条数正常, 大量条数能复现问题;
花了一上午,使用了各种方案,为了各位少走弯路,特意贴出解决办法(②可以解决,但不合适,直接使用第③个解决):
解决方案:
①在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"
后台报错:Content type 'multipart/form-data;boundary=----WebKitFormBoundarymn2IDPynGhlHwALI;charset=UTF-8' not supported;
解决:去掉:@RequestBody,body不会接收file。