若依(ruoyi)框架:如何实现灵活自定义路由配置

Posted 轻狂书生FS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了若依(ruoyi)框架:如何实现灵活自定义路由配置相关的知识,希望对你有一定的参考价值。

如何灵活自定义路由配置

业务背景

随着项目的深入开发,我们可能会对路由做特殊化处理。比如:访问路由A时需要传入routerType=A,前端会根据routerType=A做一些特殊的处理。

如何实现

方式一:直接在前端路由表(router/index.js)里面某个路由的meta属性里面配置。

这种方法可用于公共路由或固定路由中,而现实开发过程中我们经常遇到的对某个菜单路由的做特殊化处理。还有经常遇到对动态路由的特殊化处理。所以就需要第二种方式。

方式二:在后台返回动态路由的接口中组装meta信息

在若依框架中,获取路由信息接口 /getRouters 中是对存在sys_menu表里的菜单数据进行拼装。

如何改造

步骤:

  1. 在sys_menu表中增加一个属性 meta
  2. RouterVo 类中的 private MetaVo meta 改为 private Map<String,Object> meta
  3. 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;  

  1. 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

ruoyi能支持多大并发

若依权限模块探究

若依权限模块探究

若依(RuoYi)SpringBoot框架密码加密传输(前后分离板)

若依权限模块探究