推荐:Java秒杀系统优化(高性能高并发)Java秒杀系统优化(高性能高并发)_Garry1115的博客-CSDN博客

说明:这是本人正在使用的一款通用权限管理系统。

来源:通过对网上优秀开源项目组件的合并与重构实现自身需求和功能。

技术架构:Springboot2.x + Shiro + MyBatis Plus + Layui

整个项目(初级版)的功能包括:用户管理、角色管理、菜单管理、字典管理、参数设置、通知公告、操作日志、登录日志、服务监控、资源分类等

高级版的功能在初级版之上会增加:部门管理、岗位管理、在线用户、定时任务、代码生成、系统接口、邮件管理、短信管理等

数据库表设计:

初级版数据库表:用户表、角色表、菜单表、用户角色表、角色菜单表、字典数据表、配置信息表、通知公告表、操作日志表、登陆日志表等。

高级版新增数据库表:新增部门表、岗位表、用户岗位表、角色部门表、短信配置模板、短信发送日志、邮件配置模板、邮件发送日志、定时任务管理、定时任务日志表等。

项目结构:

realm类

package com.xiaofeng.shiro.realm;

import com.google.common.collect.Sets;
import com.xiaofeng.shiro.entity.SysUser;
import com.xiaofeng.shiro.service.ISysLoginService;
import com.xiaofeng.shiro.service.ISysMenuService;
import com.xiaofeng.shiro.service.ISysRoleService;
import com.xiaofeng.shiro.util.ShiroUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Set;

/**
 * @author xiaofeng
 * @version V1.0
 * @title: UserRealm
 * @package: com.xiaofeng.share.shiro
 * @description: 自定义Realm 处理登录 权限
 * @date 2019/7/4 9:44
 */
public class UserRealm extends AuthorizingRealm {
    private static final Logger log = LoggerFactory.getLogger(UserRealm.class);

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ISysLoginService loginService;

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
        SysUser user = ShiroUtils.getSysUser();
        // 角色列表
        Set<String> roles = Sets.newHashSet();
        // 功能列表
        Set<String> menus = Sets.newHashSet();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 管理员拥有所有权限
        if (user.isAdmin()) {
            info.addRole("admin");
            info.addStringPermission("*:*:*");
        } else {
            roles = roleService.selectRoleKeys(user.getId().longValue());
            menus = menuService.selectPermssionByUserId(user.getId().longValue());
            // 角色加入AuthorizationInfo认证对象
            info.setRoles(roles);
            // 权限加入AuthorizationInfo认证对象
            info.setStringPermissions(menus);
        }
        return info;
    }

    /**
     * 登录认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        String password = "";
        if (upToken.getPassword() != null) {
            password = new String(upToken.getPassword());
        }

        SysUser user = null;
        try {
            user = loginService.login(username, password);
        } catch (Exception e) {
            log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage());
            throw new AuthenticationException(e.getMessage(), e);
        }
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
        return info;
    }

    /**
     * 清理缓存权限
     */
    public void clearCachedAuthorizationInfo() {
        this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }
}

废话不多说,直接上效果图:

后台主页:

用户管理模块:

角色管理模块:

菜单管理模块:

操作日志模块:

用户模块Controller:

package com.xiaofeng.shiro.controller;


import cn.afterturn.easypoi.entity.vo.NormalExcelConstants;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.view.PoiBaseView;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Maps;
import com.xiaofeng.shiro.aspectj.annotation.Log;
import com.xiaofeng.shiro.common.response.AjaxResult;
import com.xiaofeng.shiro.common.response.TableDataInfo;
import com.xiaofeng.shiro.constant.UserConstants;
import com.xiaofeng.shiro.entity.SysRole;
import com.xiaofeng.shiro.entity.SysUser;
import com.xiaofeng.shiro.enums.LogType;
import com.xiaofeng.shiro.service.ISysRoleService;
import com.xiaofeng.shiro.service.ISysUserService;
import com.xiaofeng.shiro.service.impl.SysPasswordService;
import com.xiaofeng.shiro.util.DateUtil;
import com.xiaofeng.shiro.util.ShiroUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户信息表 前端控制器
 * </p>
 *
 * @author xiaofeng
 * @since 2019-07-03
 */
