springboot mybatis redis shiro 許可權控制(springboot模組化使用,後臺程式碼已經完成)

瘋狂的楊中仁發表於2018-04-27

springboot mybatis redis shiro 許可權控制(springboot模組化使用,後臺程式碼已經完成)

配置檔案 以及 module建立

1、新建parent maven專案,編寫 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.vuix</groupId>
    <artifactId>vuixparent</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <modules>
        <module>service</module>
        <module>bts</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>1.8.4</version>
        </dependency>

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

        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
            <version>1.9.22</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.44</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.2.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.2.4</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-cas</artifactId>
            <version>1.2.4</version>
        </dependency>
    </dependencies>


</project>

2、新建service module maven專案,編寫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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>vuixparent</artifactId>
        <groupId>com.vuix</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>service</artifactId>

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

</project>

3、新建bts module maven工程 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>vuixparent</artifactId>
        <groupId>com.vuix</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>bts</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.vuix</groupId>
            <artifactId>service</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

    </dependencies>


</project>

4、在應用 bts 下面resources 下面新建 application.yml

server:
  port: 8888
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db_vuix
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
  redis:
    database: 0
    password:
    port: 6379
    host: 127.0.0.1
    pool:
      max-active: 8
      max-wait: 10
      max-idle: 8
      min-idle: 0
  thymeleaf:
      cache: false
      mode: LEGACYHTML5

