从零搭建项目开发框架-19系统登录及首页面

系统管理的各个功能开发完毕,下一步就该开发系统登录界面及首页面了,这样一个系统的雏形才能出来。

这里设计登录先以简单为主,像用不用验证码、密码输入错误次数等等都不做考虑,这是后续需要完成的事情,这里只校验账号密码是否成功,账户是否锁定,成功则设置session,并跳转至首页面。

1、登录页面图

登录页面图.png

jCookie.js

引入这个js的目的是,用cookie来保存是否选择记住我这个checkbox。

userBrower.js

引入这个的目的是获取浏览器的类型及版本号,提交给后台记录下来

UserSession.java

public class UserSession implements Serializable {

    private static final long serialVersionUID = 1629527703944211785L;
    private int userId;//用户id
    private String userIp;//用户IP

    private String username;//用户名  即登录账号
    private String realname;//真实姓名
    private int roleId;//角色id
    private String roleName;//角色名称

    @Override
    public String toString() {
        return "UserSession{" +
                "userId=" + userId +
                ", userIp='" + userIp + '\'' +
                ", username='" + username + '\'' +
                ", realname='" + realname + '\'' +
                ", roleId=" + roleId +
                ", roleName='" + roleName + '\'' +
                '}';
    }
// set get方法省略
}

用户UserSession是一个对象,里面包括ip、userId、用户名、姓名、角色id、角色等常用信息。

SessionUtil.java

public class SessionUtil {
    /**
     * 功能描述:获取用户session
     *
     * @param request
     * @return UserSession
     * @version 1.0.0
     */
    public static UserSession getUserSession(HttpServletRequest request) {
        if (request.getSession().getAttribute("userSession") != null)
            return (UserSession) request.getSession().getAttribute("userSession");
        else {
//            UserSession userSession = new UserSession();
//            userSession.setRoleId(1);
//            userSession.setUserId(1);
//            userSession.setUsername("admin");
//            userSession.setRealname("admin");
//            return userSession;
            return null;
        }
    }

    /**
     * 获取当前操作人
     *
     * @param request
     * @return
     */
    public static String getRealname(HttpServletRequest request) {
        return getUserSession(request).getRealname();
    }
}

这个工具类的目的是统一获取UserSession

checkLogin()校验登录方法

@RequestMapping("/checkLogin")
    public void checkLogin(HttpServletRequest request, HttpServletResponse response, String username, String password) {
        //      // 校验账号和密码是否都为空
        if (StringUtil.isNullOrEmpty(username) || StringUtil.isNullOrEmpty(password)) {
            WebUtil.out(response, JsonUtil.createOperaStr(false, "用户名或密码错误"));
            return;
        }

        SysUser sysUser = sysUserService.getByUsername(username);
        if (sysUser == null || !sysUserService.checkPass(sysUser, password)) {
            String json = "{\"success\":" + false + ",\"msgText\":\"用户名或密码错误\"}";
            WebUtil.out(response, json);
        } else {
            if (sysUser.getStatus() == 2) {
                WebUtil.out(response, JsonUtil.createOperaStr(false, "该用户已锁定"));
            } else {
                String ip = StringUtil.getIp(request);
                UserSession userSession = new UserSession();
                userSession.setUserId(sysUser.getId());//userId
                userSession.setUsername(sysUser.getUsername());//username
                userSession.setUserIp(ip);//IP地址
                userSession.setRoleId(sysUser.getRoleId());
                userSession.setRoleName(sysUser.getRoleName());// 角色
                userSession.setRealname(sysUser.getRealname());
                request.getSession().setAttribute("userSession", userSession);

                request.getSession().setMaxInactiveInterval(1000 * 60 * 30);// 设置过期时间30分钟
                // 插入登录日志
                SysUserLogin sysUserLogin = new SysUserLogin();
                sysUserLogin.setUserId(sysUser.getId());
                sysUserLogin.setLoginDate(new Date());
                sysUserLogin.setLoginIp(ip);
                sysUserLogin.setTerminal(WebUtil.getSafeStr(request.getParameter("terminal")));
                sysUserLogin.setExplorerType(WebUtil.getSafeStr(request.getParameter("explorerType")));
                sysUserLogin.setExplorerVersion(WebUtil.getSafeStr(request.getParameter("explorerVersion")));
                userLoginService.add(sysUserLogin);
                WebUtil.out(response, JsonUtil.createOperaStr(true, "登录成功"));
            }
        }
    }