@Controller
@RequestMapping("/system/user")
public class SysUserController extends BaseController {
    private String prefix = "system/user";

    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysRoleService roleService;
    @Autowired
    private SysPasswordService passwordService;

    @RequiresPermissions("system:user:view")
    @GetMapping()
    public String user() {
        return prefix + "/user";
    }

    @Log(title = "用户查询", logType = LogType.SELECT)
    @RequiresPermissions("system:user:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(SysUser user) {
        IPage<SysUser> page = getPage();
        userService.pageList(page, user);
        return getDataTable(page.getRecords(), page.getSize());
    }

    @Log(title = "用户管理", logType = LogType.EXPORT)
    @RequiresPermissions("system:user:export")
    @GetMapping("/export")
    public void export(SysUser user, HttpServletRequest request, HttpServletResponse response) {
        List<SysUser> list = userService.list(user);
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        String title = "用户信息";
        Map<String, Object> map = Maps.newHashMap();
        ExportParams params = new ExportParams(title, title, ExcelType.HSSF);
        map.put(NormalExcelConstants.DATA_LIST, list);
        map.put(NormalExcelConstants.CLASS, SysUser.class);
        map.put(NormalExcelConstants.PARAMS, params);
        map.put("fileName", DateUtil.getNowDateTime());
        PoiBaseView.render(map, request, response, NormalExcelConstants.EASYPOI_EXCEL_VIEW);
    }

    /**
     * 新增用户
     */
    @GetMapping("/add")
    public String add(ModelMap mmap) {
        List<SysRole> roleList = roleService.list(new LambdaQueryWrapper<SysRole>().eq(SysRole::getDelFlag, 0));
        mmap.put("roles", roleList);
        return prefix + "/add";
    }

