SpringBoot整合Mybatis和Shiro(代码记录)

本文为个人学习demo记录随笔,主要代码记录

*Redis部分忽略,因为仅仅是整合,未测试

*内容中包含很多个人学习性代码 

 

一、项目目录

展开

 

二、详细代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/>
    </parent>
    
    <groupId>com.classic</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <mybatis.version>2.1.3</mybatis.version>
        <shiro.version>1.5.3</shiro.version>
        <hikaricp.version>3.4.5</hikaricp.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
        <!-- JDBC -->
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.apache.tomcat</groupId>
                <artifactId>tomcat-jdbc</artifactId>
            </exclusion>
        </exclusions>
     </dependency>
        
        <!-- HikariCP -->
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </dependency>
        
        <!-- MySQL -->
        <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
    </dependency>
        
        <!-- Mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        
        <!-- shiro -->
    <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        
        <!-- Redis -->
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency> 
        
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
View Code

 

application.properties

### 基本配置  ###
server.port=8080
server.servlet.context-path=/demo

### DataSource ###
spring.datasource.url=jdbc:mysql://localhost:3306/sourceplan?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false
spring.datasource.username=root
spring.datasource.password=pw123456
# 驱动
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 数据源类型
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
# 连接池名称
spring.datasource.hikari.pool-name=DateSourceHikariCP
# 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 默认:30秒
spring.datasource.hikari.connection-timeout=30000
# 最小连接数
spring.datasource.hikari.minimum-idle=10
# 最大连接数
spring.datasource.hikari.maximum-pool-size=2000
# 自动提交
spring.datasource.hikari.auto-commit=true
# 连接超时的最大时长(毫秒),超时则被释放(retired),默认:10分钟
spring.datasource.hikari.idle-timeout=600000
# 连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟 1800000ms
spring.datasource.hikari.max-lifetime=1800000
# 连接测试
spring.datasource.hikari.connection-test-query=SELECT 1

### MyBatis 配置  ###
# 所有POJO类所在包路径
#mybatis.type-aliases-package=com.test.pojo
# mapper映射文件
mybatis.mapper-locations=classpath:mapper/*.xml

### Redis pool 配置  ###
# Redis数据库索引(默认为0,最大15) 
#spring.redis.database=0
# Redis服务器地址
#spring.redis.host=192.168.0.24
# Redis服务器连接端口
#spring.redis.port=6379
# Redis服务器连接密码(默认为空)
#spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
#spring.redis.pool.max-active=200
# 连接池最大阻塞等待时间(使用负值表示没有限制) 
#spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
#spring.redis.pool.max-idle=10
# 连接池中的最小空闲连接
#spring.redis.pool.min-idle=0
# 连接超时时间(毫秒) 
#spring.redis.timeout=1000
View Code

 

启动类:DemoApplication.java

package com.classic.app;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@ComponentScan(basePackages = {"com.classic"})
@MapperScan("com.classic.dao")
@EnableTransactionManagement // 启注解事务管理,等同于xml配置方式的 <tx:annotation-driven />
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}
View Code

 

建表语句(表中均为模拟数据)

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for permission
-- ----------------------------
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `permission_code` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of permission
-- ----------------------------
INSERT INTO `permission` VALUES ('1', 'query');
INSERT INTO `permission` VALUES ('2', 'update');
INSERT INTO `permission` VALUES ('3', 'insert');
INSERT INTO `permission` VALUES ('4', 'delete');

-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `role_code` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES ('1', 'ADMIN');
INSERT INTO `role` VALUES ('2', 'USER');

-- ----------------------------
-- Table structure for role_to_permission
-- ----------------------------
DROP TABLE IF EXISTS `role_to_permission`;
CREATE TABLE `role_to_permission` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role_id` int(11) DEFAULT NULL,
  `permission_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of role_to_permission
-- ----------------------------
INSERT INTO `role_to_permission` VALUES ('1', '1', '1');
INSERT INTO `role_to_permission` VALUES ('2', '1', '2');
INSERT INTO `role_to_permission` VALUES ('3', '1', '3');
INSERT INTO `role_to_permission` VALUES ('4', '1', '4');
INSERT INTO `role_to_permission` VALUES ('5', '2', '1');

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(30) DEFAULT NULL,
  `password` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'zhousjcn', 'pw123456');
INSERT INTO `user` VALUES ('2', 'zhousj', 'pw123456');

-- ----------------------------
-- Table structure for user_role
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `role_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES ('1', '1', '1');
INSERT INTO `user_role` VALUES ('2', '2', '2');
View Code

 

entity 

User.java

package com.classic.entity;

import java.util.Set;

public class User {
    
    private Long id;
    private String username;
    private String password;
    
    /*
     * 用户对应角色集合
     */
    private Set<Role> roleSet;
    
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public Set<Role> getRoleSet() {
        return roleSet;
    }
    public void setRoleSet(Set<Role> roleSet) {
        this.roleSet = roleSet;
    }
    
    
}
View Code

 