mybatis:
  config-location: classpath:mybatis-config.xml
  type-aliases-package: com.vuix.dao.entity
  mapper-locations: classpath:mapper/*.xml

下面是mapper.xml配合和應用程式碼

## mybatis-config.xml 程式碼如下 ##
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 引數設定 -->
    <settings>
        <!--&lt;!&ndash; 這個配置使全域性的對映器啟用或禁用快取 &ndash;&gt;-->
        <!--<setting name="cacheEnabled" value="true" />-->
        <!--&lt;!&ndash; 全域性啟用或禁用延遲載入。當禁用時,所有關聯物件都會即時載入 &ndash;&gt;-->
        <!--<setting name="lazyLoadingEnabled" value="true" />-->
        <!--&lt;!&ndash; 當啟用時,有延遲載入屬性的物件在被呼叫時將會完全載入任意屬性。否則,每種屬性將會按需要載入 &ndash;&gt;-->
        <!--<setting name="aggressiveLazyLoading" value="true" />-->
        <!--&lt;!&ndash; 允許或不允許多種結果集從一個單獨的語句中返回(需要適合的驅動) &ndash;&gt;-->
        <!--<setting name="multipleResultSetsEnabled" value="true" />-->
        <!--&lt;!&ndash; 使用列標籤代替列名。不同的驅動在這方便表現不同。參考驅動文件或充分測試兩種方法來決定所使用的驅動 &ndash;&gt;-->
        <!--<setting name="useColumnLabel" value="true" />-->
        <!--&lt;!&ndash; 允許JDBC支援生成的鍵。需要適合的驅動。如果設定為true則這個設定強制生成的鍵被使用,儘管一些驅動拒絕相容但仍然有效(比如Derby) &ndash;&gt;-->
        <!--<setting name="useGeneratedKeys" value="true" />-->
        <!--&lt;!&ndash; 指定MyBatis如何自動對映列到欄位/屬性。PARTIAL只會自動對映簡單,沒有巢狀的結果。FULL會自動對映任意複雜的結果(巢狀的或其他情況) &ndash;&gt;-->
        <!--<setting name="autoMappingBehavior" value="PARTIAL" />-->
        <!--&lt;!&ndash;當檢測出未知列(或未知屬性)時,如何處理,預設情況下沒有任何提示,這在測試的時候很不方便,不容易找到錯誤。-->
        <!--NONE : 不做任何處理 (預設值)-->
        <!--WARNING : 警告日誌形式的詳細資訊-->
        <!--FAILING : 對映失敗,丟擲異常和詳細資訊-->
        <!--&ndash;&gt;-->
        <!--<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>-->
        <!--&lt;!&ndash; 配置預設的執行器。SIMPLE執行器沒有什麼特別之處。REUSE執行器重用預處理語句。BATCH執行器重用語句和批量更新 &ndash;&gt;-->
        <!--<setting name="defaultExecutorType" value="SIMPLE" />-->
        <!--&lt;!&ndash; 設定超時時間,它決定驅動等待一個資料庫響應的時間 &ndash;&gt;-->
        <!--<setting name="defaultStatementTimeout" value="25000" />-->
        <!--&lt;!&ndash;設定查詢返回值數量,可以被查詢數值覆蓋  &ndash;&gt;-->
        <!--<setting name="defaultFetchSize" value="100"/>-->
        <!--&lt;!&ndash; 允許在巢狀語句中使用分頁&ndash;&gt;-->
        <!--<setting name="safeRowBoundsEnabled" value="false"/>-->
        <!--&lt;!&ndash;是否開啟自動駝峰命名規則(camel case)對映,即從經典資料庫列名 A_COLUMN 到經典 Java 屬性名 aColumn 的類似對映。&ndash;&gt;-->
        <!--<setting name="mapUnderscoreToCamelCase" value="false"/>-->
        <!--&lt;!&ndash;MyBatis 利用本地快取機制(Local Cache)防止迴圈引用(circular references)和加速重複巢狀查詢。 預設值為 SESSION,這種情況下會快取一個會話中執行的所有查詢。 若設定值為 STATEMENT,本地會話僅用在語句執行上,對相同 SqlSession 的不同呼叫將不會共享資料。&ndash;&gt;-->
        <!--<setting name="localCacheScope" value="SESSION"/>-->
        <!--&lt;!&ndash; 當沒有為引數提供特定的 JDBC 型別時,為空值指定 JDBC 型別。 某些驅動需要指定列的 JDBC 型別,多數情況直接用一般型別即可,比如 NULL、VARCHAR-->
        <!--OTHER。&ndash;&gt;-->
        <!--<setting name="jdbcTypeForNull" value="OTHER"/>-->
        <!--&lt;!&ndash; 指定哪個物件的方法觸發一次延遲載入。&ndash;&gt;-->
        <!--<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>-->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>

    <!-- 別名定義 -->
    <!--<typeAliases>-->
        <!--<typeAlias alias="pageAccessURL" type="com.lgm.mybatis.model.PageAccessURL" />-->
    <!--</typeAliases>-->

    <!--自定義型別處理器 -->
    <!--<typeHandlers>-->
        <!--&lt;!&ndash; <typeHandler handler="com.xhm.util.BooleanTypeHandlder" /> &ndash;&gt;-->
        <!--&lt;!&ndash;掃描整個包下的自定義型別處理器&ndash;&gt;-->
        <!--<package name="com.xhm.util"/>-->
    <!--</typeHandlers>-->

    <!--plugins外掛之 分頁攔截器  -->
    <!--<plugins>-->
        <!---->
    <!--</plugins>-->
</configuration>

業務程式碼的mapper.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.vuix.dao.mapper.MenuMapper" >
    <resultMap id="BaseResultMap" type="com.vuix.dao.entity.MenuEntity" >
        <id column="id" property="id" />
        <result column="name" property="name" />
        <result column="icon" property="icon"/>
        <result column="parent_id" property="parentId" />
        <result column="is_delete" property="isDelete" />
        <result column="url" property="url"/>
        <result column="created_time" property="createdTime" />
        <result column="update_time" property="updateTime"/>
    </resultMap>

    <select id="queryByPrimarykey" resultMap="BaseResultMap">
        select * from xx_menu where is_delete = 0 and id = #{id}
    </select>

    <select id="findListByParentId" resultMap="BaseResultMap" parameterType="long">
        select * from xx_menu where parent_id = #{parentId}
    </select>

</mapper>

<?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.vuix.dao.mapper.SysPermissionMapper" >
    <resultMap id="BaseResultMap" type="com.vuix.dao.entity.SysPermission" >
        <id column="id" property="id" />
        <result column="available" property="available" />
        <result column="name" property="name"/>
        <result column="parent_id" property="parentId" />
        <result column="parent_ids" property="parentIds"/>
        <result column="permission" property="permission" />
        <result column="resource_type" property="resourceType"/>
        <result column="url" property="url" />
    </resultMap>

    <select id="findListByRoleId" resultMap="BaseResultMap" parameterType="long">
        select * from sys_permission where id in (select permission_id from sys_role_permission where role_id = #{roleId})
    </select>

    <select id="queryAll" resultMap="BaseResultMap" >
        select * from sys_permission
    </select>

</mapper>

<?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.vuix.dao.mapper.SysRoleMapper" >
    <resultMap id="BaseResultMap" type="com.vuix.dao.entity.SysRole" >
        <id column="id" property="id" />
        <result column="available" property="available" />
        <result column="description" property="description"/>
        <result column="role" property="role" />
    </resultMap>

    <select id="findListByUid" resultMap="BaseResultMap" parameterType="long">
        select * from sys_role where id in (select role_id from sys_user_role where uid = #{uid})
    </select>

</mapper>

<?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.vuix.dao.mapper.TeampleMapper" >
    <resultMap id="BaseResultMap" type="com.vuix.dao.entity.TeampleEntity" >
        <id column="id" property="id" />
        <result column="user_name" property="userName" />
        <result column="password" property="password"/>
        <result column="phone" property="phone" />
    </resultMap>

    <select id="queryByPrimarykey" resultMap="BaseResultMap">
        select * from xx_teample where id = #{id}
    </select>
    
    <select id="queryAll" resultMap="BaseResultMap">
        select * from xx_teample order by id desc
    </select>

</mapper>

<?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.vuix.dao.mapper.UserInfoMapper" >

    <resultMap id="BaseResultMap" type="com.vuix.dao.entity.UserInfo">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="name" column="name"/>
        <result property="password" column="password"/>
        <result property="salt" column="salt"/>
        <result property="state" column="state"/>
    </resultMap>

    <select id="findByUsername" parameterType="string" resultMap="BaseResultMap">
        select * from user_info where username = #{username}
    </select>

</mapper>

下面是java類


## entity 類##
package com.vuix.dao;

import com.alibaba.fastjson.JSON;

import java.io.Serializable;

public class ABaseEntity implements Serializable{

    private Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }
}

package com.vuix.dao.entity;

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

public class UserInfo implements Serializable{

    private Long uid;

    private String username;

    private String name;

    private String password;

    private String salt;

    private int state;

    private List<SysRole> roleList;

    public List<SysRole> getRoleList() {
        return roleList;
    }

    public void setRoleList(List<SysRole> roleList) {
        this.roleList = roleList;
    }

    public Long getUid() {
        return uid;
    }

    public void setUid(Long uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    /**
     * 密碼鹽.
     * @return
     */
    public String getCredentialsSalt(){
        return this.username+this.salt;
    }
}

package com.vuix.dao.entity;