    /**
     * 新增保存用户
     */
    @RequiresPermissions("system:user:add")
    @Log(title = "用户管理", logType = LogType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(SysUser user) {
        if (user.getId() != null && SysUser.isAdmin(ShiroUtils.getSysUser().getUserType())) {
            return error("不允许修改超级管理员用户");
        }
        String nameUnique = userService.checkLoginNameUnique(user.getUserName());
        if (UserConstants.USER_NAME_NOT_UNIQUE.equals(nameUnique)) {
            return error("保存用户'" + user.getUserName() + "'失败,登录账号已存在");
        }
        user.setSalt(ShiroUtils.randomSalt());
        user.setPassword(passwordService.encryptPassword(user.getUserName(), user.getPassword(), user.getSalt()));
        user.setCreateBy(ShiroUtils.getLoginName());
        user.setCreateTime(DateUtil.getNowTimestamp());
        return toAjax(userService.insertUser(user));
    }

    /**
     * 修改用户
     */
    @GetMapping("/edit/{userId}")
    public String edit(@PathVariable("userId") Long userId, ModelMap mmap) {
        mmap.put("user", userService.getById(userId));
        mmap.put("roles", roleService.selectRolesByUserId(userId));
        return prefix + "/edit";
    }

    /**
     * 修改保存用户
     */
    @RequiresPermissions("system:user:edit")
    @Log(title = "用户管理", logType = LogType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(SysUser user) {
        if (user.getId() != null && SysUser.isAdmin(ShiroUtils.getSysUser().getUserType())) {
            return error("不允许修改超级管理员用户");
        }
        user.setUpdateBy(ShiroUtils.getLoginName());
        return toAjax(userService.updateUser(user));
    }


    @RequiresPermissions("system:user:resetPwd")
    @Log(title = "重置密码", logType = LogType.UPDATE)
    @GetMapping("/resetPwd/{userId}")
    public String resetPwd(@PathVariable("userId") Long userId, ModelMap mmap) {
        mmap.put("user", userService.getById(userId));
        return prefix + "/resetPwd";
    }

    @RequiresPermissions("system:user:resetPwd")
    @Log(title = "重置密码", logType = LogType.UPDATE)
    @PostMapping("/resetPwd")
    @ResponseBody
    public AjaxResult resetPwdSave(SysUser user) {
        user.setSalt(ShiroUtils.randomSalt());
        user.setPassword(passwordService.encryptPassword(user.getUserName(), user.getPassword(), user.getSalt()));
        return toAjax(userService.updateById(user));
    }

    @RequiresPermissions("system:user:remove")
    @Log(title = "用户管理", logType = LogType.DELETE)
    @PostMapping("/remove")
    @ResponseBody
    public AjaxResult remove(String ids) {
        try {
            if (StringUtils.isNoneBlank(ids)) {
                String[] split = ids.split(",");
                return toAjax(userService.batchDeleteUser(Arrays.asList(split)));
            }
        } catch (Exception e) {
            return error(e.getMessage());
        }
        return error();
    }


    /**
     * 校验用户名
     */
    @PostMapping("/checkLoginNameUnique")
    @ResponseBody
    public String checkLoginNameUnique(SysUser user) {
        String nameUnique = userService.checkLoginNameUnique(user.getUserName());
        return nameUnique;
    }

    /**
     * 校验手机号码
     */
    @PostMapping("/checkPhoneUnique")
    @ResponseBody
    public String checkPhoneUnique(SysUser user) {
        String phoneUnique = userService.checkPhoneUnique(user);
        return phoneUnique;
    }

    /**
     * 校验email邮箱
     */
    @PostMapping("/checkEmailUnique")
    @ResponseBody
    public String checkEmailUnique(SysUser user) {
        return userService.checkEmailUnique(user);
    }

    /**
     * 用户状态修改
     */
    @Log(title = "用户管理", logType = LogType.UPDATE)
    @RequiresPermissions("system:user:edit")
    @PostMapping("/changeStatus")
    @ResponseBody
    public AjaxResult changeStatus(SysUser user) {
        if (SysUser.isAdmin(ShiroUtils.getSysUser().getUserType())) {
            return error("不允许修改超级管理员用户");
        }
        return toAjax(userService.updateUser(user));
    }
}

用户模块service实现:

package com.xiaofeng.shiro.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaofeng.shiro.constant.Constants;
import com.xiaofeng.shiro.constant.UserConstants;
import com.xiaofeng.shiro.entity.SysRole;
import com.xiaofeng.shiro.entity.SysUser;
import com.xiaofeng.shiro.entity.SysUserRole;
import com.xiaofeng.shiro.mapper.SysRoleMapper;
import com.xiaofeng.shiro.mapper.SysUserMapper;
import com.xiaofeng.shiro.mapper.SysUserRoleMapper;
import com.xiaofeng.shiro.service.ISysUserRoleService;
import com.xiaofeng.shiro.service.ISysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author xiaofeng
 * @since 2019-07-03
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {
    @Autowired
    SysUserMapper sysUserMapper;
    @Autowired
    SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    SysRoleMapper sysRoleMapper;
    @Autowired
    ISysUserRoleService userRoleService;

    @Override
    public IPage<SysUser> pageList(IPage<SysUser> iPage, SysUser user) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<SysUser>();
        queryWrapper
                .like(StringUtils.isNoneBlank(user.getUserName()), SysUser::getUserName, user.getUserName())
                .like(StringUtils.isNoneBlank(user.getTelephone()), SysUser::getTelephone, user.getTelephone())
                .ge(user.getParams().get(Constants.START_TIME) != null && StringUtils.isNoneBlank(user.getParams().get(Constants.START_TIME).toString()), SysUser::getCreateTime, user.getParams().get(Constants.START_TIME))
                .le(user.getParams().get(Constants.END_TIME) != null && StringUtils.isNoneBlank(user.getParams().get(Constants.END_TIME).toString()), SysUser::getCreateTime, user.getParams().get(Constants.END_TIME));
        page(iPage, queryWrapper);
        return iPage;
    }

    /**
     * 不分页查询
     *
     * @param user
     * @return
     */
    @Override
    public List<SysUser> list(SysUser user) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<SysUser>();
        queryWrapper
                .like(StringUtils.isNoneBlank(user.getUserName()), SysUser::getUserName, user.getUserName())
                .like(StringUtils.isNoneBlank(user.getTelephone()), SysUser::getTelephone, user.getTelephone())
                .like(StringUtils.isNoneBlank(user.getSearchValue()), SysUser::getUserName, user.getSearchValue())
                .like(StringUtils.isNoneBlank(user.getSearchValue()), SysUser::getTelephone, user.getSearchValue())
                .ge(user.getParams().get(Constants.START_TIME) != null && StringUtils.isNoneBlank(user.getParams().get(Constants.START_TIME).toString()), SysUser::getCreateTime, user.getParams().get(Constants.START_TIME))
                .le(user.getParams().get(Constants.END_TIME) != null && StringUtils.isNoneBlank(user.getParams().get(Constants.END_TIME).toString()), SysUser::getCreateTime, user.getParams().get(Constants.END_TIME));
        List<SysUser> list = list(queryWrapper);
        return list;
    }