Role.java

package com.classic.entity;

import java.util.Set;

public class Role {
    
    private Long id;
    private String roleCode;
    
    /**
     * 角色对应权限集合
     */
    private Set<Permission> permissionSet;
    
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getRoleCode() {
        return roleCode;
    }
    public void setRoleCode(String roleCode) {
        this.roleCode = roleCode;
    }
    public Set<Permission> getPermissionSet() {
        return permissionSet;
    }
    public void setPermissionSet(Set<Permission> permissionSet) {
        this.permissionSet = permissionSet;
    }
    
}
View Code

 

Permission.java

package com.classic.entity;

public class Permission {
    
    private Long id;
    private String permissionCode;
    
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getPermissionCode() {
        return permissionCode;
    }
    public void setPermissionCode(String permissionCode) {
        this.permissionCode = permissionCode;
    }
    
    
}
View Code

 

AbstractDao.java

package com.classic.commons;

/**
 * 一些规定的dao层接口
 * @author ...
 *
 */
public abstract class AbstractDao {
    
    
    
}
View Code

 

configure包

DemoExceptionHandler.java

package com.classic.configure;

import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 异常捕捉类
 */
@ControllerAdvice
public class DemoExceptionHandler {

    private static Logger logger = LoggerFactory.getLogger(DemoExceptionHandler.class);
    
    @ExceptionHandler
    @ResponseBody
    public String unauthenticatedExceptionHandler(UnauthenticatedException e) {
        logger.warn(e.getMessage(), e);
        return "用户名或密码错误";
    }
    
    @ExceptionHandler
    @ResponseBody
    public String unauthorizedExceptionHandler(UnauthorizedException e) {
        logger.warn(e.getMessage(), e);
        return "权限不足";
    }
    
    @ExceptionHandler
    @ResponseBody
    public String exceptionHandler(Exception e) {
        logger.error(e.getMessage(), e);
        return "未知异常";
    }
    
}
View Code

 

ExceptionMessageType.java

package com.classic.configure;

public enum ExceptionMessageType {
    
    AUTHENTICATION_EXCEPTION,
    AUTHORIZATION_EXCEPTION,
    UNAUTHENTICATED_EXCEPTION,    // 账号密码错误
    UNAUTHORIZED_EXCEPTION    // 权限不足
    
}
View Code

 

RedisConfig.java

package com.classic.configure;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;

@Configuration
public class RedisConfig {
    
    @Bean
//    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, DefaultTyping.NON_FINAL, As.PROPERTY);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
    
}
View Code

 

ShiroConfig.java

package com.classic.configure;

import java.util.HashMap;
import java.util.Map;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.classic.realm.UserRealm;

@Configuration
public class ShiroConfig {
    
    @Autowired
    private UserRealm userRealm;
    