import com.vuix.dao.ABaseEntity;

public class TeampleEntity extends ABaseEntity {

    private String userName;

    private String password;

    private String phone;

    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 String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}


package com.vuix.dao.entity;

import java.io.Serializable;

public class SysUserRole implements Serializable {

    private Long roleId;

    private Long uid;

    public Long getRoleId() {
        return roleId;
    }

    public void setRoleId(Long roleId) {
        this.roleId = roleId;
    }

    public Long getUid() {
        return uid;
    }

    public void setUid(Long uid) {
        this.uid = uid;
    }
}


package com.vuix.dao.entity;

import java.io.Serializable;

public class SysRolePermission implements Serializable{

    private Long permissionId;

    private Long roleId;

    public Long getPermissionId() {
        return permissionId;
    }

    public void setPermissionId(Long permissionId) {
        this.permissionId = permissionId;
    }

    public Long getRoleId() {
        return roleId;
    }

    public void setRoleId(Long roleId) {
        this.roleId = roleId;
    }
}


package com.vuix.dao.entity;

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

public class SysRole implements Serializable {

    private Long id;

    private Integer available;

    private String description;

    private String role;

    private List<SysPermission> permissions;



    public List<SysPermission> getPermissions() {
        return permissions;
    }

    public void setPermissions(List<SysPermission> permissions) {
        this.permissions = permissions;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Integer getAvailable() {
        return available;
    }

    public void setAvailable(Integer available) {
        this.available = available;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }
}

package com.vuix.dao.entity;

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

public class SysPermission implements Serializable {

    private Long id;

    private Integer available;

    private String name;

    private Long parentId;

    private String parentIds;

    private String permission;

    private String resourceType;

    private String url;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Integer getAvailable() {
        return available;
    }

    public void setAvailable(Integer available) {
        this.available = available;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getParentId() {
        return parentId;
    }

    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }

    public String getParentIds() {
        return parentIds;
    }

    public void setParentIds(String parentIds) {
        this.parentIds = parentIds;
    }

    public String getPermission() {
        return permission;
    }

    public void setPermission(String permission) {
        this.permission = permission;
    }

    public String getResourceType() {
        return resourceType;
    }