    /**
     * 校验用户名称是否唯一
     *
     * @param loginName 登录名称
     * @return 结果
     */
    @Override
    public String checkLoginNameUnique(String loginName) {
        int count = count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, loginName));
        return count > 0 ? UserConstants.USER_NAME_NOT_UNIQUE : UserConstants.USER_NAME_UNIQUE;
    }

    /**
     * 校验手机号码是否唯一
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public String checkPhoneUnique(SysUser user) {
        Long userId = user.getId() == null ? -1L : user.getId();
        SysUser sysUser = getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getTelephone, user.getTelephone()));
        String s = sysUser != null && !userId.equals(sysUser.getId()) ? UserConstants.USER_NAME_NOT_UNIQUE : UserConstants.USER_NAME_UNIQUE;
        return s;
    }

    /**
     * 校验email是否唯一
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public String checkEmailUnique(SysUser user) {
        Long userId = user.getId() == null ? -1L : user.getId();
        SysUser sysUser = getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getEmail, user.getEmail()));
        String s = sysUser != null && !userId.equals(sysUser.getId()) ? UserConstants.USER_NAME_NOT_UNIQUE : UserConstants.USER_NAME_UNIQUE;
        return s;
    }

    @Override
    public List<SysUser> selectAllocatedList(SysUser user) {
        return sysUserMapper.selectAllocatedList(user);
    }

    @Override
    public List<SysUser> selectUnallocatedList(SysUser user) {
        return sysUserMapper.selectUnallocatedList(user);
    }

    /**
     * 新增保存用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public int insertUser(SysUser user) {
        // 新增用户信息
        int rows = sysUserMapper.insert(user);
        // 新增用户与角色管理
        insertUserRole(user);
        return rows;
    }

    /**
     * 修改保存用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public int updateUser(SysUser user) {
        // 删除用户与角色关联
        sysUserRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, user.getId()));
        // 新增用户与角色管理
        insertUserRole(user);
        boolean b = updateById(user);
        return b ? 1 : 0;
    }

    /**
     * 查询用户所属角色组
     *
     * @param userId 用户ID
     * @return 结果
     */
    @Override
    public String selectUserRoleGroup(Long userId) {
        List<SysRole> sysRoles = sysRoleMapper.selectRolesByUserId(userId);
        StringBuffer idsStr = new StringBuffer();
        for (SysRole role : sysRoles) {
            idsStr.append(role.getRoleName()).append(",");
        }
        if (StringUtils.isNotEmpty(idsStr.toString())) {
            return idsStr.substring(0, idsStr.length() - 1);
        }
        return idsStr.toString();
    }

    /**
     * 查询用户所属岗位组
     *
     * @param userId 用户ID
     * @return 结果
     */
    @Override
    public String selectUserPostGroup(Long userId) {

        return "";
    }

    /**
     * 删除
     *
     * @param userId
     * @return
     */
    @Override
    public int deleteUser(Long userId) {
        //删除用户角色关联
        sysUserRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
        //删除用户信息
        boolean b = removeById(userId);
        return b ? 1 : 0;
    }

    /**
     * 批量删除
     *
     * @param userId
     * @return
     */
    @Override
    public int batchDeleteUser(Collection<? extends Serializable> userId) {
        //删除用户角色关联
        sysUserRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getUserId, userId));
        //删除用户
        boolean b = removeByIds(userId);
        return b ? 1 : 0;
    }

    /**
     * 新增用户角色信息
     *
     * @param user 用户对象
     */
    public void insertUserRole(SysUser user) {
        Long[] roles = user.getRoleIds();
        if (roles != null) {
            // 新增用户与角色管理
            List<SysUserRole> list = new ArrayList<SysUserRole>();
            for (Long roleId : roles) {
                SysUserRole ur = new SysUserRole();
                ur.setUserId(user.getId());
                ur.setRoleId(roleId.intValue());
                list.add(ur);
            }
            if (list.size() > 0) {
                userRoleService.saveBatch(list);
            }
        }
    }

}