    /**
     * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions)
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可实现此功能
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator daapc = new DefaultAdvisorAutoProxyCreator();
        daapc.setProxyTargetClass(true);
        return daapc;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
    
    //权限管理,配置主要是Realm的管理认证
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        return securityManager;
    }
    
  //Filter工厂,设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, String> map = new HashMap<>();
        //登出
        map.put("/logout", "logout");
        //对所有用户认证
        map.put("/**", "authc");
        // 如果未登录这跳转登录
        shiroFilterFactoryBean.setLoginUrl("/user/login");
        //首页
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //错误页面,认证不通过跳转
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

}
View Code

 

realm包

UserRealm.java

package com.classic.realm;

import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.classic.entity.Permission;
import com.classic.entity.Role;
import com.classic.entity.User;
import com.classic.service.UserService;

@Component
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;
    
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Object primaryPrincipal = principals.getPrimaryPrincipal();
        if (primaryPrincipal == null) {
            return null;
        }
        String principal = primaryPrincipal.toString();
        User user = userService.queryUserByUsername(principal);
        if (user == null) {
            return null;
        }
        SimpleAuthorizationInfo sai = new SimpleAuthorizationInfo();
        Set<Role> roleSet = user.getRoleSet();
        if (roleSet != null && roleSet.size() > 0) {
            for (Role role : roleSet) {
                // 添加角色
                sai.addRole(role.getRoleCode());
                // 添加权限
                Set<Permission> permissionSet = role.getPermissionSet();
                if (permissionSet != null && permissionSet.size() > 0) {
                    for (Permission permission : permissionSet) {
                        sai.addStringPermission(permission.getPermissionCode());
                    }
                }
            }
        }
        return sai;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //加这一步的目的是在Post请求的时候会先进认证,然后在到请求
        Object principalObj = token.getPrincipal();
        if (principalObj == null) {
            return null;
        }
        //获取用户信息
        String principal = principalObj.toString();
        User user = userService.queryUserByUsername(principal);
        if (user == null) {
            //这里返回后会报出对应异常
            return null;
        } else {
            //这里验证authenticationToken和simpleAuthenticationInfo的信息
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, user.getPassword().toString(), getName());
            return simpleAuthenticationInfo;
        }
    }

}
View Code

 

util包

RedisUtil.java

package com.classic.util;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

/**
 * Redis工具类
 */
@Component
public final class RedisUtil {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    // =============================common============================
    /**
     * 指定缓存失效时间
     * @param key 键
     * @param time 时间(秒)
     * @return
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key 获取过期时间
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     * @param key 可以传一个值 或多个
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

    // ============================String=============================
    /**
     * 普通缓存获取
     * @param key 键
     * @return*/
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     * @param key 键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    /**
     * 普通缓存放入并设置时间
     * @param key 键
     * @param value 值
     * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 递增
     * @param key 键
     * @param delta 要增加几(大于0)
     * @return
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 递减
     * @param key 键
     * @param delta 要减少几(小于0)
     * @return
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递减因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }

    // ================================Map=================================
    /**
     * HashGet
     * @param key 键 不能为null
     * @param item 项 不能为null
     * @return*/
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * 获取hashKey对应的所有键值
     * @param key 键
     * @return 对应的多个键值
     */
    public Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet
     * @param key 键
     * @param map 对应多个键值
     * @return true 成功 false 失败
     */
    public boolean hmset(String key, Map<String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet 并设置时间
     * @param key 键
     * @param map 对应多个键值
     * @param time 时间(秒)
     * @return true成功 false失败
     */
    public boolean hmset(String key, Map<String, Object> map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     * @param key 键
     * @param item 项
     * @param value 值
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     * @param key 键
     * @param item 项
     * @param value 值
     * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除hash表中的值
     * @param key 键 不能为null
     * @param item 项 可以使多个 不能为null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    /**
     * 判断hash表中是否有该项的值
     * @param key 键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
     * @param key 键
     * @param item 项
     * @param by 要增加几(大于0)
     * @return
     */
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    /**
     * hash递减
     * @param key 键
     * @param item 项
     * @param by 要减少记(小于0)
     * @return
     */
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }

    // ============================set=============================
    /**
     * 根据key获取Set中的所有值
     * @param key 键
     * @return
     */
    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据value从一个set中查询,是否存在
     * @param key 键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将数据放入set缓存
     * @param key 键
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 将set数据放入缓存
     * @param key 键
     * @param time 时间(秒)
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取set缓存的长度
     * @param key 键
     * @return
     */
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值为value的
     * @param key 键
     * @param values 值 可以是多个
     * @return 移除的个数
     */
    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    // ===============================list=================================

    /**
     * 获取list缓存的内容
     * @param key 键
     * @param start 开始
     * @param end 结束 0 到 -1代表所有值
     * @return
     */
    public List<Object> lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取list缓存的长度
     * @param key 键
     * @return
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 通过索引 获取list中的值
     * @param key 键
     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
     * @return
     */
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     * @return
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     * @return
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     * 
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据索引修改list中的某条数据
     * @param key 键
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 移除N个值为value
     * @param key 键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}
View Code

 

dao层

UserMapper.java

package com.classic.dao;

import java.util.List;

import org.apache.ibatis.annotations.Select;

import com.classic.entity.User;

public interface UserMapper {
    
