若依框架学习————持续更新

若依框架学习

    • 一、01-登录流程
      • 1、用户发送请求进入到登录页面
      • 2、用户点击登录按钮
    • 二、02-首页

一、01-登录流程

1、用户发送请求进入到登录页面

//SysLoginController.java
@GetMapping("/login")
public String login(HttpServletRequest request, HttpServletResponse response)
{
    // 如果是Ajax请求,返回Json字符串。
    if (ServletUtils.isAjaxRequest(request))
    {
        return ServletUtils.renderString(response, "{\"code\":\"1\",\"msg\":\"未登录或登录超时。请重新登录\"}");
    }

    return "login";
}
  • 对ajax和视图返回进行区分
//ServletUtils.java

/**
 * 是否是Ajax异步请求
 * 
 * @param request
 */
public static boolean isAjaxRequest(HttpServletRequest request)
{
    String accept = request.getHeader("accept");
    if (accept != null && accept.indexOf("application/json") != -1)
    {
        return true;
    }

    String xRequestedWith = request.getHeader("X-Requested-With");
    if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1)
    {
        return true;
    }

    String uri = request.getRequestURI();
    if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
    {
        return true;
    }

    String ajax = request.getParameter("__ajax");
    if (StringUtils.inStringIgnoreCase(ajax, "json", "xml"))
    {
        return true;
    }
    return false;
}
  • 同时页面发送一个验证码请求

    //	SysCaptchaController.java
    
    if ("math".equals(type))
    {
        String capText = captchaProducerMath.createText();
        capStr = capText.substring(0, capText.lastIndexOf("@"));
        code = capText.substring(capText.lastIndexOf("@") + 1);
        bi = captchaProducerMath.createImage(capStr);
    }
    else if ("char".equals(type))
    {
        capStr = code = captchaProducer.createText();
        bi = captchaProducer.createImage(capStr);
    }
    session.setAttribute(Constants.KAPTCHA_SESSION_KEY, code);
    out = response.getOutputStream();
    ImageIO.write(bi, "jpg", out);
    out.flush();
    
    • 若依使用的是谷歌提供的一个验证码生成器com.google.code.kaptcha,可以在配置类中配置验证码生成的参数,最后返回一个ImageIO对象,controller将图片对象通过流的形式写入到前端页面

    • 验证码形式支持字符和数学运算,数学运算需要自定义一个文本生成器`

      // 验证码文本生成器	
      properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.framework.config.KaptchaTextCreator");
      

2、用户点击登录按钮

  • 前端发送ajax请求

    //login.js
    function login() {
        $.modal.loading($("#btnSubmit").data("loading"));
        var username = $.common.trim($("input[name='username']").val());
        var password = $.common.trim($("input[name='password']").val());
        var validateCode = $("input[name='validateCode']").val();
        var rememberMe = $("input[name='rememberme']").is(':checked');
        $.ajax({
            type: "post",
            url: ctx + "login",
            data: {
                "username": username,
                "password": password,
                "validateCode": validateCode, //请求体中的验证码会在shiro验证码过滤器中进行验证
                "rememberMe": rememberMe
            },
            success: function(r) {
               //响应数据成功后,根据响应代码跳转到不同的页面
                if (r.code == web_status.SUCCESS) {
                   //登录成功,跳转到index页面
                    location.href = ctx + 'index';
                } else {
                   //登录失败
                   //关闭loading蒙层
                   $.modal.closeLoading();
                   //模拟点击一下刷新验证码按钮
                   $('.imgcode').click();
                   //清空验证码输入值
                   $(".code").val("");
                   //显示响应的错误消息
                   $.modal.msg(r.msg);
                }
            }
        });
    }
    
  • 发送POST请求到/login

    • 进行shiro权限验证
    • 获取登录的token值
    • 验证成功返回成功ajax数据,失败返回失败ajax数据
@PostMapping("/login")
@ResponseBody
public AjaxResult ajaxLogin(String username, String password, Boolean rememberMe)
{
    UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
    Subject subject = SecurityUtils.getSubject();
    try
    {
        subject.login(token);
        return success();
    }
    catch (AuthenticationException e)
    {
        String msg = "用户或密码错误";
        if (StringUtils.isNotEmpty(e.getMessage()))
        {
            msg = e.getMessage();
        }
        return error(msg);
    }
}

二、02-首页

  • 发送get请求index视图

    • ModelMap和Model的用法类似
    • SysUser user = ShiroUtils.getSysUser();获取当前登录的用户信息
    //SysIndexController.java
    
    // 系统首页
    @GetMapping("/index")
    public String index(ModelMap mmap)
    {
        // 取身份信息
        SysUser user = ShiroUtils.getSysUser();
        // 根据用户id取出菜单
        List<SysMenu> menus = menuService.selectMenusByUser(user);
        mmap.put("menus", menus);
        mmap.put("user", user);
        mmap.put("sideTheme", configService.selectConfigByKey("sys.index.sideTheme"));
        mmap.put("skinName", configService.selectConfigByKey("sys.index.skinName"));
        mmap.put("ignoreFooter", configService.selectConfigByKey("sys.index.ignoreFooter"));
        mmap.put("copyrightYear", RuoYiConfig.getCopyrightYear());
        mmap.put("demoEnabled", RuoYiConfig.isDemoEnabled());
        mmap.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
        mmap.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
    
        // 菜单导航显示风格
        String menuStyle = configService.selectConfigByKey("sys.index.menuStyle");
        // 移动端,默认使左侧导航菜单,否则取默认配置
        String indexStyle = ServletUtils.checkAgentIsMobile(ServletUtils.getRequest().getHeader("User-Agent")) ? "index" : menuStyle;
    
        // 优先Cookie配置导航菜单
        Cookie[] cookies = ServletUtils.getRequest().getCookies();
        for (Cookie cookie : cookies)
        {
            if (StringUtils.isNotEmpty(cookie.getName()) && "nav-style".equalsIgnoreCase(cookie.getName()))
            {
                indexStyle = cookie.getValue();
                break;
            }
        }
        String webIndex = "topnav".equalsIgnoreCase(indexStyle) ? "index-topnav" : "index";
        return webIndex;
    }
    
  • 从数据库查询到的菜单列表是没有树形结构的,进行了二次封装,最终返回树形结构的菜单到视图

    //SysMenuServiceImpl.java
    /**
     * 根据用户查询菜单
     * 
     * @param user 用户信息
     * @return 菜单列表
     */
    @Override
    public List<SysMenu> selectMenusByUser(SysUser user)
    {
        List<SysMenu> menus = new LinkedList<SysMenu>();
        // 管理员显示所有菜单信息
        if (user.isAdmin())
        {
            menus = menuMapper.selectMenuNormalAll();
        }
        else
        {
            menus = menuMapper.selectMenusByUserId(user.getUserId());
        }
        return getChildPerms(menus, 0);
    }
    
    /**
     * 根据父节点的ID获取所有子节点
     * 
     * @param list 分类表
     * @param parentId 传入的父节点ID
     * @return String
     */
    public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId)
    {
        List<SysMenu> returnList = new ArrayList<SysMenu>();
        for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext();)
        {
            SysMenu t = (SysMenu) iterator.next();
            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (t.getParentId() == parentId)
            {
                recursionFn(list, t);
                returnList.add(t);
            }
        }
        return returnList;
    }
    
    /**
     * 递归列表
     * 
     * @param list
     * @param t
     */
    private void recursionFn(List<SysMenu> list, SysMenu t)
    {
        // 得到子节点列表
        List<SysMenu> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysMenu tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                recursionFn(list, tChild);
            }
        }
    }
    

你可能感兴趣的:(ruoyi学习,java,shiro,mybatis,springmvc,spring,boot)