这一段的代码不复杂,就是根据获取的用户名和密码与数据库取到的进行比较,如果一样且当前用户未锁定,则登录成功,记录session,并记录登录日志。

2、系统首页

首页.png

登录成功后进入首页,这一块需要修改的是左侧菜单,需要根据用户的roleId动态从数据库中读取。这里采用自定义标签函数的方式,在service层写好生成的菜单代码。

webtag.tld增加配置

<function>
    <description>生成菜单</description>
    <name>createMenu</name>
    <function-class>com.critc.plat.util.web.WebTag</function-class>
    <function-signature>java.lang.String createMenu(javax.servlet.http.HttpServletRequest)</function-signature>
    </function>

WebTag.java增加代码

/**
     * 生成菜单
     *
     * @param request 请求
     * @return 菜单
     */
    public static String createMenu(HttpServletRequest request) {
        UserSession userSession = SessionUtil.getUserSession(request);
        SysRoleService sysRoleService = SpringContextHolder.getBean("sysRoleService");
        return sysRoleService.createMenuStr(userSession.getRoleId());
    }

SysRoleService.java增加createMenuStr代码

/**
     * 根据角色id生成该角色对应的菜单
     *
     * @param role_id
     * @return
     */
    public String createMenuStr(int role_id) {
        String menu = EhCacheUtil.get("sysCache", "roleMenu_" + role_id);
        if (menu == null) {
            StringBuffer sb = new StringBuffer();
            List<SysResource> listResource = sysResourceDao.list();// 模块列表
            List<SysRoleResource> listRoleResource = sysRoleresourceDao.listRoleResourceByType(role_id, 1);// 角色模块列表
            List<Integer> displayResourceIdList = new ArrayList<>();
            for (SysRoleResource sysRoleResource : listRoleResource) {
                displayResourceIdList.add(sysRoleResource.getResourceId());
            }
            for (SysResource sysResource : listResource) {
                if (sysResource.getParentId() == 1 && displayResourceIdList.contains(sysResource.getId())) {
                    sb.append("<li class=\"\"><a href=\"#\" class=\"dropdown-toggle\"> <i class=\"menu-icon fa "
                            + sysResource.getIconImg() + "\"></i> <span class=\"menu-text\"> " + sysResource.getName()
                            + " </span> <b class=\"arrow fa fa-angle-down\"></b></a> <b class=\"arrow\"></b><ul class=\"submenu\">");
                    for (SysResource sysResourceChild : listResource) {
                        if (sysResourceChild.getParentId() == sysResource.getId()
                                && displayResourceIdList.contains(sysResourceChild.getId())) {
                            sb.append("<li id=\"module_" + sysResourceChild.getId() + "\" class=\"\"><a href=\""
                                    + pubConfig.getDynamicServer() + "/" + sysResourceChild.getUrl()
                                    + "\" target=\"" + sysResourceChild.getTarget() + "\"> <i class=\"menu-icon fa fa-caret-right\"></i>" + sysResourceChild.getName()
                                    + "</a> <b class=\"arrow\"></b></li>");
                        }
                    }
                    sb.append("</ul></li>");
                }
            }
            menu = sb.toString();
            EhCacheUtil.put("sysCache", "roleMenu_" + role_id, menu);
        }
        return menu;
    }

这段代码的原理是先根据roleId从EhCache的缓存读取菜单的字符串,如果没有则生成该字符串。生成的原理很简单,可以参照ACE菜单的代码,就是<ul><li>的迭代。生成完放入EhCache中。

EhCacheUtil.java 缓存工具类

增加依赖

 <!-- EHCache -->
<dependency>
      <groupId>net.sf.ehcache</groupId>
      <artifactId>ehcache</artifactId>
      <version>${ehcache.version}</version>
</dependency>
public class EhCacheUtil {
    private static volatile EhCacheUtil ehCacheUtil;
    private static volatile CacheManager cacheManager;
    private static Logger log = LoggerFactory.getLogger(EhCacheUtil.class);
    private static String confPath = "/ehcache.xml";//定义配置文件路径