    public void setResourceType(String resourceType) {
        this.resourceType = resourceType;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

package com.vuix.dao.entity;

import com.vuix.dao.ABaseEntity;

import java.util.Date;
import java.util.List;

public class MenuEntity extends ABaseEntity {

    private String name;

    private String icon;

    private Long parentId;

    private Integer isDelete;

    private String url;

    private Date createdTime;

    private Date updateTime;

    private boolean isHasMenu = false;

    public boolean isHasMenu() {
        return isHasMenu;
    }

    public void setHasMenu(boolean hasMenu) {
        isHasMenu = hasMenu;
    }

    private List<MenuEntity> list;

    public List<MenuEntity> getList() {
        return list;
    }

    public void setList(List<MenuEntity> list) {
        this.list = list;
    }

    public Integer getIsDelete() {
        return isDelete;
    }

    public void setIsDelete(Integer isDelete) {
        this.isDelete = isDelete;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }

    public Long getParentId() {
        return parentId;
    }

    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public Date getCreatedTime() {
        return createdTime;
    }

    public void setCreatedTime(Date createdTime) {
        this.createdTime = createdTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}

## mapper 類 ##

package com.vuix.dao;

import java.util.List;

public interface IBaseMapper<T extends ABaseEntity> {

    // 增加
    Long insert(T entity);

    // 修改
    void update(T entity);

    // 刪除
    void deleteByPrimarykey(Long id);

    // 查詢單個物件
    T queryByPrimarykey(Long id);

    // 分頁查詢
    List<T> queryByPager(APagerEntity<T> pagerEntity);

    // 查詢所有的
    List<T> queryAll();

}

package com.vuix.dao;

public class APagerEntity<T extends ABaseEntity> {

    // 條件
    private T entity;

    public APagerEntity(){
        super();
    }

    private int index; // 當前頁碼

    private int isStart = 0; // 開始值  entity 下面不得有這些條件

    private int isLength = 10; // 大小 entity 下面不得有這些條件

    public T getEntity() {
        return entity;
    }

    public void setEntity(T entity) {
        this.entity = entity;
    }

    public int getIndex() {
        if (index <= 0) {
            index = 1;
        }
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public int getIsStart() {
        isStart = (getIndex() - 1 ) * getIsLength();
        return isStart;
    }

    public void setIsStart(int isStart) {
        this.isStart = isStart;
    }

    public int getIsLength() {
        return isLength;
    }

    public void setIsLength(int isLength) {
        this.isLength = isLength;
    }
}

package com.vuix.dao.mapper;

import com.vuix.dao.entity.UserInfo;
import org.apache.ibatis.annotations.Param;

public interface UserInfoMapper {

    // 使用者名稱查詢 userInfo
    UserInfo findByUsername(@Param("username") String username);

}

package com.vuix.dao.mapper;

import com.vuix.dao.IBaseMapper;
import com.vuix.dao.entity.TeampleEntity;

public interface TeampleMapper extends IBaseMapper<TeampleEntity> {
}

package com.vuix.dao.mapper;

import com.vuix.dao.entity.SysRole;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface SysRoleMapper {

    // 查詢使用者許可權
    List<SysRole> findListByUid(@Param("uid") Long uid);
}


package com.vuix.dao.mapper;

import com.vuix.dao.entity.SysPermission;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface SysPermissionMapper {

    List<SysPermission> findListByRoleId(@Param("roleId") Long roleId);

    List<SysPermission> queryAll();
    
}


package com.vuix.dao.mapper;

import com.vuix.dao.IBaseMapper;
import com.vuix.dao.entity.MenuEntity;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface MenuMapper extends IBaseMapper<MenuEntity> {

    List<MenuEntity> findListByParentId(@Param("parentId") Long parentId);

}


## util 類 ##

package com.vuix.util;

public class VuixUtil {

    public static boolean isNull(String value) {
        if (value == null || value.trim().equals("") || value.length() == 0){
            return true;
        }
        return false;
    }

    public static boolean isNotNull(String value) {
        return !isNull(value);
    }


}

## service類##

package com.vuix.service;

import com.alibaba.fastjson.JSON;
import com.vuix.util.VuixUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.List;

/**
 * @Cacheable    表明在Spring呼叫之前,首先應該在快取中查詢方法的返回值,
 *              如果這個值能夠找到,就會返回快取的值,
 *              否則這個方法會被呼叫,返回值會放到快取中
 *
 * @CachePut    表明Spring應該將該方法返回值放到快取中,在方法呼叫前不會檢查快取,方法始終會被呼叫
 *
 * @CacheEvict    表明Spring應該在快取中清楚一個或多個條目
 *
 * @Caching    分組註解,能夠同時應用多個其他的快取註解
 *
 * @CacheConfig    可以在類層級配置一些共有的快取配置
 *
 * @Cacheable和@CachePut有一些共有的屬性:
 *
 *      屬性    型別    描述
 *      value    String[]    快取名稱
 *      condition    SpEL表示式,如果得到的值是false,則不會應用快取在該方法
 *      key    String    SpEl表示式,用來計算自定義的快取key
 *      unless    String    SpEl表示式,如果得到的值為true,返回值不會放到快取中
 *
 */
public abstract class ABaseService {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    protected static final String root_symbol = ":";

    // 預設儲存時間
    protected static final Long default_millisecond = 24 * 60 * 60 * 1000L;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    protected String generalRedisKey(String... parameters) {
        StringBuffer stringBuffer = new StringBuffer();
        if (parameters.length > 0) {
            for (String parameter : parameters) {
                stringBuffer.append(parameter).append(root_symbol);
            }
        }
        if (stringBuffer.length() > 0) {
            return stringBuffer.toString().substring(0,stringBuffer.length()-1);
        }
        return null;
    }

    protected void removeCache(String key) {
        if (VuixUtil.isNotNull(key)){
            stringRedisTemplate.delete(key);
        }
    }

    protected <T>List<T> getListCache(String key,Class<T> targetClass) {
        if (VuixUtil.isNotNull(key)) {
            String value = stringRedisTemplate.opsForValue().get(key);
            logger.info("ABaseService getListCache:value:{}",value);
            if (VuixUtil.isNotNull(value)){
                List<T> targets = JSON.parseArray(value,targetClass);
                return targets;
            }
        }
        return null;
    }

    // get快取
    protected <T> T getFormCache(String key,Class<T> targetClass) {
        if (VuixUtil.isNotNull(key)) {
            String value = stringRedisTemplate.opsForValue().get(key);
            if (VuixUtil.isNotNull(value)){
                logger.info("ABaseService getFormCache:value:{}",value);
                T target = JSON.parseObject(value,targetClass);
                return target;
            }
        }
        return null;
    }

    // 放進快取
    protected void putCache(String key,Object object) {
        putCache(key,object,default_millisecond);
    }

    protected void putCache(String key,Object object,Long millisecond) {
        if (object != null) {
            String value = JSON.toJSONString(object);
            logger.info("ABaseService putCache:value:{}",value);
            stringRedisTemplate.opsForValue().set(key,value,millisecond);
        }
    }

}


package com.vuix.service;

public interface RootNamespace {

    String root_namespace = "root";

    String root_symbol = ":";

}


package com.vuix.service;

import com.vuix.dao.entity.MenuEntity;

import java.util.List;

public interface MenuService extends RootNamespace {

    List<MenuEntity> findList(Long parentId);

}


package com.vuix.service;

import com.vuix.dao.entity.SysPermission;

import java.util.List;

public interface SysPermissionService extends RootNamespace{

    String class_name = "sysPermission";

    List<SysPermission> findListByRoleId(Long roleId);

    // 查詢全部的許可權
    List<SysPermission> queryAll();
}

package com.vuix.service;

import com.vuix.dao.entity.SysRole;

import java.util.List;

public interface SysRoleService extends RootNamespace {

    String class_name = "sysRole";

    List<SysRole> findListByUid(Long uid);
}


package com.vuix.service;

import com.vuix.dao.entity.TeampleEntity;

import java.util.List;

public interface TeampleService extends RootNamespace {

    String class_name = "teample";

    TeampleEntity queryByPrimarykey(Long id);

    List<TeampleEntity> queryAll();

    void update(TeampleEntity entity);

    Long insert(TeampleEntity entity);

}


package com.vuix.service;

import com.vuix.dao.entity.UserInfo;

public interface UserInfoService extends RootNamespace{

    String class_name = "userInfo";

    UserInfo findByUsername(String username);

}


## service impl 類 ###
package com.vuix.service.impl;

import com.vuix.dao.entity.MenuEntity;
import com.vuix.dao.mapper.MenuMapper;
import com.vuix.service.ABaseService;
import com.vuix.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class MenuServiceImpl extends ABaseService implements MenuService{

    @Autowired
    private MenuMapper menuMapper;

    @Override
    public List<MenuEntity> findList(Long parentId) {
        if (parentId == null) {
            parentId = 0L;
        }
        // 加入redis 快取  做兩級選單  後期有的話  使用遞迴
        List<MenuEntity> list = menuMapper.findListByParentId(parentId);
        for (MenuEntity menu : list) {
            List<MenuEntity> list2 = menuMapper.findListByParentId(menu.getId());
            if ( list2 != null && list2.size() > 0) {
                menu.setHasMenu(true);
                menu.setList(list2);
            }
        }
        return list;
    }
}

package com.vuix.service.impl;

import com.vuix.dao.entity.SysPermission;
import com.vuix.dao.mapper.SysPermissionMapper;
import com.vuix.service.ABaseService;
import com.vuix.service.SysPermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class SysPermissionServiceImpl extends ABaseService implements SysPermissionService {

    @Autowired
    private SysPermissionMapper sysPermissionMapper;

    @Override
    public List<SysPermission> findListByRoleId(Long roleId) {
//        String key = generalRedisKey(root_namespace,class_name,"roleId",roleId.toString());
//        List<SysPermission> list = getListCache(key,SysPermission.class);
//        if (list == null) {
//            list = sysPermissionMapper.findListByRoleId(roleId);
//            putCache(key,list);
//        }
        return sysPermissionMapper.findListByRoleId(roleId);
    }

    @Override
    public List<SysPermission> queryAll() {
        return sysPermissionMapper.queryAll();
    }
}

package com.vuix.service.impl;

import com.vuix.dao.entity.SysRole;
import com.vuix.dao.mapper.SysRoleMapper;
import com.vuix.service.ABaseService;
import com.vuix.service.SysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class SysRoleServiceImpl extends ABaseService implements SysRoleService {

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Override
    public List<SysRole> findListByUid(Long uid) {
//        String key = generalRedisKey(root_namespace,class_name,"uid",uid.toString());
//        List<SysRole> list = getListCache(key,SysRole.class);
//        if (list == null) {
//            list = sysRoleMapper.findListByUid(uid);
//            putCache(key,list);
//        }
        return sysRoleMapper.findListByUid(uid);
    }
}


package com.vuix.service.impl;

import com.vuix.dao.entity.TeampleEntity;
import com.vuix.dao.mapper.TeampleMapper;
import com.vuix.service.ABaseService;
import com.vuix.service.TeampleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class TeampleServiceImpl extends ABaseService implements TeampleService {

    @Autowired
    private TeampleMapper teampleMapper;

    @Override
    public TeampleEntity queryByPrimarykey(Long id) {
        String key = generalRedisKey(root_namespace,class_name,id.toString());
        TeampleEntity result = getFormCache(key,TeampleEntity.class);
        if (result == null) {
            result = teampleMapper.queryByPrimarykey(id);
            putCache(key,result);
        }
        return result;
    }

    @Override
    public List<TeampleEntity> queryAll() {
        List<TeampleEntity> list = teampleMapper.queryAll();
        return list;
    }

    @Override
    public void update(TeampleEntity entity) {

    }

    @Override
    public Long insert(TeampleEntity entity) {
        return null;
    }
}


package com.vuix.service.impl;

import com.vuix.dao.entity.SysPermission;
import com.vuix.dao.entity.SysRole;
import com.vuix.dao.entity.UserInfo;
import com.vuix.dao.mapper.UserInfoMapper;
import com.vuix.service.ABaseService;
import com.vuix.service.SysPermissionService;
import com.vuix.service.SysRoleService;
import com.vuix.service.UserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserInfoServiceImpl extends ABaseService implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysPermissionService sysPermissionService;

    @Override
    public UserInfo findByUsername(String username) {
        // 查詢redis下面的值
//        String key = generalRedisKey(root_namespace,class_name,"username",username);
//        UserInfo userInfo = getFormCache(key,UserInfo.class);
//        if (userInfo == null) {
            // 資料庫處理業務
            UserInfo userInfo = userInfoMapper.findByUsername(username);
            // 放入快取
//            putCache(key,userInfo);
//        }
        // 查詢許可權
        List<SysRole> sysRoles = sysRoleService.findListByUid(userInfo.getUid());
        // 給sysRole物件  賦值許可權
        for (SysRole sysRole : sysRoles) {
            List<SysPermission> sysPermissions = sysPermissionService.findListByRoleId(sysRole.getId());
            sysRole.setPermissions(sysPermissions);
        }
        userInfo.setRoleList(sysRoles);
        return userInfo;
    }
}

下面是bts下面controller包下面的java類

package com.vuix.bts;

import com.vuix.dao.entity.UserInfo;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public abstract class ABaseController {

    protected final Logger logger = LoggerFactory.getLogger(ABaseController.class);


    protected UserInfo getCurrentUserInfo(){
        UserInfo userInfo = (UserInfo) SecurityUtils.getSubject().getPrincipal();
        return userInfo;
    }

    /**
     * springMVC 獲取requset
     *
     * @return
     */
    public HttpServletRequest getRequest() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
        return request;
    }

    /**
     * 獲取response
     *
     * @return
     */
    public HttpServletResponse getResponse() {
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getResponse();
        return response;
    }

    /**
     * 獲取session
     *
     * @return
     */
    public HttpSession getSession() {
        HttpSession session = this.getRequest().getSession();
        return session;
    }

    /**
     * 獲取ServletContext
     *
     * @return
     */
    public ServletContext getServletContent() {
        // ServletContext application= request.getServletContext();

        WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
        ServletContext servletContext = webApplicationContext.getServletContext();
        return servletContext;
    }

    /**
     * 獲取ModelAndView
     *
     * @return
     */
    public ModelAndView getModelAndView() {
        return new ModelAndView();
    }

    public ModelAndView get404ModelAndView() {
        ModelAndView view = new ModelAndView();
        view.setViewName("404");
        return view;
    }

    /**
     * 獲取ip
     *
     * @return
     */
    public String getRemortIP() {
        HttpServletRequest request = this.getRequest();
        String ip = "";
        if (request.getHeader("x-forwarded-for") == null) {
            ip = request.getRemoteAddr();
        } else {
            ip = request.getHeader("x-forwarded-for");
        }
        return ip;
    }

    /**
     * 獲取port
     *
     * @return
     */
    public int getPort() {
        return this.getRequest().getServerPort();
    }

    /**
     * 獲取ip
     *
     * @return
     */
    public String getIpAddr() {
        HttpServletRequest request = this.getRequest();
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}


package com.vuix.bts.controller;


import com.alibaba.fastjson.JSON;
import com.vuix.bts.ABaseController;
import com.vuix.dao.entity.MenuEntity;
import com.vuix.dao.entity.UserInfo;
import com.vuix.service.MenuService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.Map;

@Controller
public class IndexController extends ABaseController{

    @Autowired
    private MenuService menuService;

    @RequestMapping({"/","/index"})
    public String index(Model model) {
        // 載入選單樹
        List<MenuEntity> menuList = menuService.findList(null);
        // 獲取登入使用者的詳細
        UserInfo userInfo = getCurrentUserInfo();

        logger.info("IndexController index:  userInfo:{}", JSON.toJSONString(userInfo));
        model.addAttribute("userInfo",userInfo);
        model.addAttribute("menuList",menuList);
        return"/index";
    }

    @RequestMapping(value = "logout")
    public String logout(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        //跳轉登陸頁面
        return "login";
    }

    @RequestMapping("/login")
    public String login(HttpServletRequest request, Map<String, Object> map) throws Exception{
        logger.info("HomeController.login()");
        // 登入失敗從request中獲取shiro處理的異常資訊。
        // shiroLoginFailure:就是shiro異常類的全類名.
        String exception = (String) request.getAttribute("shiroLoginFailure");
        logger.info("exception:{}",exception);
        String msg = "";
        if (exception != null) {
            if (UnknownAccountException.class.getName().equals(exception)) {
                logger.error("UnknownAccountException -- > 賬號不存在:");
                msg = "UnknownAccountException -- > 賬號不存在:";
            } else if (IncorrectCredentialsException.class.getName().equals(exception)) {
                logger.error("IncorrectCredentialsException -- > 密碼不正確:");
                msg = "IncorrectCredentialsException -- > 密碼不正確:";
            } else if ("kaptchaValidateFailed".equals(exception)) {
                logger.error("kaptchaValidateFailed -- > 驗證碼錯誤");
                msg = "kaptchaValidateFailed -- > 驗證碼錯誤";
            } else {
                msg = "else >> "+exception;
                logger.error("else -- >" + exception);
            }
        }
        map.put("msg", msg);
        // 此方法不處理登入成功,由shiro進行處理
        return "/login";
    }

    @RequestMapping("/403")
    public String unauthorizedRole(){
        logger.info("------沒有許可權-------");
        return "403";
    }


}

package com.vuix.bts.controller;

import com.vuix.bts.ABaseController;
import com.vuix.dao.entity.MenuEntity;
import com.vuix.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
@RequestMapping(value = "menu")
public class MenuController extends ABaseController{

    @Autowired
    private MenuService menuService;

    @RequestMapping(value = "list")
    public String list(Model model) {
        List<MenuEntity> list = menuService.findList(null);
        model.addAttribute("list",list);
        return "page/menu/list";
    }

}


package com.vuix.bts.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class PageController {

    private static final Logger logger = LoggerFactory.getLogger(PageController.class);

    @RequestMapping("/include/{pageName}")
    public String include(@PathVariable("pageName") String pageName){
        logger.info("PageController include : /include/"+pageName);
        return "include/"+pageName;
    }

}

package com.vuix.bts.controller;

import com.vuix.bts.ABaseController;
import com.vuix.dao.entity.TeampleEntity;
import com.vuix.service.TeampleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
@RequestMapping(value = "teample")
public class TeampleController extends ABaseController{

    @Autowired
    private TeampleService teampleService;

    @RequestMapping(value = "list")
    public String list(Model model) {
        List<TeampleEntity> list = teampleService.queryAll();
        model.addAttribute("list",list);
        return "page/teample/list";
    }
}


package com.vuix.bts.controller;


import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/userInfo")
public class UserInfoController {

    /**
     * 使用者查詢.
     * @return
     */
    @RequestMapping("/userList")
    @RequiresPermissions("userInfo:view")//許可權管理;
    public String userInfo(){
        return "userInfo";
    }

    /**
     * 使用者新增;
     * @return
     */
    @RequestMapping("/userAdd")
    @RequiresPermissions("userInfo:add")//許可權管理;
    public String userInfoAdd(){
        return "userInfoAdd";
    }

    /**
     * 使用者刪除;
     * @return
     */
    @RequestMapping("/userDel")
    @RequiresPermissions("userInfo:del")//許可權管理;
    public String userDel(){
        return "userInfoDel";
    }

    @RequestMapping("/userEdit")
    @RequiresPermissions("userInfo:edit")//許可權管理;
    public String userEdit(){
        return "userInfoEdit";
    }

}

## bts Config類 ##
package com.vuix.bts.config;

import com.alibaba.fastjson.JSON;
import com.vuix.dao.entity.SysPermission;
import com.vuix.dao.entity.SysRole;
import com.vuix.dao.entity.UserInfo;
import com.vuix.service.UserInfoService;
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.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

public class LoginShiroRealm extends AuthorizingRealm {

    private static final Logger logger = LoggerFactory.getLogger(LoginShiroRealm.class);

    @Autowired
    private UserInfoService userInfoService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        logger.info("許可權配置-->MyShiroRealm.doGetAuthorizationInfo()");
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        UserInfo userInfo  = (UserInfo)principals.getPrimaryPrincipal();
        for(SysRole role:userInfo.getRoleList()){
            authorizationInfo.addRole(role.getRole());
            for(SysPermission p:role.getPermissions()){
                authorizationInfo.addStringPermission(p.getPermission());
            }
        }
        return authorizationInfo;
    }

    /*主要是用來進行身份認證的,也就是說驗證使用者輸入的賬號和密碼是否正確。*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {
        logger.info("LoginShiroRealm.doGetAuthenticationInfo()");
        //獲取使用者的輸入的賬號.
        String username = (String)token.getPrincipal();
        logger.info("token.getCredentials() : str:{}", JSON.toJSONString(token.getCredentials()));
        //通過username從資料庫中查詢 User物件,如果找到,沒找到.
        //實際專案中,這裡可以根據實際情況做快取,如果不做,Shiro自己也是有時間間隔機制,2分鐘內不會重複執行該方法
        UserInfo userInfo = userInfoService.findByUsername(username);
        logger.info("----->>userInfo={}",JSON.toJSONString(userInfo));
        if(userInfo == null){
            return null;
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                userInfo, //使用者名稱
                userInfo.getPassword(), //密碼
                ByteSource.Util.bytes(userInfo.getCredentialsSalt()),//salt=username+salt
                getName()  //realm name
        );
        return authenticationInfo;
    }

}

package com.vuix.bts.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import java.lang.reflect.Method;

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{

//    @Bean
//    public KeyGenerator keyGenerator() {
//        return new KeyGenerator() {
//            @Override
//            public Object generate(Object target, Method method, Object... params) {
//                StringBuilder sb = new StringBuilder();
//                sb.append(target.getClass().getSimpleName());
//                sb.append(method.getName());
//                for (Object obj : params) {
//                    sb.append(obj.toString());
//                }
//                return sb.toString();
//            }
//        };
//    }

    @SuppressWarnings("rawtypes")
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate);
        //設定快取過期時間
        //rcm.setDefaultExpiration(60);//秒
        return redisCacheManager;
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(redisConnectionFactory);
        return stringRedisTemplate;
    }

}

package com.vuix.bts.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class SessionConfig {
}

package com.vuix.bts.config;

import com.vuix.dao.entity.SysPermission;
import com.vuix.service.SysPermissionService;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

@Configuration
public class ShiroConfig {

    private static final Logger logger = LoggerFactory.getLogger(ShiroConfig.class);

    @Autowired
    private SysPermissionService sysPermissionService;

    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        logger.info("ShiroConfiguration.shirFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //攔截器.
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
        // 配置不會被攔截的連結 順序判斷
        filterChainDefinitionMap.put("/bower_components/**", "anon");
        filterChainDefinitionMap.put("/dist/**", "anon");
        filterChainDefinitionMap.put("/images/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/plugins/**", "anon");
        filterChainDefinitionMap.put("/ztree/**", "anon");
        //配置退出 過濾器,其中的具體的退出程式碼Shiro已經替我們實現了
        filterChainDefinitionMap.put("/logout", "logout");
        //<!-- 過濾鏈定義,從上向下順序執行,一般將/**放在最為下邊 -->:這是一個坑呢,一不小心程式碼就不好使了;
        //<!-- authc:所有url都必須認證通過才可以訪問; anon:所有url都都可以匿名訪問-->

        List<SysPermission> sysPermissions = sysPermissionService.queryAll();
        for (SysPermission sysPermission : sysPermissions) {
            filterChainDefinitionMap.put("/" + sysPermission.getUrl(), "perms["+sysPermission.getPermission()+"]");
        }
        filterChainDefinitionMap.put("/**", "authc");
        // 如果不設定預設會自動尋找Web工程根目錄下的"/login.jsp"頁面
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登入成功後要跳轉的連結
        shiroFilterFactoryBean.setSuccessUrl("/index");

        //未授權介面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 憑證匹配器
     * (由於我們的密碼校驗交給Shiro的SimpleAuthenticationInfo進行處理了
     * )
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");//雜湊演算法:這裡使用MD5演算法;
        hashedCredentialsMatcher.setHashIterations(2);//雜湊的次數,比如雜湊兩次,相當於 md5(md5(""));
        return hashedCredentialsMatcher;
    }

    @Bean
    public LoginShiroRealm loginShiroRealm(){
        LoginShiroRealm loginShiroRealm = new LoginShiroRealm();
        loginShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return loginShiroRealm;
    }


    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        securityManager.setRealm(loginShiroRealm());
        return securityManager;
    }

    /**
     *  開啟shiro aop註解支援.
     *  使用代理方式;所以需要開啟程式碼支援;
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean(name="simpleMappingExceptionResolver")
    public SimpleMappingExceptionResolver
    createSimpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
        Properties mappings = new Properties();
        mappings.setProperty("DatabaseException", "databaseError");//資料庫異常處理
        mappings.setProperty("UnauthorizedException","403");
        r.setExceptionMappings(mappings);  // None by default
        r.setDefaultErrorView("error");    // No default
        r.setExceptionAttribute("ex");     // Default is "exception"
        //r.setWarnLogCategory("example.MvcLogger");     // No default
        return r;
    }
}

啟動類 BtsMainApplication


package com.vuix;

import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.vuix.dao.mapper")
public class BtsMainApplication {

    private static final Logger logger = LoggerFactory.getLogger(BtsMainApplication.class);

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

        logger.info("BtsMainApplication main running...");
    }
}
下面附上對應的sql

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 50537
Source Host           : localhost:3306
Source Database       : db_vuix

Target Server Type    : MYSQL
Target Server Version : 50537
File Encoding         : 65001

Date: 2018-04-27 15:37:24
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `sys_permission`
-- ----------------------------
DROP TABLE IF EXISTS `sys_permission`;
CREATE TABLE `sys_permission` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `available` int(10) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `parent_id` int(11) DEFAULT NULL,
  `parent_ids` varchar(255) DEFAULT NULL,
  `permission` varchar(255) DEFAULT NULL,
  `resource_type` varchar(255) DEFAULT NULL,
  `url` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_permission
-- ----------------------------
INSERT INTO `sys_permission` VALUES (`1`, `0`, `使用者管理`, `0`, `0/`, `userInfo:view`, `menu`, `userInfo/userList`);
INSERT INTO `sys_permission` VALUES (`2`, `0`, `使用者新增`, `1`, `0/1`, `userInfo:add`, `button`, `userInfo/userAdd`);
INSERT INTO `sys_permission` VALUES (`3`, `0`, `使用者刪除`, `1`, `0/1`, `userInfo:del`, `button`, `userInfo/userDel`);

-- ----------------------------
-- Table structure for `sys_role`
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `available` int(10) DEFAULT NULL,
  `description` varchar(255) DEFAULT NULL,
  `role` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES (`1`, `0`, `管理員`, `admin`);
INSERT INTO `sys_role` VALUES (`2`, `0`, `VIP會員`, `vip`);
INSERT INTO `sys_role` VALUES (`3`, `1`, `test`, `test`);

-- ----------------------------
-- Table structure for `sys_role_permission`
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_permission`;
CREATE TABLE `sys_role_permission` (
  `permission_id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_role_permission
-- ----------------------------
INSERT INTO `sys_role_permission` VALUES (`1`, `1`);
INSERT INTO `sys_role_permission` VALUES (`2`, `1`);
INSERT INTO `sys_role_permission` VALUES (`3`, `2`);

-- ----------------------------
-- Table structure for `sys_user_role`
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
  `role_id` int(11) NOT NULL,
  `uid` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES (`1`, `1`);

-- ----------------------------
-- Table structure for `user_info`
-- ----------------------------
DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `password` varchar(255) NOT NULL,
  `salt` varchar(255) DEFAULT NULL,
  `state` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user_info
-- ----------------------------
INSERT INTO `user_info` VALUES (`1`, `admin`, `管理員`, `d3c59d25033dbf980d29554025c23a75`, `8d78869f470951332959580424d4bf4f`, `0`);
INSERT INTO `user_info` VALUES (`2`, `yang`, `VIP`, `d3c59d25033dbf980d29554025c23a75`, `8d78869f470951332959580424d4bf4f`, `0`);

-- ----------------------------
-- Table structure for `xx_menu`
-- ----------------------------
DROP TABLE IF EXISTS `xx_menu`;
CREATE TABLE `xx_menu` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `icon` varchar(255) DEFAULT NULL,
  `parent_id` int(11) DEFAULT NULL,
  `is_delete` int(2) DEFAULT `0` COMMENT `是否刪除  0:未刪除 1:刪除`,
  `url` varchar(255) DEFAULT NULL,
  `created_time` datetime DEFAULT NULL,
  `update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of xx_menu
-- ----------------------------
INSERT INTO `xx_menu` VALUES (`1`, `系統管理`, `fa fa-gears`, `0`, `0`, `#`, `2018-04-13 14:54:36`, `2018-04-13 15:35:19`);
INSERT INTO `xx_menu` VALUES (`2`, `選單管理`, `fa fa-gears`, `1`, `0`, `menu/list`, `2018-04-13 14:55:12`, `2018-04-13 15:33:59`);
INSERT INTO `xx_menu` VALUES (`3`, `模板自定義`, `fa fa-gears`, `1`, `0`, `teample/list`, `2018-04-13 16:46:48`, `2018-04-13 16:46:50`);

-- ----------------------------
-- Table structure for `xx_teample`
-- ----------------------------
DROP TABLE IF EXISTS `xx_teample`;
CREATE TABLE `xx_teample` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `phone` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of xx_teample
-- ----------------------------
INSERT INTO `xx_teample` VALUES (`1`, `yang_zhongren`, `123456`, `15261811115`);
INSERT INTO `xx_teample` VALUES (`2`, `楊中仁`, `21121`, `18888888888`);

做了好幾年了 也不知道怎麼寫文章 多多包涵

案例下面的程式碼 直接複製貼上過來的 如果有何不懂的 可以直接在下面提問。

相關文章