    @Select("select * from user")
    List<User> queryAll();
    
    @Select(
            "select id,username,password from user "
            + "where username = #{username}"
            )
    User queryUserByUsername(String username);
    
}
View Code

 

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.classic.dao.UserMapper">
   
    <!-- <select id="queryAll" resultType="com.classic.entity.User">
        select * from user
    </select> -->
    
</mapper>
View Code

 

RoleMapper.java

package com.classic.dao;

import java.util.Set;

import org.apache.ibatis.annotations.Select;

import com.classic.entity.Role;

public interface RoleMapper {
    
    Set<Role> queryRolesByIds(Set<Long> ids);

    @Select("select role_id from user_role where user_id=#{userId}")
    Set<Long> queryRoleIdsByUserId(Long userId);
    
    
}
View Code

 

RoleMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.classic.dao.RoleMapper">
       
       <sql id="selectAllColumnSql">
               select id,role_code roleCode from role
       </sql>
       
    <select id="queryRolesByIds" resultType="com.classic.entity.Role">
        <include refid="selectAllColumnSql" />
        where id in 
        <foreach collection="ids" item="id" index="index" open="(" close=")" separator=",">
                #{id}
        </foreach>
    </select>
    
</mapper>
View Code

 

PermissionMapper.java

package com.classic.dao;

import java.util.Set;

import org.apache.ibatis.annotations.Select;

import com.classic.entity.Permission;

public interface PermissionMapper {
    
    Set<Permission> queryPermissionsByIds(Set<Integer> ids);
    
    @Select("select permission_id from role_to_permission where role_id=#{roleId}")
    Set<Integer> queryPermissionIdsByRoleId(Long roleId);
    
}
View Code

 

PermissionMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.classic.dao.PermissionMapper">
       
       <sql id="selectAllColumnSql">
               select id,permission_code permissionCode from permission
       </sql>
       
    <select id="queryPermissionsByIds" resultType="com.classic.entity.Permission">
        <include refid="selectAllColumnSql"/>
        where id in 
        <foreach collection="ids" item="id" index="index" open="(" close=")" separator=",">
                #{id}
        </foreach>
    </select>
    
</mapper>
View Code

 

service层

UserService.java

package com.classic.service;

import java.util.List;

import com.classic.entity.User;

public interface UserService {

    List<User> queryAll();
    
    User queryUserByUsername(String username);
    
}
View Code

 

UserServiceImp.java

package com.classic.service;

import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.classic.dao.UserMapper;
import com.classic.entity.Role;
import com.classic.entity.User;

@Service
public class UserServiceImp implements UserService {

    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private RoleService roleService;
    
    @Override
    public List<User> queryAll() {
        return userMapper.queryAll();
    }