Shiro权限:

package com.xiaofeng.share.shiro;

import com.google.common.collect.Sets;
import com.xiaofeng.share.entity.SysUser;
import com.xiaofeng.share.service.ISysLoginService;
import com.xiaofeng.share.service.ISysMenuService;
import com.xiaofeng.share.service.ISysRoleService;
import com.xiaofeng.share.util.ShiroUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Set;

/**
 * @author xiaofeng
 * @version V1.0
 * @title: UserRealm
 * @package: com.xiaofeng.share.shiro
 * @description: 自定义Realm 处理登录 权限
 * @date 2019/7/4 9:44
 */
public class UserRealm extends AuthorizingRealm {
    private static final Logger log = LoggerFactory.getLogger(UserRealm.class);

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ISysLoginService loginService;

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
        SysUser user = ShiroUtils.getSysUser();
        // 角色列表
        Set<String> roles = Sets.newHashSet();
        // 功能列表
        Set<String> menus = Sets.newHashSet();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 管理员拥有所有权限
        if (user.isAdmin()) {
            info.addRole("admin");
            info.addStringPermission("*:*:*");
        } else {
            roles = roleService.selectRoleKeys(user.getId().longValue());
            menus = menuService.selectPermssionByUserId(user.getId().longValue());
            // 角色加入AuthorizationInfo认证对象
            info.setRoles(roles);
            // 权限加入AuthorizationInfo认证对象
            info.setStringPermissions(menus);
        }
        return info;
    }

    /**
     * 登录认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        String password = "";
        if (upToken.getPassword() != null) {
            password = new String(upToken.getPassword());
        }

        SysUser user = null;
        try {
            user = loginService.login(username, password);
        } catch (Exception e) {
            log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage());
            throw new AuthenticationException(e.getMessage(), e);
        }
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
        return info;
    }

    /**
     * 清理缓存权限
     */
    public void clearCachedAuthorizationInfo() {
        this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }
}

核心配置文件:

更新日志:

多环境配置:

多数据源配置(动态数据源):

--------------------------------------------------------------20190926----------------------------------------------------------------------

2019年9月26,今天主要更新了2个功能模块:代码生成工具、在线会话数统计、同一个用户多设备登录限制(默认踢出前一个),sftp文件上传配置修复(用于图片上传),邮件发送配置更新等。

更新日志:

代码生成工具:

采用velocity模板工具生成代码

CodeGenerateController

package com.xiaofeng.sys.controller.tool;

import com.xiaofeng.sys.common.TableDataInfo;
import com.xiaofeng.sys.controller.BaseController;
import com.xiaofeng.sys.entity.generate.TableInfo;
import com.xiaofeng.sys.service.IGenerateService;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @author xiaofeng
 * @version V1.0
 * @title: CodeGenerateController
 * @package: com.xiaofeng.code.generate.controller
 * @description: 代码生成 操作处理
 * @date 2019/9/20 13:47
 */
@Controller
@RequestMapping("/tool/gen")
public class CodeGenerateController extends BaseController {
    private String prefix = "tool/gen";

    @Autowired
    private IGenerateService generateService;

    @RequiresPermissions("tool:gen:view")
    @GetMapping()
    public String gen() {
        return prefix + "/gen";
    }

    @GetMapping("/test")
    public String test() {
        return "test";
    }

    @RequiresPermissions("tool:gen:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(TableInfo tableInfo) {
        List<TableInfo> list = generateService.selectTableList(tableInfo);
        return getDataTable(list);
    }