    public static EhCacheUtil getInstance() {
        if (null == ehCacheUtil) {
            synchronized (EhCacheUtil.class) {
                if (null == ehCacheUtil) {
                    ehCacheUtil = new EhCacheUtil();
                }
            }
        }
        return ehCacheUtil;
    }

    static {
        try {
            URL url = EhCacheUtil.class.getResource(confPath);
            cacheManager = CacheManager.create(url);
            log.info("ehcache初始化");
        } catch (Exception e) {
            e.printStackTrace();
            log.info("ehcache初始化失败");
        }
    }

    public static CacheManager getCacheManager() {
        return cacheManager;
    }

    static Cache getOrAddCache(String cacheName) {
        Cache cache = cacheManager.getCache(cacheName);
        if (cache == null) {
            synchronized (cacheManager) {
                cache = cacheManager.getCache(cacheName);
                if (cache == null) {
                    log.warn("Could not find cache config [" + cacheName + "], using default.");
                    cacheManager.addCacheIfAbsent(cacheName);
                    cache = cacheManager.getCache(cacheName);
                    log.info("Cache [" + cacheName + "] started.");
                }
            }
        }
        return cache;
    }

    public static void put(String cacheName, Object key, Object value) {
        getOrAddCache(cacheName).put(new Element(key, value));
    }

    @SuppressWarnings("unchecked")
    public static <T> T get(String cacheName, Object key) {
        Element element = getOrAddCache(cacheName).get(key);
        return element != null ? (T) element.getObjectValue() : null;
    }

    @SuppressWarnings("rawtypes")
    public static List getKeys(String cacheName) {
        return getOrAddCache(cacheName).getKeys();
    }

    public static void remove(String cacheName, Object key) {
        getOrAddCache(cacheName).remove(key);
    }

    public static void removeAll(String cacheName) {
        getOrAddCache(cacheName).removeAll();
    }

    public static void main(String[] args) {
        EhCacheUtil.put("sysCache", "cache", "Hello EhCache");
        String value = EhCacheUtil.get("sysCache", "cache");
        System.out.println(value);
    }

}

上面是EhCache的工具类用法,很简单,核心就三个方法,put、get、removeAll三个方法。

具体EHCache的用法,参见
2.1EhCache

SpringContextHolder

由于在WebTag.java这个静态方法中,是无法直接注入SysRoleService这个类的,所以必须从Spring的容器中根据方法名直接获取。

public class SpringContextHolder implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    /**
     * 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.
     */
    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContextHolder.applicationContext = applicationContext; //NOSONAR
    }

    /**
     * 取得存储在静态变量中的ApplicationContext.
     */
    public static ApplicationContext getApplicationContext() {
        checkApplicationContext();
        return applicationContext;
    }

    /**
     * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        checkApplicationContext();
        return (T) applicationContext.getBean(name);
    }

    /**
     * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
     * 如果有多个Bean符合Class, 取出第一个.
     */
    public static <T> T getBean(Class<T> requiredType) {
        checkApplicationContext();
        return applicationContext.getBean(requiredType);
    }

    /**
     * 清除applicationContext静态变量.
     */
    public static void cleanApplicationContext() {
        applicationContext = null;
    }

    private static void checkApplicationContext() {
        if (applicationContext == null) {
            throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder");
        }
    }
}

代码比较简单,不过需要在Spring配置中applicationContext.xml增加以下一句话:

<bean class="com.critc.plat.core.spring.SpringContextHolder"
          lazy-init="false"/>

menu.jspf

<ul class="nav nav-list">
        <li class="active" id="menu-statistic"><a href="${dynamicServer}/index.htm" id="module_statistic"> <i
                class="menu-icon fa fa-tachometer"></i> <span class="menu-text"> 功能菜单 </span>
        </a> <b class="arrow"></b></li> 
        ${critc:createMenu(pageContext.request) }

    </ul>

调用标签的createMenu方法即可

系统登录和进入首页还是比较复杂的,远远不是几句话就能讲清楚的,得需要深入的研究和琢磨才行

源码下载

本阶段详细源码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,288评论 19 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,877评论 18 399
  • 一. Java基础部分.................................................
    wy_sure阅读 3,882评论 0 11
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,792评论 0 17
  • 二十岁你觉得迷茫吗?二十岁无论你是在上学,无论你是在工作,无论你是无业或是其他我没有想到的,但是我知道你们都会感...
    怀书呀阅读 218评论 0 0