    @Override
    public User queryUserByUsername(String username) {
        User user = userMapper.queryUserByUsername(username);
        if (user != null) {
            Long userId = user.getId();
            Set<Role> roleSet = roleService.queryRolesByUserId(userId);
            user.setRoleSet(roleSet);
        }
        return user;
    }
    
}
View Code

 

RoleService.java

package com.classic.service;

import java.util.Set;

import com.classic.entity.Role;

public interface RoleService {
    
    Set<Role> queryRolesByUserId(Long userId);
    
}
View Code

 

RoleServiceImpl.java

package com.classic.service;

import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.classic.dao.RoleMapper;
import com.classic.entity.Role;

@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleMapper roleMapper;
    
    @Autowired
    private PermissionService permissionService;
    
    @Override
    public Set<Role> queryRolesByUserId(Long userId) {
        Set<Long> ids = roleMapper.queryRoleIdsByUserId(userId);
        if (ids != null && ids.size() > 0) {
            Set<Role> roleSet = roleMapper.queryRolesByIds(ids);
            if (roleSet != null && roleSet.size() > 0) {
                for (Role role : roleSet) {
                    Long roleId = role.getId();
                    role.setPermissionSet(permissionService.queryPermissionsByRoleId(roleId));
                }
            }
            return roleSet;
        }
        return null;
    }
    
}
View Code

 

PermissionService.java

package com.classic.service;

import java.util.Set;

import com.classic.entity.Permission;

public interface PermissionService {
    
    Set<Permission> queryPermissionsByRoleId(Long roleId);
    
}
View Code

 

PermissionServiceImpl.java

package com.classic.service;

import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.classic.dao.PermissionMapper;
import com.classic.entity.Permission;

@Service
public class PermissionServiceImpl implements PermissionService {

    @Autowired
    private PermissionMapper permissionMapper;
    
    @Override
    public Set<Permission> queryPermissionsByRoleId(Long roleId) {
        Set<Integer> ids = permissionMapper.queryPermissionIdsByRoleId(roleId);
        if (ids != null && ids.size() > 0) {
            return permissionMapper.queryPermissionsByIds(ids);
        }
        return null;
    }

}
View Code

 

Controller层(仅提供测试接口)

UserController.java

package com.classic.controller;

import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.classic.entity.User;
import com.classic.service.UserService;

@RestController
@RequestMapping("/user")
public class UserController {

    private static final Logger logger = LoggerFactory.getLogger(UserController.class);
    
    @Autowired
    private UserService userService;
    
    @GetMapping("/queryAll")
    public List<User> queryAll() {
        return userService.queryAll();
    }
    
    @GetMapping("/queryByUsername")
    public User queryByUsername(String username) {
        return userService.queryUserByUsername(username);
    }
    
    @RequestMapping("/login")
    public String userLogin(User user) {
        //添加用户认证信息
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = 
                new UsernamePasswordToken(user.getUsername(), user.getPassword());
        try {
            //进行验证,这里可以捕获异常,然后返回对应信息
            subject.login(usernamePasswordToken);
//            subject.checkRole("ADMIN");
//            subject.checkPermissions("query", "add");
        } catch (AuthenticationException e) {
            logger.error(e.getMessage(), e);
            return "账号或密码错误!";
        } catch (AuthorizationException e) {
            logger.error(e.getMessage(), e);
            return "没有权限";
        }
        return "登录成功";
    }
    
    @RequestMapping("/index")
    @RequiresRoles(value={"ADMIN","USER"},logical = Logical.OR)
    @RequiresPermissions(value={"query"},logical = Logical.OR)
    public String indexTest() {
        return "Index";
    }
    
    @RequestMapping("/logout")
    public String userLogout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "登出成功";
    }
    
}
View Code

 

 

参考链接:

https://www.jianshu.com/p/7f724bec3dc3

和权限的话无法捕捉异常,从而无法正确的返回给前端错误信息,所以我加了一个类用于拦截异常,具体代码如下
posted @ 2020-07-22 17:52    阅读(244)  评论(0编辑  收藏  举报