    /**
     * 生成代码
     */
    @RequiresPermissions("tool:gen:code")
    @GetMapping("/genCode/{tableName}")
    public void genCode(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException {
        byte[] data = generateService.generatorCode(tableName);
        genCode(response, data);
    }

    /**
     * 批量生成代码
     */
    @RequiresPermissions("tool:gen:code")
    @GetMapping("/batchGenCode")
    @ResponseBody
    public void batchGenCode(HttpServletResponse response, String tables) throws IOException {
        if (StringUtils.isBlank(tables)) {
            return;
        }
        String[] tableNames = tables.split(",");
        byte[] data = generateService.generatorCode(tableNames);
        genCode(response, data);
    }

    /**
     * 生成zip文件
     *
     * @param response
     * @param data
     * @throws IOException
     */
    private void genCode(HttpServletResponse response, byte[] data) throws IOException {
        response.reset();
        response.setHeader("Content-Disposition", "attachment; filename=\"xiaofeng-code-generate.zip\"");
        response.addHeader("Content-Length", "" + data.length);
        response.setContentType("application/octet-stream; charset=UTF-8");
        IOUtils.write(data, response.getOutputStream());
    }
}

在线会话统计:

采用shiro session存储用户会话信息,会话信息存在系统session中,退出即销毁

OnlineSessionFilter(在线session过滤器


package com.xiaofeng.sys.shiro;

import com.xiaofeng.sys.common.constant.ShiroConstants;
import com.xiaofeng.sys.common.enums.OnlineStatus;
import com.xiaofeng.sys.entity.SysUser;
import com.xiaofeng.sys.util.ShiroUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

/**
 * @author xiaofeng
 * @version V1.0
 * @title: OnlineSessionFilter
 * @package: com.xiaofeng.sys.shiro
 * @description: 在线session过滤器
 * @date 2019/9/26 16:00
 */
public class OnlineSessionFilter extends AccessControlFilter {

    /**
     * 强制退出后重定向的地址
     */
    private String forceLogoutUrl;

    private SessionDAO sessionDAO;

    public String getForceLogoutUrl() {
        return forceLogoutUrl;
    }

    public void setForceLogoutUrl(String forceLogoutUrl) {
        this.forceLogoutUrl = forceLogoutUrl;
    }

    public void setSessionDAO(SessionDAO sessionDAO) {
        this.sessionDAO = sessionDAO;
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
            throws Exception {
        Subject subject = getSubject(request, response);
        if (subject == null || subject.getSession() == null) {
            return true;
        }
        Session session = sessionDAO.readSession(subject.getSession().getId());
        if (session != null && session instanceof OnlineSession) {
            OnlineSession onlineSession = (OnlineSession) session;
            request.setAttribute(ShiroConstants.ONLINE_SESSION, onlineSession);
            // 把user id设置进去
            //boolean isGuest = onlineSession.getUserId() == null  ;
            if (onlineSession.getUserId() == null) {
                SysUser user = ShiroUtils.getSysUser();
                if (user != null) {
                    onlineSession.setUserId(user.getUserId().longValue());
                    onlineSession.setLoginName(user.getLoginName());
                    onlineSession.setAvatar(user.getAvatar());
                    onlineSession.markAttributeChanged();
                }
            }
            if (onlineSession.getStatus() == OnlineStatus.off_line) {
                return false;
            }
        }
        return true;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        Subject subject = getSubject(request, response);
        if (subject != null) {
            subject.logout();
        }
        saveRequestAndRedirectToLogin(request, response);
        return true;
    }

    @Override
    protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
        WebUtils.issueRedirect(request, response, getForceLogoutUrl());
    }

}

SFTP上传配置:

在线用户统计

代码生成

文件管理主要包括:文件上传、文件编辑、文件下载、文件删除,后续会增加文件预览等功能。

文件上传到自主服务器linux目录,通过nginx配置反向代理映射处理,采用sftp协议实现上传、下载、删除等功能。

效果如下:

点击上传(将文件上传到服务器)

点击下载(将文件下载到本地)

由于篇幅有限,无法粘贴所有核心代码。

初级版download:java web基础权限系统 (resourcecode.cn)

高级版download:springboot完整版权限系统 (resourcecode.cn)

qq:193459197

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