若依(ruoyi)框架:如何实现灵活自定义路由配置
Posted 轻狂书生FS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了若依(ruoyi)框架:如何实现灵活自定义路由配置相关的知识,希望对你有一定的参考价值。
如何灵活自定义路由配置
业务背景
随着项目的深入开发,我们可能会对路由做特殊化处理。比如:访问路由A时需要传入routerType=A,前端会根据routerType=A做一些特殊的处理。
如何实现
方式一:直接在前端路由表(router/index.js)里面某个路由的meta属性里面配置。
这种方法可用于公共路由或固定路由中,而现实开发过程中我们经常遇到的对某个菜单路由的做特殊化处理。还有经常遇到对动态路由的特殊化处理。所以就需要第二种方式。
方式二:在后台返回动态路由的接口中组装meta信息
在若依框架中,获取路由信息接口 /getRouters
中是对存在sys_menu表里的菜单数据进行拼装。
如何改造
步骤:
- 在sys_menu表中增加一个属性
meta
。 - 将
RouterVo
类中的private MetaVo meta
改为private Map<String,Object> meta
- 在
SysMenuServiceImpl
类里增加assembleMeta
方法。
/**
* 装配路由的Meta信息
*
* @param menu 菜单
* @return Map类型
*/
public Map<String,Object> assembleMeta(SysMenu menu)
Map<String,Object> meta = new HashMap<>();
if (StringUtils.isNotEmpty(menu.getMenuName()))
meta.put("title",menu.getMenuName());
if (StringUtils.isNotEmpty(menu.getIcon()))
meta.put("icon",menu.getIcon());
if (StringUtils.isNotEmpty(menu.getIsCache()))
meta.put("noCache",StringUtils.equals("1", menu.getIsCache()));
if (StringUtils.isNotEmpty(menu.getPath()))
meta.put("link",menu.getPath());
//往路由里面添加扩展元数据
if (StringUtils.isNotEmpty(menu.getMeta()))
try
Map<String,Object> metaInfo = (Map<String,Object>)JSONObject.parse(menu.getMeta());
meta.putAll (metaInfo);
catch (Exception e)
log.error("元数据JSON数据转换异常", e.getMessage());
return meta;
- 将
SysMenuServiceImpl
类里的buildMenus
方法中setMeta(new MetaVo(menu...))
改为setMeta(assembleMeta(menu))
。
效果展示
使用方法
router.beforeEach((to, from) =>
// 而不是去检查每条路由记录
if (to.meta.routerType === 'A')
console.log("做一些特殊的处理.....")
return
path: '/login',
// 保存我们所在的位置,以便以后再来
query: redirect: to.fullPath ,
)
总结
以上只是在实际开发过程中,根据实际需要做个一下改造,个性化比较强。你也可以在你的项目中做适合自己项目的改造。
RuoYi(若依开源框架)-前后台分离版-后端流程简单分析
RuoYi(若依开源框架)-前后台分离-后端流程简单分析
【项目结构】
├── common // 工具类
│ └── annotation // 自定义注解
│ └── config // 全局配置
│ └── constant // 通用常量
│ └── core // 核心控制
│ └── enums // 通用枚举
│ └── exception // 通用异常
│ └── filter // 过滤器处理
│ └── utils // 通用类处理
├── framework // 框架核心
│ └── aspectj // 注解实现
│ └── config // 系统配置
│ └── datasource // 数据权限
│ └── interceptor // 拦截器
│ └── manager // 异步处理
│ └── security // 权限控制
│ └── web // 前端控制
├── ruoyi-generator // 代码生成(可移除)
├── ruoyi-quartz // 定时任务(可移除)
├── ruoyi-system // 系统代码
├── ruoyi-admin // 后台服务
├── ruoyi-xxxxxx // 其他模块
-登录请求过程
前端发起请求:http://127.0.0.1:8080/login
防止重复提交拦截器捕获
【------------ruoyi-framework\\src\\main\\java\\com\\ruoyi\\framework\\interceptor\\RepeatSubmitInterceptor.java------------------】
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{
if (handler instanceof HandlerMethod)
{
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
if (annotation != null)
{
if (this.isRepeatSubmit(request))
{
AjaxResult ajaxResult = AjaxResult.error("不允许重复提交,请稍后再试");
ServletUtils.renderString(response, JSONObject.toJSONString(ajaxResult));
return false;
}
}
return true;
}
else
{
return super.preHandle(request, response, handler);
}
}
【1】请求先进入过滤器,符合要求放行,不符合放行一个空请求
【-------------------ruoyi-common\\src\\main\\java\\com\\ruoyi\\common\\filter\\RepeatableFilter.java-----------------------】
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest
&& StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
{
requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
}
if (null == requestWrapper)
{
chain.doFilter(request, response);
}
else
{
chain.doFilter(requestWrapper, response);
}
}
【2】安全机制捕获
【-------------------ruoyi-framework\\src\\main\\java\\com\\ruoyi\\framework\\config\\SecurityConfig.java-----------------------】
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception
{
httpSecurity
// CSRF禁用,因为不使用session
.csrf().disable()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
// 对于登录login 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/captchaImage").anonymous()
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/profile/**"
).permitAll()
.antMatchers("/common/download**").anonymous()
.antMatchers("/common/download/resource**").anonymous()
.antMatchers("/swagger-ui.html").anonymous()
.antMatchers("/swagger-resources/**").anonymous()
.antMatchers("/webjars/**").anonymous()
.antMatchers("/*/api-docs").anonymous()
.antMatchers("/druid/**").anonymous()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()
.headers().frameOptions().disable();
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
// 添加JWT filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// 添加CORS filter
httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
}
【3】SysLoginController的post方法login获取到请求,并调用login()方法进行登录验证
【-------------------ruoyi-admin\\src\\main\\java\\com\\ruoyi\\web\\controller\\system\\SysLoginController.java-----------------------】
@Autowired
private SysLoginService loginService;
/**
* 登录方法
*
* @param loginBody 登录信息
* @return 结果
*/
@PostMapping("/login")
public AjaxResult login(@RequestBody LoginBody loginBody)
{
System.out.println("This is login!");
AjaxResult ajax = AjaxResult.success();
// 生成令牌
String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
loginBody.getUuid());
ajax.put(Constants.TOKEN, token);
return ajax;
}
@PostMapping是一个组合注解,是@RequestMapping(method=RequestMethod.POST)的缩写。
@GetMapping、@PutMapping、@PatchMapping和@DeleteMapping,与@PostMapping实现类似
【4】SysLoginServicer对请求发来的信息进行验证,以此调用mapper映射接口完成持久层操作
【5】完成后向前端返回AjaxResult ajax信息
springboot security 安全机制
认证流程:
1、由认证配置WebSecurityConfigurerAdapter的configure(HttpSecurity http)方法进入,添加拦截器addFilterBefore
2、进入拦截器AbstractAuthenticationProcessingFilter的attemptAuthentication方法,指定认证对象AbstractAuthenticationToken
3、进入认证逻辑AuthenticationProvider,根据supports的断定对认证的目标对象指定对哪个拦截器进行认证,进入具体的认证逻辑方法authenticate
4、认证结果:认证成功后进入拦截器的successfulAuthentication方法;认证失败后进入拦截器的unsuccessfulAuthentication方法
5、对认证结果进行处理
a.认证成功的逻辑:进入SimpleUrlAuthenticationSuccessHandler的onAuthenticationSuccess方法
b.认证失败的逻辑:进入SimpleUrlAuthenticationFailureHandler的onAuthenticationFailure方法
6、返回结果给页面,将数据封装在ObjectMapper对象中,将会以文本形式返回给客户端(页面)
以上是关于若依(ruoyi)框架:如何实现灵活自定义路由配置的主要内容,如果未能解决你的问题,请参考以下文章
若依RuoYi框架浅析 部署篇②——CentOS 8 配置MySQL 8.0