SSM項目實戰 之 權限管理系統


目錄

SSM權限管理系統

項目搭建

1.創建Maven-webapp工程

2.SSM框架集成

2.1添加依賴,即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.itlike</groupId>
  <artifactId>PromissionPro</artifactId>
  <version>1.0</version>
  <packaging>war</packaging>

  <name>PromissionPro Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>

    <!--定義版本號   ${org.springframework.version}-->
    <org.springframework.version>5.0.7.RELEASE</org.springframework.version>
    <org.mybatis.version>3.4.6</org.mybatis.version>

  </properties>

  <dependencies>

    <!--單元測試-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <!--lombok-->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.6</version>
    </dependency>
    <!-- servlet-api -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <!--mysql驅動-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.21</version>
    </dependency>
    <!-- druid -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.0.14</version>
    </dependency>
    <!-- common-lang -->
    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.6</version>
    </dependency>
    <!--spring-test-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${org.springframework.version}</version>
      <scope>test</scope>
    </dependency>
    <!--spring-core-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <!--spring-context-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <!--spring-context-support-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <!--spring-expression-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-expression</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <!--spring-jdbc-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <!--spring-tx-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <!--spring-web-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <!--spring-aop-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <!--spring-webmvc-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>

    <!-- aspectj -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.7.4</version>
    </dependency>
    <!--aspectj weaver-->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.7.4</version>
    </dependency>

    <!-- cglib -->
    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.1</version>
    </dependency>

    <!-- mybatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${org.mybatis.version}</version>
    </dependency>
    <!--mybatis-spring-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.0</version>
    </dependency>

    <!-- jackson-core -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.4</version>
    </dependency>
    <!--jackson-databind-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.4</version>
    </dependency>
    <!--jackson-annotations-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.4</version>
    </dependency>

    <!--slf4j-api-->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.6</version>
    </dependency>
    <!--slf4j-log4j12-->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.6</version>
    </dependency>
    <!--log4j-->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    <!--commons-fileupload-->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <!-- jstl -->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <!-- standard -->
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>
    <!--pagehelper-->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>4.1.4</version>
    </dependency>

    <!--shiro-->
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-nop</artifactId>
      <version>1.7.24</version>
    </dependency>
    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>3.2.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.4.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-web</artifactId>
      <version>1.4.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-ehcache</artifactId>
      <version>1.4.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>1.4.0</version>
    </dependency>

    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>4.0.1</version>
    </dependency>
  </dependencies>

  <build>
    <finalName>PromissionPro</finalName>
    <plugins>
      <plugin>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-maven-plugin</artifactId>
        <version>1.3.2</version>
        <configuration>
          <verbose>true</verbose>
          <overwrite>false</overwrite>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.21</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

2.2添加配置文件

db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/promission?characterEncoding=utf-8
jdbc.username=root
jdbc.password=1234

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
     http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
">
    <!--注解掃描-->
    <context:component-scan base-package="com.itlike"/>
    <!--導入mybatis-->
    <import resource="classpath:application-mybatis.xml"/>
    <!--導入springMVC-->
    <import resource="classpath:application-mvc.xml"/>
    <!--導入shiro-->
    <import resource="classpath:application-shiro.xml"/>
    <!-- aop配置 日志配置 -->
    <bean id="SystemAspect" class="com.itlike.aspect.SystemAspect"></bean>

    <aop:config>
        <aop:pointcut expression="execution(* com.itlike.service.*.*(..))" id="servicePoint" />
        <aop:aspect ref="SystemAspect">
            <aop:after method="writeLog" pointcut-ref="servicePoint"/>
        </aop:aspect>
    </aop:config>
</beans>

application-mvc.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd
	http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
	">

    <mvc:annotation-driven />
    <!--靜態資源處理 -->
    <mvc:default-servlet-handler/>
    <!--視圖解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp" />
    </bean>

    <!--配置攔截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/*"/>
            <bean class="com.itlike.interceptor.RequestInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

    <!--配置文件上傳解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize">
            <value>1040000</value>
        </property>
    </bean>
</beans>

application-mybatis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
     http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
">

    <!--spring-Mybatis整合-->
    <!--加載數據庫屬性文件-->
    <context:property-placeholder location="classpath:db.properties"/>
    <!--連接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init"
          destroy-method="close">
        <property name="initialSize" value="5"/>
        <property name="driverClassName" value="${jdbc.driver}" />
        <!--屬性文件當中的名稱不能和name名稱一樣-->
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />

    </bean>
    <!-- 配置事務管理器 -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 數據源 -->
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!-- 開啟注解事務 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- Mybatis的工廠 -->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 核心配置文件的位置 -->
        <property name="configLocation" value="classpath:sqlMapConfig.xml"/>
        <!--配置mapper映射文件的路徑-->
        <property name="mapperLocations" value="classpath:com.itlike.mapper/*Mapper.xml"/>
    </bean>

    <!-- 配置Mapper接口掃描 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" >
        <!-- 配置Mapper掃描包 -->
        <property name="basePackage" value="com.itlike.mapper" />
    </bean>
</beans>

2.3配置web.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0"
         metadata-complete="false">
  <absolute-ordering/>
  <display-name>web</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <!-- 攔截到所有請求,使用spring一個bean來進行處理 -->
  <filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <!-- 是否filter中的init和 destroy-->
    <init-param>
      <param-name>targetFilterLifecycle</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>


  <!--配置前端控制器-->
  <servlet>
    <servlet-name>SpringMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <!--加載的主配置文件-->
      <param-value>classpath:applicationContext.xml</param-value>
    </init-param>
    <!-- 項目啟動就加載框架 -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>SpringMVC</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!-- 編碼過濾器 -->
  <filter>
    <filter-name>CharacterEncoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>utf-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncoding</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

3.添加代碼生成器

添加代碼生成器插件pom依賴

<plugin>
	<groupId>org.mybatis.generator</groupId>
	<artifactId>mybatis-generator-maven-plugin</artifactId>
	<version>1.3.2</version>
	<configuration>
	  <verbose>true</verbose>
	  <overwrite>false</overwrite>
	</configuration>
	<dependencies>
	  <dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.1.21</version>
	  </dependency>
	</dependencies>
</plugin>

添加代碼生成器配置文件,即generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<!-- 配置生成器 -->
<generatorConfiguration>
	<context id="mysql" defaultModelType="hierarchical"
		targetRuntime="MyBatis3Simple">

		<!-- 自動識別數據庫關鍵字,
		默認false,如果設置為true,
		根據SqlReservedWords中定義的關鍵字列表;
		一般保留默認值,
		遇到數據庫關鍵字(Java關鍵字),
		使用columnOverride覆蓋 -->
		<property name="autoDelimitKeywords" value="false" />
		<!-- 生成的Java文件的編碼 -->
		<property name="javaFileEncoding" value="UTF-8" />
		<!-- 格式化java代碼 -->
		<property name="javaFormatter"
			value="org.mybatis.generator.api.dom.DefaultJavaFormatter" />
		<!-- 格式化XML代碼 -->
		<property name="xmlFormatter"
			value="org.mybatis.generator.api.dom.DefaultXmlFormatter" />

		<!-- beginningDelimiter和endingDelimiter:指明數據庫的用於標記數據庫對象名的符號,
		比如ORACLE就是雙引號,MYSQL默認是`反引號; -->
		<property name="beginningDelimiter" value="`" />
		<property name="endingDelimiter" value="`" />

		<!--阻止生成日期和注釋-->
		<commentGenerator>
			<property name="suppressDate" value="true" />
			<property name="suppressAllComments" value="true" />
		</commentGenerator>

		<!-- 數據庫連接信息 -->
		<jdbcConnection driverClass="com.mysql.jdbc.Driver"
			connectionURL="jdbc:mysql:///employee" userId="root" password="123456">
		</jdbcConnection>

		<!-- java類型處理器 用於處理數據庫中的類型到Java中的類型,
			 默認使用JavaTypeResolverDefaultImpl;
			 注意一點,默認會先嘗試使用Integer,Long,Short等來對應DECIMAL和
			NUMERIC數據類型; -->
		<javaTypeResolver
			type="org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl">
			<!-- true:使用BigDecimal對應DECIMAL和 NUMERIC數據類型 f
				 alse:默認, scale>0;length>18:使用BigDecimal;
				scale=0;length[10,18]:使用Long; scale=0;length[5,9]:
				使用Integer; scale=0;length<5:使用Short; -->
			<property name="forceBigDecimals" value="false" />
		</javaTypeResolver>


		<!--
		配置domain生成策略
        targetProject:把自動生成的domian放在哪個工程里面
        targetPackage:哪個包下
		-->
		<javaModelGenerator targetPackage="com.itlike.domain"
			targetProject="src/main/java">
			<!-- for MyBatis3/MyBatis3Simple
			自動為每一個生成的類創建一個構造方法,
			構造方法包含了所有的field;而不是使用setter; -->
			<property name="constructorBased" value="false" />

			<!-- for MyBatis3 / MyBatis3Simple
			是否創建一個不可變的類,如果為true,
			那么MBG會創建一個沒有setter方法的類,
			取而代之的是類似constructorBased的類 -->
			<property name="immutable" value="false" />

			<!-- 設置是否在getter方法中,
			對String類型字段調用trim()方法 -->
			<property name="trimStrings" value="true" />
		</javaModelGenerator>

		<!--
            配置mapper.xml的生成策略
            targetPackage:把自動生成的mapper放在哪個工程里面
            targetProject:哪個包下
        -->
		<sqlMapGenerator targetPackage="com.itlike.mapper"
			targetProject="src/main/java">
			<!-- 在targetPackage的基礎上,
			根據數據庫的schema再生成一層package,
			最終生成的類放在這個package下,默認為false -->
			<property name="enableSubPackages" value="true" />
		</sqlMapGenerator>

		<!--
           mapper接口生成策略
        -->
		<javaClientGenerator targetPackage="com.itlike.mapper"
			type="XMLMAPPER" targetProject="src/main/java">
			<property name="enableSubPackages" value="true" />
		</javaClientGenerator>

		<table tableName="employee"></table>

	</context>
</generatorConfiguration>

創建員工表sql語句

CREATE TABLE `employee` (
  `id` bigint(20) NOT NULL,
  `username` varchar(50) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  `realname` varchar(50) DEFAULT NULL,
  `tel` varchar(50) DEFAULT NULL,
  `email` varchar(50) DEFAULT NULL,
  `inputtime` datetime DEFAULT NULL,
  `state` tinyint(1) DEFAULT NULL,
  `admin` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

生成員工mapper,雙擊maven插件

主頁搭建

EasyUI主頁

1.在目錄當中引入EasyUI相關JS與css

2.在首頁當中引入所需要的js與css

<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/static/plugins/easyui/uimaker/easyui.css">
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/static/plugins/easyui/uimaker/icon.css">
<script type="text/javascript" src="${pageContext.request.contextPath}/static/plugins/easyui/jquery.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/plugins/easyui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/plugins/easyui/easyui-lang-zh_CN.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/index.js"></script>

3.編寫body首頁框架格式

<body class="easyui-layout">
	<div data-options="region:'north'" style="height:100px; background: #ec4e00; padding: 20px 20px">
		<img src="main_logo.png" alt="">
	</div>
	<div data-options="region:'south'" style="height:50px; border-bottom: 3px solid #ec4e00">
		<p align="center" style="font-size: 14px">撩課學院</p>
	</div>
	<div data-options="region:'west',split:true" style="width:300px;">
		<div id="aa" class="easyui-accordion" data-options="fit:true">
			<div title="菜單" data-options="iconCls:'icon-save',selected:true" style="overflow:auto;padding:10px;">
				<!--tree-->
				<ul id="tree"></ul>
			</div>
			<div title="公告" data-options="iconCls:'icon-reload'" style="padding:10px;">
			</div>
		</div>
	</div>
	<div data-options="region:'center'" style="background:#eee;">
		<!--標簽-->
		<div id="tabs" style="overflow: hidden" >
		</div>
	</div>
</body>

4.創建首頁index.js引入

$(function () {
	$("#tabs").tabs({
		fit:true
	})
	$('#tree').tree({
		url:'/getTreeData',
		lines:true,
		onSelect: function(node){
			/*在添加之前, 做判斷  判斷這個標簽是否存在 */
			var exists =   $("#tabs").tabs("exists",node.text);
			if(exists){
				/*存在,就讓它選中*/
				$("#tabs").tabs("select",node.text);
			}else {
				if (node.url !=''&& node.url !=null){
					/*如果不存在 ,添加新標簽*/
					$("#tabs").tabs("add",{
						title:node.text,
						/*href:node.attributes.url,*/  /*href  引入的是body當中*/
						content:"<iframe src="+node.url+" frameborder='0' width='100%' height='100%'></iframe>",
						closable:true
					})
				}
			}
		},
		onLoadSuccess: function (node, data) {
			console.log(data[0].children[0].id);
			if (data.length > 0) {
				//找到第一個元素
				var n = $('#tree').tree('find', data[0].children[0].id);
				//調用選中事件
				$('#tree').tree('select', n.target);
			}
		}

	});
});

員工列表

1.在tree當中指定跳轉的地址--暫時用tree.json文件代替

[
  {
    "id": 1,
    "text": "系統管理",
    "children": [
      {
        "id":2,
        "text": "員工管理",
         "url": "/employee"
      },
      {
        "id":3,
        "text": "角色權限管理",
          "url": "/role"
      },
      {
        "id":4,
        "text": "菜單管理",
        "url": "/menu"

      }
    ]
  }
]
**index.js**
$(function () {
    $("#tabs").tabs({
        fit:true
    })
    $('#tree').tree({
        url:"static/tree.json",
        lines:true,
        onSelect: function(node){
            /*在添加之前, 做判斷  判斷這個標簽是否存在 */
            var exists =   $("#tabs").tabs("exists",node.text);
            if(exists){
                /*存在,就讓它選中*/
                $("#tabs").tabs("select",node.text);
            }else {
                if (node.url !=''&& node.url !=null){
                    /*如果不存在 ,添加新標簽*/
                    $("#tabs").tabs("add",{
                        title:node.text,
                        /*href:node.attributes.url,*/  /*href  引入的是body當中*/
                        content:"<iframe src="+node.url+" frameborder='0' width='100%' height='100%'></iframe>",
                        closable:true
                    })
                }
            }
        }
    });
});

2.創建頁面跳轉控制器,接收請求跳轉到Employee頁面

@Controller
public class PageLocation {
    @RequestMapping("/employee")
    public String employee(){
        return "employee";
    }

	@RequestMapping("/department")
    public String department(){
        return "department";
    }
}

3.在Employee頁面中引入公共的EasyUI相關js編寫數據表格

<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/employee.js"></script>

4.創建Employee.js引入設置-數據表格

數據加載

			**employee.js**
$(function () {
    /*員式數據列表*/
    $("#dg").datagrid({
        url:"/employeeList",
        columns:[[
            {field:'username',title:'姓名',width:100,align:'center'},
            {field:'inputtime',title:'入職時間',width:100,align:'center'},
            {field:'tel',title:'電話',width:100,align:'center'},
            {field:'email',title:'郵箱',width:100,align:'center'},
            {field:'department',title:'部門',width:100,align:'center',formatter: function(value,row,index){
                if (value){
                    return value.name;
                }
            }},
            {field:'state',title:'狀態',width:100,align:'center',formatter: function(value,row,index){
                    if(row.state){
                        return "在職";
                    }else {
                        return "<font style='color: red'>離職</font>"
                    }
                }},
            {field:'admin',title:'管理員',width:100,align:'center',formatter: function(value,row,index){
                    if(row.admin){
                        return "是";
                    }else {
                        return "否"
                    }
                }},
        ]],
        fit:true,
        fitColumns:true,
        rownumbers:true,
        pagination:true,
        singleSelect:true,
        striped:true,
        toolbar:"#tb",
        onClickRow:function (rowIndex,rowData) {
            /*判斷當前行是否是離職狀態*/
            if(!rowData.state){
                /*離職,把離職按鈕禁用*/
                $("#delete").linkbutton("disable");
            }else {
                /*離職,把離職按鈕啟用*/
                $("#delete").linkbutton("enable");
            }
        }
    });
})

控制層

@Controller
public class EmployeeController {
    /*注入業務層*/
    @Autowired
    private EmployeeService employeeService;

    @RequestMapping("/employee")
    public String employee(){
        return "employee";
    }

    @RequestMapping("/employeeList")
    @ResponseBody
    public PageListRes employeeList(QueryVo vo){
        System.out.println(vo);
        /*調用業務層查詢員工*/
        PageListRes pageListRes = employeeService.getEmployee(vo);
        return pageListRes;
    }
})

業務層

@Service
@Transactional
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    @Override
    public PageListRes getEmployee(QueryVo vo) {
        /*調用mapper 查詢員工 */
        Page<Object> page = PageHelper.startPage(vo.getPage(), vo.getRows());
        List<Employee> employees = employeeMapper.selectAll(vo);
        /*封裝成pageList*/
        PageListRes pageListRes = new PageListRes();
        pageListRes.setTotal(page.getTotal());
        pageListRes.setRows(employees);
        return pageListRes;
    }
})
		日期格式化
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date inputtime;

格式化狀態和管理員

5.創建部門表

建表語句

CREATE TABLE `department` (
	`id` bigint(20) NOT NULL,
	`name` varchar(10) DEFAULT NULL COMMENT '部門名稱 ',
	`sn` varchar(20) DEFAULT NULL COMMENT '部門編號',
	`manager_id` bigint(20) DEFAULT NULL,
	`parent_id` bigint(20) DEFAULT NULL,
	`state` tinyint(1) DEFAULT NULL,
	PRIMARY KEY (`id`),
	KEY `manager_id` (`manager_id`),
	KEY `parent_id` (`parent_id`),
	CONSTRAINT `department_ibfk_1` FOREIGN KEY (`manager_id`) REFERENCES `employee` (`id`),
	CONSTRAINT `department_ibfk_2` FOREIGN KEY (`parent_id`) REFERENCES `department` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

employee表添加字段dept_id

在代碼生成器當中生成相關domain和mapper

修改employee的domian

@Setter@Getter@ToString
public class Employee {
    private Long id;
    private String username;
    private String password;
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date inputtime;
    private String tel;
    private String email;
    private Boolean state;
    private Boolean admin;
    private Department department;
}

6.查詢部門

EmployeeMapper.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.itlike.mapper.EmployeeMapper" >
  <resultMap id="BaseResultMap" type="com.itlike.domain.Employee" >
    <id column="id" property="id" jdbcType="BIGINT" />
    <result column="username" property="username" jdbcType="VARCHAR" />
    <result column="inputtime" property="inputtime" jdbcType="TIMESTAMP" />
    <result column="tel" property="tel" jdbcType="VARCHAR" />
    <result column="email" property="email" jdbcType="VARCHAR" />
    <result column="state" property="state" jdbcType="BIT" />
    <result column="admin" property="admin" jdbcType="BIT" />

   <association property="department" javaType="com.itlike.domain.Department" columnPrefix="d_">
     <result property="id" column="id"/>
     <result property="name" column="name"/>
   </association>

  </resultMap>
  <!--員工關聯部門查詢-->
  <select id="selectAll" resultMap="BaseResultMap" >
    select
    e.id,
    e.username,
    e.inputtime,
    e.tel,
    e.email,
    e.state,
    e.admin,
    d.id as d_id,
    d.`name` as d_name
    from employee as e
    LEFT JOIN department as d
    ON e.dep_id = d.id
    <include refid="where_sql"/>
    order by e.id desc
  </select>
</mapper>

$(function () {
    /*員式數據列表*/
    $("#dg").datagrid({
        url:"/employeeList",
        columns:[[
            {field:'username',title:'姓名',width:100,align:'center'},
            {field:'inputtime',title:'入職時間',width:100,align:'center'},
            {field:'tel',title:'電話',width:100,align:'center'},
            {field:'email',title:'郵箱',width:100,align:'center'},
            {field:'department',title:'部門',width:100,align:'center',formatter: function(value,row,index){
                if (value){
                    return value.name;
                }
            }},
            {field:'state',title:'狀態',width:100,align:'center',formatter: function(value,row,index){
                    if(row.state){
                        return "在職";
                    }else {
                        return "<font style='color: red'>離職</font>"
                    }
                }},
            {field:'admin',title:'管理員',width:100,align:'center',formatter: function(value,row,index){
                    if(row.admin){
                        return "是";
                    }else {
                        return "否"
                    }
                }},
        ]]
    });
})

7.列表添加工具欄目

​ 1.添加標簽

<div id="tb">
    <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-add',plain:true" id="add">添加</a>
    <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-edit',plain:true" id="edit">編輯</a>
    <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-remove',plain:true" id="delete">刪除</a>
    <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-reload',plain:true" id="reload">刷新</a>
</div>

​ 2.處理Js

 toolbar: '#tb',

8.添加對話框彈出

對話框標簽

<table align="center" style="border-spacing: 0px 10px">
	<tr>
		<td>用戶名:</td>
		<td><input type="text" class="easyui-validatebox" data-options="required:true"></td>
	</tr>
	<tr>
		<td>真實姓名:</td>
		<td><input type="text" class="easyui-validatebox" data-options="required:true"></td>
	</tr>
	<tr>
		<td>手機:</td>
		<td><input type="text" class="easyui-validatebox" data-options="required:true"></td>
	</tr>
	<tr>
		<td>郵箱:</td>
		<td><input type="text" class="easyui-validatebox" data-options="required:true,validType:'email'" ></td>
	</tr>
	<tr>
		<td>入職日期:</td>
		<td><input type="text" class="easyui-datebox" required="required"></td>
	</tr>
	<tr>
		<td>部門:</td>
		<td><select id="department"></select></td>
	</tr>
	<tr>
		<td>是否管理員:</td>
		<td><select id="state"></select></td>
	</tr>
</table>

部門列表展示

/*部門選擇 下拉列表*/
$("#department").combobox({
    width:150,
    panelHeight:'auto',
    editable:false,
    url:'departList',
    textField:'name',
    valueField:'id',
    onLoadSuccess:function () { /*數據加載完畢之后回調*/
        $("#department").each(function(i){
            var span = $(this).siblings("span")[i];
            var targetInput = $(span).find("input:first");
            if(targetInput){
                $(targetInput).attr("placeholder", $(this).attr("placeholder"));
            }
        });
    }
});

設置placehode

$("#department").each(function(i){
	var span = $(this).siblings("span")[i];
	var targetInput = $(span).find("input:first");
	if(targetInput){
		$(targetInput).attr("placeholder", $(this).attr("placeholder"));
	}
});

是否管理員下拉列表展示

/*管理員下拉列表選擇*/
$("#state").combobox({
	width:150,
	panelHeight:'auto',
	textField:'label',
	valueField:'value',
	data:[{
		label:'是',
		value:'true'
	},{
		label:'否',
		value:'false'
	}]
});
$("#state").combobox({"select","否"});

9.保存

表單標簽上填寫name

<form id="employeeForm">
	<%--添加一個隱藏域  編輯--%>
	<input type="hidden" name="id">
	<table align="center" style="border-spacing: 0px 10px">
		<tr>
			<td>用戶名:</td>
			<td><input type="text" name="username" class="easyui-validatebox" data-options="required:true"></td>
		</tr>
		<tr id="password">
			<td>密碼:</td>
			<td><input type="text" name="password" class="easyui-validatebox"></td>
		</tr>
		<tr>
			<td>手機:</td>
			<td><input type="text" name="tel" class="easyui-validatebox" ></td>
		</tr>
		<tr>
			<td>郵箱:</td>
			<td><input type="text" name="email" class="easyui-validatebox" ></td>
		</tr>
		<tr>
			<td>入職日期:</td>
			<td><input type="text" name="inputtime" class="easyui-datebox"></td>
		</tr>
		<tr>
			<td>部門:</td>
			<td><input id="department" name="department.id" placeholder="請選擇部門"/></td>
		</tr>
		<tr>
			<td>是否管理員:</td>
			<td><input id="state" name="admin" placeholder="是否為管理員"/></td>
		</tr>
		<tr>
			<td>選擇角色:</td>
			<td><input id="role" name="role.rid" placeholder="請選擇角色"/></td>
		</tr>
	</table>
</form>

下拉列表設置默認值時, 默認value也要設置上去

保存時判斷添加還是編輯

監聽保存按鈕,提交表單

/*對話框*/
$("#dialog").dialog({
	width:350,
	height:400,
	closed:true,
	buttons:[{
		text:'保存',
		handler:function(){

			/*判斷當前是添加 還是編輯*/
			var id = $("[name='id']").val();
			var url;
			if(id){
				/*編輯*/
				url = "updateEmployee";
			}else {
				/*添加*/
				url= "saveEmployee";
			}

			/*提交表單*/
			$("#employeeForm").form("submit",{
				url:url,
				onSubmit:function(param){
					/*獲取選中的角色*/
				   var values =  $("#role").combobox("getValues");
				   for(var i = 0; i < values.length; i++){
					   var rid  =  values[i];
					   param["roles["+i+"].rid"] = rid;
				   }
				},
				success:function (data) {
				  data = $.parseJSON(data);
				  if (data.success){
					  $.messager.alert("溫馨提示",data.msg);
					  /*關閉對話框 */
					  $("#dialog").dialog("close");
					  /*重新加載數據表格*/
					  $("#dg").datagrid("reload");
				  } else {
					  $.messager.alert("溫馨提示",data.msg);
				  }
				}
			});
		}
	},{
		text:'關閉',
		handler:function(){
			$("#dialog").dialog("close");
		}
	}]
});

10.編輯

監聽編輯按鈕點擊

/*監聽編輯按鈕點擊*/
$("#edit").click(function () {
    /*獲取當前選中的行*/
    var rowData = $("#dg").datagrid("getSelected");
    console.log(rowData);
    if(!rowData){
        $.messager.alert("提示","選擇一行數據進行編輯");
        return;
    }
    /*取消密碼驗證*/
    $("[name='password']").validatebox({required:false});
    $("#password").hide();
    /*彈出對話框*/
    $("#dialog").dialog("setTitle","編輯員工");
    $("#dialog").dialog("open");
    /*回顯部門*/
    rowData["department.id"] = rowData["department"].id;
    /*回顯管理員*/
    rowData["admin"] = rowData["admin"]+"";
    /*回顯角色*/
    /*根據當前用戶的id,查出對應的角色*/
    $.get("/getRoleByEid?id="+rowData.id,function (data) {
        /*設置下拉列表數據回顯*/
        $("#role").combobox("setValues",data);
    });

    /*選中數據的回示*/
    $("#employeeForm").form("load",rowData);

});

更新業務邏輯

/*接收更新員工請求*/
@RequestMapping("/updateEmployee")
@ResponseBody
@RequiresPermissions("employee:edit")
public AjaxRes updateEmployee(Employee employee){
	AjaxRes ajaxRes = new AjaxRes();
	try {
		/*調用業務層,更新員工*/
		employeeService.updateEmployee(employee);
		ajaxRes.setMsg("更新成功");
		ajaxRes.setSuccess(true);
	}catch (Exception e){
		ajaxRes.setSuccess(false);
		ajaxRes.setMsg("更新失敗");
	}
	return ajaxRes;
}

11.離職

離職按鈕點擊

/*設置離職按鈕點擊*/
$("#delete").click(function () {
    /*獲取當前選中的行*/
    var rowData = $("#dg").datagrid("getSelected");
    console.log(rowData);
    if(!rowData){
        $.messager.alert("提示","選擇一行數據進行編輯");
        return;
    }
    /*提醒用戶,是否做離職操作*/
    $.messager.confirm("確認","是否做離職操作",function (res) {
       if(res){
           /*做離職操作*/
           $.get("/updateState?id="+rowData.id,function (data) {
               if (data.success){
                   $.messager.alert("溫馨提示",data.msg);
                   /*重新加載數據表格*/
                   $("#dg").datagrid("reload");
               } else {
                   $.messager.alert("溫馨提示",data.msg);
               }

           });
       }
    });
});

業務處理

/*接收離職操作請求*/
@RequestMapping("/updateState")
@ResponseBody
@RequiresPermissions("employee:delete")
public AjaxRes updateState(Long id){
    AjaxRes ajaxRes = new AjaxRes();
    try {
        /*調用業務層,設置員工離職狀態*/
        employeeService.updateState(id);
        ajaxRes.setMsg("更新成功");
        ajaxRes.setSuccess(true);
    }catch (Exception e){
        System.out.println(e);
        ajaxRes.setSuccess(false);
        ajaxRes.setMsg("更新失敗");
    }
    return ajaxRes;
}

12.離職按鈕禁用

給數據表格綁定選中事件

/*員式數據列表*/
$("#dg").datagrid({
    url:"/employeeList",
    columns:[[
        {field:'username',title:'姓名',width:100,align:'center'},
        {field:'inputtime',title:'入職時間',width:100,align:'center'},
        {field:'tel',title:'電話',width:100,align:'center'},
        {field:'email',title:'郵箱',width:100,align:'center'},
        {field:'department',title:'部門',width:100,align:'center',formatter: function(value,row,index){
            if (value){
                return value.name;
            }
        }},
        {field:'state',title:'狀態',width:100,align:'center',formatter: function(value,row,index){
                if(row.state){
                    return "在職";
                }else {
                    return "<font style='color: red'>離職</font>"
                }
            }},
        {field:'admin',title:'管理員',width:100,align:'center',formatter: function(value,row,index){
                if(row.admin){
                    return "是";
                }else {
                    return "否"
                }
            }},
    ]],
    fit:true,
    fitColumns:true,
    rownumbers:true,
    pagination:true,
    singleSelect:true,
    striped:true,
    toolbar:"#tb",
    onClickRow:function (rowIndex,rowData) {
        /*判斷當前行是否是離職狀態*/
        if(!rowData.state){
            /*離職,把離職按鈕禁用*/
            $("#delete").linkbutton("disable");
        }else {
            /*離職,把離職按鈕啟用*/
            $("#delete").linkbutton("enable");
        }
    }
});

添加按鈕js插件(記得是因為EasyUI帶有小bug)

base.js

/**
 * linkbutton方法擴展
 * @param {Object} jq
 */
$.extend($.fn.linkbutton.methods, {
    /**
     * 激活選項(覆蓋重寫)
     * @param {Object} jq
     */
    enable: function(jq){
        return jq.each(function(){
            var state = $.data(this, 'linkbutton');
           
            if ($(this).hasClass('l-btn-disabled')) {
                var itemData = state._eventsStore;
                //恢復超鏈接
                if (itemData.href) {
                    $(this).attr("href", itemData.href);
                }
                //回復點擊事件
                if (itemData.onclicks) {
                    for (var j = 0; j < itemData.onclicks.length; j++) {
                        $(this).bind('click', itemData.onclicks[j]);
                    }
                }
                //設置target為null,清空存儲的事件處理程序
                itemData.target = null;
                itemData.onclicks = [];
                $(this).removeClass('l-btn-disabled');
            }
        });
    },
    /**
     * 禁用選項(覆蓋重寫)
     * @param {Object} jq
     */
    disable: function(jq){
        return jq.each(function(){
            var state = $.data(this, 'linkbutton');
            if (!state._eventsStore)
                state._eventsStore = {};
            if (!$(this).hasClass('l-btn-disabled')) {
                var eventsStore = {};
                eventsStore.target = this;
                eventsStore.onclicks = [];
                //處理超鏈接
                var strHref = $(this).attr("href");
                if (strHref) {
                    eventsStore.href = strHref;
                    $(this).attr("href", "javascript:void(0)");
                }
                //處理直接耦合綁定到onclick屬性上的事件
                var onclickStr = $(this).attr("onclick");
                if (onclickStr && onclickStr != "") {
                    eventsStore.onclicks[eventsStore.onclicks.length] = new Function(onclickStr);
                    $(this).attr("onclick", "");
                }
                //處理使用jquery綁定的事件
                var eventDatas = $(this).data("events") || $._data(this, 'events');
                if (eventDatas["click"]) {
                    var eventData = eventDatas["click"];
                    for (var i = 0; i < eventData.length; i++) {
                        if (eventData[i].namespace != "menu") {
                            eventsStore.onclicks[eventsStore.onclicks.length] = eventData[i]["handler"];
                            $(this).unbind('click', eventData[i]["handler"]);
                            i--;
                        }
                    }
                }
                state._eventsStore = eventsStore;
                $(this).addClass('l-btn-disabled');
            }
        });
    }
});

13.分頁控制

EasyUI中可以自動的提交分頁參數直接接收分頁參數

@RequestMapping("/employeeList")
@ResponseBody
public PageListRes employeeList(QueryVo vo){
    System.out.println(vo);
    /*調用業務層查詢員工*/
    PageListRes pageListRes = employeeService.getEmployee(vo);
    return pageListRes;
}

業務處理

@Override
public PageListRes getEmployee(QueryVo vo) {
    /*調用mapper 查詢員工 */
    Page<Object> page = PageHelper.startPage(vo.getPage(), vo.getRows());
    List<Employee> employees = employeeMapper.selectAll(vo);
    /*封裝成pageList*/
    PageListRes pageListRes = new PageListRes();
    pageListRes.setTotal(page.getTotal());
    pageListRes.setRows(employees);
    return pageListRes;
}

14.高級查詢

在toolbar上添加搜索框

<input type="text" name="keyword" style="width: 200px; height: 30px;padding-left: 5px;">
<a class="easyui-linkbutton" iconCls="icon-search" id="searchbtn">查詢</a>

監聽搜索點擊

/*監聽搜索按鈕點擊*/
$("#searchbtn").click(function () {
    /*獲取搜索的內容*/
   var keyword =  $("[name='keyword']").val();
  /*重新加載列表  把參數keyword傳過去*/
    $("#dg").datagrid("load",{keyword:keyword});
});

接收參數處理

@Setter@Getter@ToString
public class QueryVo {
    private int page;
    private int rows;
    private String keyword;
}

@Override
public PageListRes getEmployee(QueryVo vo) {
    /*調用mapper 查詢員工 */
    Page<Object> page = PageHelper.startPage(vo.getPage(), vo.getRows());
    List<Employee> employees = employeeMapper.selectAll(vo);
    /*封裝成pageList*/
    PageListRes pageListRes = new PageListRes();
    pageListRes.setTotal(page.getTotal());
    pageListRes.setRows(employees);
    return pageListRes;
}

<sql id="where_sql">
	<where>
	   <if test="keyword !=null and keyword !=''">
		  and e.username like concat('%',#{keyword},'%')
		  or e.tel like concat('%',#{keyword},'%')
		  or e.email like concat('%',#{keyword},'%')
	   </if>
	</where>
</sql>

<!--員工關聯部門查詢-->
<select id="selectAll" resultMap="BaseResultMap" >
	select
	e.id,
	e.username,
	e.inputtime,
	e.tel,
	e.email,
	e.state,
	e.admin,
	d.id as d_id,
	d.`name` as d_name
	from employee as e
	LEFT JOIN department as d
	ON e.dep_id = d.id
	<include refid="where_sql"/>
	order by e.id desc
</select>

添加權限

1.建立角色與權限的表

為多對多關系

  • 角色表
CREATE TABLE `employee` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) DEFAULT NULL,
  `inputtime` datetime DEFAULT NULL,
  `tel` varchar(20) DEFAULT NULL,
  `email` varchar(50) DEFAULT NULL,
  `state` tinyint(1) DEFAULT NULL,
  `admin` tinyint(1) DEFAULT NULL,
  `dep_id` bigint(20) DEFAULT NULL,
  `password` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `dep_id` (`dep_id`),
  CONSTRAINT `employee_ibfk_1` FOREIGN KEY (`dep_id`) REFERENCES `department` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8;

  • 權限表
CREATE TABLE `permission` (
  `pid` bigint(20) NOT NULL,
  `pname` varchar(50) DEFAULT NULL,
  `presource` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`pid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  • 角色與權限中間表
CREATE TABLE `employee_role_rel` (
  `eid` bigint(20) NOT NULL,
  `rid` bigint(20) NOT NULL,
  PRIMARY KEY (`eid`,`rid`),
  KEY `rid` (`rid`),
  CONSTRAINT `employee_role_rel_ibfk_1` FOREIGN KEY (`eid`) REFERENCES `employee` (`id`),
  CONSTRAINT `employee_role_rel_ibfk_2` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

使用代碼生成器生成相關mapper

2.建立角色頁面

角色數據列表

<table id="emp_dg"></table>
<div id="toolbar">
	<a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-add',plain:true" id="add">添加</a>
	<a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-edit',plain:true" id="edit">編輯</a>
	<a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-remove',plain:true" id="remove">離職</a>
	<a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-reload',plain:true" id="reload">刷新</a>
</div>

添加角色權限對話框

<div id="dialog">
	<form id="myform">
		<table align="center" style="border-spacing: 20px 30px">
			<input type="hidden" name="id">
			<tr align="center">
				<td>角色編號: <input type="text" name="username" class="easyui-validatebox" ></td>
				<td>角色名稱: <input type="text" name="username" class="easyui-validatebox" ></td>
			</tr>
			<tr>
				<td><div id="role_data1"></div></td>
				<td><div id="role_data2"></div></td>
			</tr>
		</table>
	</form>
</div>

3.加載權限數據實現點擊添加權限,點擊刪除權限

/*角色數據列表*/
$("#role_dg").datagrid({
	url:"/getRoles",
	columns:[[
		{field:'rnum',title:'角色編號',width:100,align:'center'},
		{field:'rname',title:'角色名稱',width:100,align:'center'},
	]],
	fit:true,
	fitColumns:true,
	rownumbers:true,
	pagination:true,
	singleSelect:true,
	striped:true,
	toolbar:"#toolbar",
});

/*權限列表*/
$("#role_data1").datagrid({
	title:"所有權限",
	width:250,
	height:400,
	fitColumns:true,
	singleSelect:true,
	url:'/permissionList',
	columns:[[
		{field:'pname',title:'權限名稱',width:100,align:'center'},
	]],
	onClickRow:function (rowIndex,rowData) {/*點擊一行時,回調*/

		/*判斷是否已經存在該權限*/
		/*取出所有的已選權限*/
		var allRows = $("#role_data2").datagrid("getRows");
		/*取出每一個進行判斷*/
		for(var i = 0; i<allRows.length; i++){
			/*取出每一行*/
			var row = allRows[i];
			if(rowData.pid == row.pid){/*已經存在該權限*/
				/*讓已經存在權限成為選中的狀態*/
				/*獲取已經成為選中狀態當前角標*/
				var index = $("#role_data2").datagrid("getRowIndex",row);
				/*讓該行成為選中狀態*/
				$("#role_data2").datagrid("selectRow",index);
				return;
			}
		}

		/*把當前選中的,添加到已選權限*/
		$("#role_data2").datagrid("appendRow",rowData);
	}
});

/*選中權限列表*/
$("#role_data2").datagrid({
	title:"已選權限",
	width:250,
	height:400,
	singleSelect:true,
	fitColumns:true,
	columns:[[
		{field:'pname',title:'權限名稱',width:100,align:'center'},
	]],
	onClickRow:function (rowIndex,rowData) {
		/*刪除當中選中的一行*/
		$("#role_data2").datagrid("deleteRow",rowIndex);
	}
});

4.添加角色權限

定義角色權限關系:一個角色有多個權限

@Getter@Setter@ToString
public class Role {
    private Long rid;
    private String rnum;
    private String rname;

    /*一個角色可以有多個權限*/
    private List<Permission> permissions = new ArrayList<>();

}

點擊保存時,如果沒有隱藏字段id,則為添加操作

保存時, 參數傳遞;默認只傳遞input中的內容,還需要在提交表單時, 把添加的權限信息提交過去

/*添加/編輯對話框*/
$("#dialog").dialog({
    width:600,
    height:650,
    buttons:[{
        text:'保存',
        handler:function(){

            /*判斷當前是保存操作還是編輯操作*/
           var rid =  $("[name='rid']").val();
           var url;
           if(rid){
               /*編輯*/
               url="updateRole"
           }else {
               /*保存*/
               url="saveRole";
           }

            /*提交表單*/
            $("#myform").form("submit",{
                url:url,
                onSubmit:function(param){  /*傳遞額外參數  已選擇的權限*/

                    /*獲取已經選擇的權限*/
                   var allRows =  $("#role_data2").datagrid("getRows");
                   /*遍歷出每一個權限*/
                    for(var i = 0; i< allRows.length; i++){
                        /*取出每一個權限 */
                       var row =  allRows[i];
                       /*給它封裝到集合中*/
                        param["permissions["+i+"].pid"] = row.pid;
                    }

                },
                success:function (data) {
                    data = $.parseJSON(data);
                    if (data.success){
                        $.messager.alert("溫馨提示",data.msg);
                        /*關閉對話框 */
                        $("#dialog").dialog("close");
                        /*重新加載數據表格*/
                        $("#role_dg").datagrid("reload");
                    } else {
                        $.messager.alert("溫馨提示",data.msg);
                    }
                }
            });

        }
    },{
        text:'關閉',
        handler:function(){
            $("#dialog").dialog("close");
        }
    }],
    closed:true
});		

接收參數,保存角色與權限

/*接收  保存角色請求地址*/
@RequestMapping("/saveRole")
@ResponseBody
public AjaxRes saveRole(Role role){
    AjaxRes ajaxRes = new AjaxRes();
    try {
        /*調用業務層, 保存角色和權限*/
        roleService.saveRole(role);
        ajaxRes.setMsg("保存成功");
        ajaxRes.setSuccess(true);
    }catch (Exception e){
        ajaxRes.setSuccess(false);
        ajaxRes.setMsg("保存失敗");
    }
    return ajaxRes;

}

@Override
public void saveRole(Role role) {
    /*1.保存角色*/
    roleMapper.insert(role);
    /*2.保存角色與權限之間關系*/
    for (Permission permission : role.getPermissions()) {
        roleMapper.insertRoleAndPermissionRel(role.getRid(),permission.getPid());
    }

}

5.角色列表

/*角色數據列表*/
$("#role_dg").datagrid({
    url:"/getRoles",
    columns:[[
        {field:'rnum',title:'角色編號',width:100,align:'center'},
        {field:'rname',title:'角色名稱',width:100,align:'center'},
    ]],
    fit:true,
    fitColumns:true,
    rownumbers:true,
    pagination:true,
    singleSelect:true,
    striped:true,
    toolbar:"#toolbar",
});

6.編輯角色權限

編輯回顯

/*監聽編輯點擊*/
$("#edit").click(function () {
    /*獲取當前選中的行*/
    var rowData = $("#role_dg").datagrid("getSelected");
    console.log(rowData);
    if(!rowData){
        $.messager.alert("提示","選擇一行數據進行編輯");
        return;
    }

    /*加載當前角色下的權限*/
    var options =  $("#role_data2").datagrid("options");
    options.url = "/getPermissionByRid?rid="+rowData.rid;
    /*重新加載數據*/
    $("#role_data2").datagrid("load");

    /*選中數據的回示*/
    $("#myform").form("load",rowData);
    /*設置標題*/
    $("#dialog").dialog("setTitle","編輯角色");
    /*打開對話框 */
    $("#dialog").dialog("open");
});

添加時清空數據

/*添加角色*/
$("#add").click(function () {
    /*清空表單*/
    $("#myform").form("clear");
    /*清空已選權限*/
    $("#role_data2").datagrid("loadData",{rows:[]});
    /*設置標題*/
    $("#dialog").dialog("setTitle","添加角色");
    /*打開對話框 */
    $("#dialog").dialog("open");
});



打破關系重新保存

/*更新角色*/
@Override
public void updateRole(Role role) {

    /*打破角色與權限之間的之前關系*/
    roleMapper.deletePermissionRel(role.getRid());
    /*更新角色*/
    roleMapper.updateByPrimaryKey(role);
    /*重新建立與權限的關系*/

    /*重新保存角色與權限之間關系*/
    for (Permission permission : role.getPermissions()) {
        roleMapper.insertRoleAndPermissionRel(role.getRid(),permission.getPid());
    }
}

5.刪除角色權限

監聽刪除按鈕

/*監聽刪除點擊*/
$("#remove").click(function () {
    /*獲取當前選中的行*/
    var rowData = $("#role_dg").datagrid("getSelected");
    console.log(rowData);
    if(!rowData){
        $.messager.alert("提示","選擇一行數據進行刪除");
        return;
    }
    $.get("deleteRole?rid="+rowData.rid,function (data) {
        if (data.success){
            $.messager.alert("溫馨提示",data.msg);
            /*重新加載數據表格*/
            $("#role_dg").datagrid("reload");
        } else {
            $.messager.alert("溫馨提示",data.msg);
        }
    });
});

處理業務邏輯

/*接收刪除的請求*/
@RequestMapping("/deleteRole")
@ResponseBody
public AjaxRes deleteRole(Long rid){
    AjaxRes ajaxRes = new AjaxRes();
    try {
        /*調用刪除角色的業務*/
        roleService.deleteRole(rid);
        ajaxRes.setMsg("刪除角色成功");
        ajaxRes.setSuccess(true);
    }catch (Exception e){
        ajaxRes.setSuccess(false);
        ajaxRes.setMsg("刪除角色失敗");
    }
    return ajaxRes;
}

/*刪除角色的業務*/
@Override
public void deleteRole(Long rid) {
	/*1.刪除關聯的權限*/
	roleMapper.deletePermissionRel(rid);
	/*2.刪除對應的角色*/
	roleMapper.deleteByPrimaryKey(rid);
} 

6.員工添加角色

添加員工時, 添加角色下拉列表

/*回顯角色*/
/*根據當前用戶的id,查出對應的角色*/
$.get("/getRoleByEid?id="+rowData.id,function (data) {
    /*設置下拉列表數據回顯*/
    $("#role").combobox("setValues",data);
});

保存時, 保存時傳遞角色信息

/*提交表單*/
$("#employeeForm").form("submit",{
	url:saveEmployee,
	onSubmit:function(param){
		/*獲取選中的角色*/
	   var values =  $("#role").combobox("getValues");
	   for(var i = 0; i < values.length; i++){
		   var rid  =  values[i];
		   param["roles["+i+"].rid"] = rid;
	   }
	},
	success:function (data) {
	  data = $.parseJSON(data);
	  if (data.success){
		  $.messager.alert("溫馨提示",data.msg);
		  /*關閉對話框 */
		  $("#dialog").dialog("close");
		  /*重新加載數據表格*/
		  $("#dg").datagrid("reload");
	  } else {
		  $.messager.alert("溫馨提示",data.msg);
	  }
	}
});


7.員工編輯

回顯數據

/*監聽編輯按鈕點擊*/
$("#edit").click(function () {
    /*獲取當前選中的行*/
    var rowData = $("#dg").datagrid("getSelected");
    console.log(rowData);
    if(!rowData){
        $.messager.alert("提示","選擇一行數據進行編輯");
        return;
    }
    /*取消密碼驗證*/
    $("[name='password']").validatebox({required:false});
    $("#password").hide();
    /*彈出對話框*/
    $("#dialog").dialog("setTitle","編輯員工");
    $("#dialog").dialog("open");
    /*回顯部門*/
    // 當rowData["department"]為空時,會異常
    if(rowData["department"] != null)
    {
        rowData["department.id"] = rowData["department"].id;
    }
    else
        rowData["department.id"] = rowData["department"]+"";
    /*回顯管理員*/
    rowData["admin"] = rowData["admin"]+"";
    /*回顯角色*/
    /*根據當前用戶的id,查出對應的角色*/
    $.get("/getRoleByEid?id="+rowData.id,function (data) {
        /*設置下拉列表數據回顯*/
        $("#role").combobox("setValues",data);
    });

    /*選中數據的回示*/
    $("#employeeForm").form("load",rowData);

});


​ 保存編輯

/*更新員工*/
@Override
public void updateEmployee(Employee employee) {
    /*打破與角色之間關系*/
    employeeMapper.deleteRoleRel(employee.getId());
    /*更新員工*/
    employeeMapper.updateByPrimaryKey(employee);
    /*重新建立角色的關系*/
    for (Role role : employee.getRoles()) {
        employeeMapper.insertEmployeeAndRoleRel(employee.getId(),role.getRid());
    }
}

權限控制

登錄認證

​ 整合Shiro(添加pom依賴)

<dependency>
  <groupId>commons-logging</groupId>
  <artifactId>commons-logging</artifactId>
  <version>1.2</version>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-nop</artifactId>
  <version>1.7.24</version>
</dependency>
<dependency>
  <groupId>commons-collections</groupId>
  <artifactId>commons-collections</artifactId>
  <version>3.2.1</version>
</dependency>
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-core</artifactId>
  <version>1.4.0</version>
</dependency>
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-web</artifactId>
  <version>1.4.0</version>
</dependency>
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-ehcache</artifactId>
  <version>1.4.0</version>
</dependency>
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-spring</artifactId>
  <version>1.4.0</version>
</dependency>

1.登錄攔截,如果沒有登錄,跳轉到登錄頁面

​ 1.在web.xml當中配置過濾器攔截所有請求,進行處理

<!-- 攔截到所有請求,使用spring一個bean來進行處理 -->
<filter>
	<filter-name>shiroFilter</filter-name>
	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	<!-- 是否filter中的init和destroy-->
	<init-param>
		<param-name>targetFilterLifecycle</param-name>
		<param-value>true</param-value>
	</init-param>
</filter>

<filter-mapping>
	<filter-name>shiroFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

​ 2.在spring當中配置shiro過濾器和安全管理器

<!-- 配置shiro過濾器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
	<property name="securityManager" ref="securityManager"></property>

	<!-- 配置shiro過濾器pattern -->
	<property name="filterChainDefinitions">
		<value>
			/static/** = anon   <!--不需要登錄驗證-->
			/login.jsp = anon   <!--不需要登錄驗證-->
			/**=authc     <!--除指定請求外,其它所有的請求都需要身份驗證-->
		</value>
	</property>
</bean>

<!-- 配置shiro安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"></bean>

2.登錄認證流程

​ 1.表單發送請求

$(function () {
    $("#loginBtn").click(function () {
        /*Ajax發送請求, 是沒有辦法跳轉服務當中的請求
        * 只能通過在瀏覽器當中來跳轉
        * */
        $.post("/login",$("form").serialize(),function (data) {
           /*把data  json格式的字符串  轉成 json 數據*/
           data = $.parseJSON(data);
           if (data.success){
               /*跳轉到首頁*/
               window.location.href = "/index.jsp"
           } else {
              alert(data.msg);
           }
        });
    });
});

​ 2.指定登錄認證路徑

<!-- 配置登錄認證的路徑 -->
<property name="loginUrl" value="/login" />

​ 3.創建登錄realm和重新配置過濾器

public class EmployeeRealm extends AuthorizingRealm {

    @Autowired
    private EmployeeService employeeService;

    /*認證*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("來到了認證-------");
        /*獲取身份信息*/
        String username = (String)token.getPrincipal();
        System.out.println(username);
        /*根據用戶名當中查詢有沒有當前用戶*/
        Employee employee = employeeService.getEmployeeWithUserName(username);
        System.out.println(employee);
        if (employee == null){
            return null;
        }
        /*認證*/
        /*參數: 主體,正確的密碼,鹽,當前realm名稱*/
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                employee,
                employee.getPassword(),
                ByteSource.Util.bytes(employee.getUsername()),
                this.getName());

        return info;
    }
    
    /*授權
     web  doGetAuthorizationInfo 什么時候調用
     1.發現訪問路徑對應的方法上面 有授權注解  就會調用doGetAuthorizationInfo
     2.頁面當中有授權標簽  也會調用doGetAuthorizationInfo
    * */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("授權調用-------------------");
        /*獲取用戶的身份信息*/
        Employee employee = (Employee) principalCollection.getPrimaryPrincipal();
        /*根據當前用,查詢角色和權限*/
        List<String> roles = new ArrayList<>();
        List<String> permissions = new ArrayList<>();

        /*判斷當前用戶是不是管理員 如果是管理員 擁有所有的權限*/
        if(employee.getAdmin()){
            /*擁有所有的權限*/
            permissions.add("*:*");
        }else {
            /*查詢角色*/
            roles = employeeService.getRolesById(employee.getId());
            /*查詢權限*/
            permissions = employeeService.getPermissionById(employee.getId());
        }
        
       /*給授權信息*/
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles(roles);
        info.addStringPermissions(permissions);
        return info;
    }
}

​ 4.配置realm數據源(在application-shiro.xml中配置)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
     http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
">

    <bean id="myFormFilter" class="com.itlike.web.filter.MyFormFilter"/>


    <!-- 配置shiro過濾器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!--
        index
        其它的請求  會判斷 當前有沒有認證過
        默認情況 ,           沒有認證,會跳轉到login.jsp
        如果配置了 loginUrl  沒有認證  執行對應的login請求
        login
        loginUrl:如果發現請求是loginUrl值  會去做認證
        配置登錄認證的路徑
        -->
        <property name="loginUrl" value="/login"/>

        <!--重新配置表單監聽的過濾器-->
        <property name="filters">
            <map>
                <entry key="authc" value-ref="myFormFilter"/>
            </map>
        </property>

        <!--配置安全管理器-->
        <property name="securityManager" ref="securityManager"></property>
        <!-- 配置shiro過濾器pattern -->
        <property name="filterChainDefinitions">
            <value>
                /static/** = anon   <!--不需要登錄驗證-->
                /login.jsp = anon   <!--不需要登錄驗證-->
                /logout = logout   <!--取消認證-->
                /**=authc     <!--除指定請求外,其它所有的請求都需要身份驗證-->
            </value>
        </property>
    </bean>

    <!--自定義realm-->
    <bean id="employeeRealm" class="com.itlike.web.realm.EmployeeRealm">
        <property name="credentialsMatcher" ref="credentialsMatcher"/>
    </bean>

    <!-- 憑證匹配器 -->
    <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
        <!-- 散列算法 -->
        <property name="hashAlgorithmName" value="md5"/>
        <!-- 散列次數 -->
        <property name="hashIterations" value="2"></property>
    </bean>

    <!-- 緩存管理器 -->
    <bean id="ehCache" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/>
    </bean>


    <!-- 配置shiro安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!--注入realm-->
        <property name="realm" ref="employeeRealm"/>
        <!--注入緩存-->
        <property name="cacheManager" ref="ehCache"/>
    </bean>

    <!--
    配置為true即使用cglib繼承的方式,
    false為jdk的接口動態代理   控制器沒有實現接口
    -->
    <aop:config proxy-target-class="true" ></aop:config>

    <!-- 使用第三方去掃描shiro的注解 -->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor ">
        <property name="securityManager" ref="securityManager"></property>
    </bean>
    
</beans>


​ 5.創建表單認證過濾器

public class MyFormFilter extends FormAuthenticationFilter {

    /*當認證成功時,會調用*/
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
       /*響應給瀏覽器*/
        response.setCharacterEncoding("utf-8");
        System.out.println("認證成功");
        AjaxRes ajaxRes = new AjaxRes();
        ajaxRes.setSuccess(true);
        ajaxRes.setMsg("登錄成功");
        /*把對象轉成json格式字符串*/
        String jsonString = new ObjectMapper().writeValueAsString(ajaxRes);

        response.getWriter().print(jsonString);

        return false;
    }
    
    /*當認證失敗時, 會調用*/
    protected boolean onLoginFailure(AuthenticationToken token,
                                     AuthenticationException e,
                                     ServletRequest request,
                                     ServletResponse response) {
        System.out.println("認證失敗");

        AjaxRes ajaxRes = new AjaxRes();
        ajaxRes.setSuccess(false);
        if (e!=null){
            /*獲取異常名稱*/
            String name = e.getClass().getName();
            if(name.equals(UnknownAccountException.class.getName())){
                /*沒有帳號*/
                ajaxRes.setMsg("帳號不正確");
            } else if(name.equals(IncorrectCredentialsException.class.getName())){
                /*密碼錯誤*/
                ajaxRes.setMsg("密碼不正確");
            }else {
                /*未知異常*/
                ajaxRes.setMsg("未知錯誤");
            }
        }

        try {
            /*把對象轉成json格式字符串*/
            String jsonString = new ObjectMapper().writeValueAsString(ajaxRes);
            response.setCharacterEncoding("utf-8");
            response.getWriter().print(jsonString);
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        /*響應給瀏覽器*/
        return false;
    }
}

​ 登錄授權

  • 當我們在控制器方法寫了 @RequiresPermissions,Shiro在訪問時, 就會判斷有沒有該權限

  • 如果沒有,就不會執行對應方法
    實現過程
    1.在配置文件當中添加Shiro注解掃描

    <!--
    	配置為true即使用cglib繼承的方式,
    	false為jdk的接口動態代理   控制器沒有實現接口
    -->
    <aop:config proxy-target-class="true" ></aop:config>
    
    <!-- 使用第三方去掃描shiro的注解 -->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor ">
    	<property name="securityManager" ref="securityManager"></property>
    </bean>
    

    ​ 2.在realm中添加授權信息

public class EmployeeRealm extends AuthorizingRealm {

    @Autowired
    private EmployeeService employeeService;

    /*認證*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("來到了認證-------");
        /*獲取身份信息*/
        String username = (String)token.getPrincipal();
        System.out.println(username);
        /*根據用戶名當中查詢有沒有當前用戶*/
        Employee employee = employeeService.getEmployeeWithUserName(username);
        System.out.println(employee);
        if (employee == null){
            return null;
        }
        /*認證*/
        /*參數: 主體,正確的密碼,鹽,當前realm名稱*/
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                employee,
                employee.getPassword(),
                ByteSource.Util.bytes(employee.getUsername()),
                this.getName());

        return info;
    }
    /*授權
     web  doGetAuthorizationInfo 什么時候調用
     1.發現訪問路徑對應的方法上面 有授權注解  就會調用doGetAuthorizationInfo
     2.頁面當中有授權標簽  也會調用doGetAuthorizationInfo
    * */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("授權調用-------------------");
        /*獲取用戶的身份信息*/
        Employee employee = (Employee) principalCollection.getPrimaryPrincipal();
        /*根據當前用,查詢角色和權限*/
        List<String> roles = new ArrayList<>();
        List<String> permissions = new ArrayList<>();

        /*判斷當前用戶是不是管理員 如果是管理員 擁有所有的權限*/
        if(employee.getAdmin()){
            /*擁有所有的權限*/
            permissions.add("*:*");
        }else {
            /*查詢角色*/
            roles = employeeService.getRolesById(employee.getId());
            /*查詢權限*/
            permissions = employeeService.getPermissionById(employee.getId());
        }

       /*給授權信息*/
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles(roles);
        info.addStringPermissions(permissions);
        return info;
    }
}

沒有權限結果處理

@ExceptionHandler(AuthorizationException.class)
public void handleShiroException(HandlerMethod method,HttpServletResponse response) throws Exception{ /*method  發生異常的方法*/
    /*跳轉到一個界面  界面提示沒有 權限*/
    /*判斷 當前的請求是不是Json請求  如果是  返回json給瀏覽器 讓它自己來做跳轉*/
    /*獲取方法上的注解*/
    ResponseBody methodAnnotation = method.getMethodAnnotation(ResponseBody.class);
    if (methodAnnotation != null){
        //Ajax
        AjaxRes ajaxRes = new AjaxRes();
        ajaxRes.setSuccess(false);
        ajaxRes.setMsg("你沒有權限操作");
        String s = new ObjectMapper().writeValueAsString(ajaxRes);
        response.setCharacterEncoding("utf-8");
        response.getWriter().print(s);
    }else {
        response.sendRedirect("nopermission.jsp");
    }
}

權限按鈕控制

  • 引入Shiro的標簽庫
  • 在需要權限控制的地方添加對應的shiro標簽
<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>
<shiro:hasPermission name="employee:add">
            <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-add',plain:true" id="add">添加</a>
</shiro:hasPermission>

密碼散列

在保存用戶時, 給用戶密碼進行加密處理

/*把密碼進行加密*/
把用戶名作為鹽值,進行2次散列
Md5Hash md5Hash = new Md5Hash(employee.getPassword(), employee.getUsername(), 2);
employee.setPassword(md5Hash.toString());

在認證當中添加密碼處理

/*認證*/
/*參數: 主體,正確的密碼,鹽,當前realm名稱*/
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
employee,
employee.getPassword(),
ByteSource.Util.bytes(employee.getUsername()),
this.getName());

添加憑證匹配器

<!-- 配置realm數據源 -->
<bean id="employeeRealm" class="com.itlike.realm.EmployeeRealm">
	<property name="credentialsMatcher" ref="credentialsMatcher"/>
</bean>

<!-- 憑證匹配器 -->
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
	<!-- 散列算法 -->
	<property name="hashAlgorithmName" value="md5"/>
	<!-- 散列次數 -->
	<property name="hashIterations" value="2"></property>
</bean>

權限緩存

  • 進入頁面時, 頁面當中寫了Shiro的標簽,每一個標簽都要去到授權當中進行一次授權查詢
  • 授權查詢只使用一次即可, 所以使用緩存,把對應的內容緩存起來,下次再去, 直接從緩存當中進行查詢

使用步驟:

​ 1.添加緩存pom依賴
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-ehcache</artifactId>
  <version>1.2.2</version>
</dependency>
2.添加shiro緩存配置

​ 添加shiro-ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
	<defaultCache 
		maxElementsInMemory="1000" 
		maxElementsOnDisk="10000000"
		eternal="false" 
		overflowToDisk="false" 
		diskPersistent="false"
		timeToIdleSeconds="120"
		timeToLiveSeconds="120" 
		diskExpiryThreadIntervalSeconds="120"
		memoryStoreEvictionPolicy="LRU">
	</defaultCache>
</ehcache>

配置約束

3.application-shiro中配置緩存管理器

<!-- 緩存管理器 -->
<bean id="ehCache" class="org.apache.shiro.cache.ehcache.EhCacheManager">
	<property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/>
</bean>
4.把緩存管理器添加到安全管理器當中

<!-- 配置shiro安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
	<property name="realm" ref="employeeRealm" />
	<property name="cacheManager" ref="ehCache"/>
</bean>

菜單權限管理

菜單頁面

頁面搭建

1.創建菜單表
CREATE TABLE `menu` (
  `id` bigint(20) NOT NULL,
  `text` varchar(10) DEFAULT NULL,
  `url` varchar(30) DEFAULT NULL,
  `parent_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `parent_id` (`parent_id`),
  CONSTRAINT `menu_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `menu` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.生成Mapper,添加父菜單字段

@Setter@Getter@ToString
public class Menu {
    private Long id;
    private String text;
    private String url;
    private Menu parent;
    private Permission permission;
    private List<Menu> children = new ArrayList<>();
}
3.創建Menu頁面
<!-- 數據表格 -->
<table id="menu_datagrid">
    <thead>
    <tr>
        <th>名稱</th>
        <th>url</th>
        <th>父菜單</th>
    </tr>
    </thead>
</table>

<!-- 數據表格CRUD按鈕 -->
<div id="menu_toolbar">
    <div>
        <a class="easyui-linkbutton" iconCls="icon-add" plain="true" id="add">新增</a>
        <a class="easyui-linkbutton" iconCls="icon-edit" plain="true" id="edit">編輯</a>
        <a class="easyui-linkbutton" iconCls="icon-remove" plain="true" id="del">刪除</a>
        <a class="easyui-linkbutton" iconCls="icon-reload" plain="true" id="reload">刷新</a>
    </div>
</div>

<div id="menu_dialog">
    <form id="menu_form" method="post">
        <table align="center" style="margin-top: 15px;">
            <input type="hidden" name="id">
            <tr>
                <td>名稱</td>
                <td><input type="text" name="text"></td>
            </tr>
            <tr>
                <td>url</td>
                <td><input type="text" name="url"></td>
            </tr>
            <tr>
                <td>父菜單</td>
                <td><input type="text" id="parentMenu" name="parent.id" class="easyui-combobox" placeholder="請選擇父菜單"/></td>
            </tr>
        </table>
    </form>
</div>

<!-- 對話框保存取消按鈕 -->
<div id="menu_dialog_bt">
    <a class="easyui-linkbutton" iconCls="icon-save" plain="true" id="save">保存</a>
    <a class="easyui-linkbutton" iconCls="icon-cancel" plain="true" id="cancel">取消</a>
</div>

4.創建Menu.js

$(function () {

    $("#menu_datagrid").datagrid({
        url:"/menuList",
        columns:[[
            {field:'text',title:'名稱',width:1,align:'center'},
            {field:'url',title:'跳轉地址',width:1,align:'center'},
            {field:'parent',title:'父菜單',width:1,align:'center',formatter:function(value,row,index){
                    return value?value.text:'';
                }
            }
        ]],
        fit:true,
        rownumbers:true,
        singleSelect:true,
        striped:true,
        pagination:true,
        fitColumns:true,
        toolbar:'#menu_toolbar'
    });

    /*
     * 初始化新增/編輯對話框
     */
    $("#menu_dialog").dialog({
        width:300,
        height:240,
        closed:true,
        buttons:'#menu_dialog_bt'
    });
    /*加載選擇父菜單*/
    $("#parentMenu").combobox({
        width:150,
        panelHeight:'auto',
        editable:false,
        url:'parentList',
        textField:'text',
        valueField:'id',
        onLoadSuccess:function () { /*數據加載完畢之后回調*/
            $("#parentMenu").each(function(i){
                var span = $(this).siblings("span")[i];
                var targetInput = $(span).find("input:first");
                if(targetInput){
                    $(targetInput).attr("placeholder", $(this).attr("placeholder"));
                }
            });
        }
    });
    /*添加菜單*/
    $("#add").click(function () {
        $("#menu_dialog").dialog("setTitle","添加菜單");
        $("#menu_form").form("clear");
        $("#menu_dialog").dialog("open");
    });
    /*保存菜單*/
    $("#save").click(function () {
        /*判斷當前是添加 還是編輯*/
        var id = $("[name='id']").val();
        var url;
        if(id){
            var parent_id = $("[name='parent.id']").val();
            if (id == parent_id) {
                $.messager.alert("溫馨提示","不能設置自己為父菜單");
                return;
            }
            /*編輯*/
            url = "updateMenu";
        }else {
            /*添加*/
            url= "saveMenu";
        }

        /*提交表單*/
        $("#menu_form").form("submit",{
            url:url,
            success:function (data) {
                data = $.parseJSON(data);
                if (data.success){
                    $.messager.alert("溫馨提示",data.msg);
                    /*關閉對話框 */
                    $("#menu_dialog").dialog("close");
                    $("#parentMenu").combobox("reload");
                    $("#menu_datagrid").datagrid("reload");
                } else {
                    $.messager.alert("溫馨提示",data.msg);
                }
            }
        });
    });
    /*編輯菜單*/
    $("#edit").click(function () {

        $("#menu_form").form("clear");
        /*獲取當前選中的行*/
        var rowData = $("#menu_datagrid").datagrid("getSelected");
        if(!rowData){
            $.messager.alert("提示","選擇一行數據進行編輯");
            return;
        }
        /*父菜單回顯*/
        if(rowData.parent){
            rowData["parent.id"] = rowData.parent.id;
        }else {/*回顯的placeholder*/
            $("#parentMenu").each(function(i){
                var span = $(this).siblings("span")[i];
                var targetInput = $(span).find("input:first");
                if(targetInput){
                    $(targetInput).attr("placeholder", $(this).attr("placeholder"));
                }
            });
        }
        /*彈出對話框*/
        $("#menu_dialog").dialog("setTitle","編輯菜單");
        $("#menu_dialog").dialog("open");
        /*選中數據的回示*/
        $("#menu_form").form("load",rowData);
    });

    $("#cancel").click(function () {
        $("#menu_dialog").dialog("close");
    });
    
    $("#del").click(function () {
        /*獲取當前選中的行*/
        var rowData = $("#menu_datagrid").datagrid("getSelected");
        if(!rowData){
            $.messager.alert("提示","選擇一行數據進行刪除");
            return;
        }
        /*提醒用戶,是否做刪除操作*/
        $.messager.confirm("確認","是否做刪除操作",function (res) {
            if(res){
                /*做離職操作*/
                $.get("/deleteMenu?id="+rowData.id,function (data) {
                    if (data.success){
                        $.messager.alert("溫馨提示",data.msg);
                        /*重新加載下拉列表數據*/
                        $("#parentMenu").combobox("reload");
                        /*重新加載數據表格*/
                        $("#menu_datagrid").datagrid("reload");
                    } else {
                        $.messager.alert("溫馨提示",data.msg);
                    }

                });
            }
        });
    });

});

菜單列表

1.接收菜單請求

@Service
public class MenuServiceImpl implements MenuService {

    @Autowired
    private MenuMapper menuMapper;

    @Override
    public PageListRes getMenuList(QueryVo vo) {
        /*調用mapper 查詢菜單 */
        Page<Object> page = PageHelper.startPage(vo.getPage(), vo.getRows());
        List<Menu> menus = menuMapper.selectAll();
        /*封裝成pageList*/
        PageListRes pageListRes = new PageListRes();
        pageListRes.setTotal(page.getTotal());
        pageListRes.setRows(menus);
        return pageListRes;
    }

}

2.底層實現

<resultMap id="BaseResultMap" type="com.itlike.domain.Menu" >
  <id column="id" property="id" jdbcType="BIGINT" />
  <result column="text" property="text" jdbcType="VARCHAR" />
  <result column="url" property="url" jdbcType="VARCHAR" />

  <association property="parent" javaType="com.itlike.domain.Menu" columnPrefix="m_">
    <result property="id" column="id"/>
    <result property="text" column="text"/>
    <result property="url" column="url"/>
  </association>

  <association property="permission" javaType="com.itlike.domain.Permission">
    <result property="pid" column="pid"/>
    <result property="pname" column="pname"/>
    <result property="presource" column="presource"/>
  </association>
  
  <collection property="children" ofType="com.itlike.domain.Menu"  select="listChildMenu" column="id"/>

</resultMap>
<!-- /*查詢所有菜單*/-->
<select id="selectAll" resultMap="BaseResultMap" >
  SELECT
  m1.id,
  m1.text,
  m1.url,
  m2.id as m_id,
  m2.text as m_text,
  m2.url as m_url
  from menu  as m1
  LEFT JOIN menu as m2
  ON m1.parent_id = m2.id
  order by m1.id desc
</select>
3.頁面處理
formatter這個屬性屬於列參數,意思就是對當前列的數據進行格式化操作,它是一個函數,有三個參數,value,row,index,
value:代表當前單元格中的值,
row:代表當前行,
index:代表當前行的下標,
可以使用return 返回你想要的數據顯示在單元格中;
formatter:function(value,row,index){
	return value?value.text:'';
}

菜單添加

獲取所有父菜單

<tr>
	<td>父菜單</td>
	<td><input type="text" id="parentMenu" name="parent.id" class="easyui-combobox" placeholder="請選擇父菜單"/></td>
</tr>

$(function () {
    /*加載選擇父菜單*/
    $("#parentMenu").combobox({
        width:150,
        panelHeight:'auto',
        editable:false,
        url:'parentList',
        textField:'text',
        valueField:'id',
        onLoadSuccess:function () { /*數據加載完畢之后回調*/
            $("#parentMenu").each(function(i){
                var span = $(this).siblings("span")[i];
                var targetInput = $(span).find("input:first");
                if(targetInput){
                    $(targetInput).attr("placeholder", $(this).attr("placeholder"));
                }
            });
        }
    });
});

保存菜單

監聽保存點擊
/*保存菜單*/
$("#save").click(function () {
    /*判斷當前是添加 還是編輯*/
    var id = $("[name='id']").val();
    var url;
    if(id){
        var parent_id = $("[name='parent.id']").val();
        if (id == parent_id) {
            $.messager.alert("溫馨提示","不能設置自己為父菜單");
            return;
        }
        /*編輯*/
        url = "updateMenu";
    }else {
        /*添加*/
        url= "saveMenu";
    }

    /*提交表單*/
    $("#menu_form").form("submit",{
        url:url,
        success:function (data) {
            data = $.parseJSON(data);
            if (data.success){
                $.messager.alert("溫馨提示",data.msg);
                /*關閉對話框 */
                $("#menu_dialog").dialog("close");
                $("#parentMenu").combobox("reload");
                $("#menu_datagrid").datagrid("reload");
            } else {
                $.messager.alert("溫馨提示",data.msg);
            }
        }
    });
});				
業務處理

/*保存菜單*/
@RequestMapping("/saveMenu")
@ResponseBody
public AjaxRes saveMenu(Menu menu){
    AjaxRes ajaxRes = new AjaxRes();
    try {
        /*調用業務層,保存菜單*/
        menuService.saveMenu(menu);
        ajaxRes.setMsg("保存成功");
        ajaxRes.setSuccess(true);
    }catch (Exception e){
        ajaxRes.setSuccess(false);
        ajaxRes.setMsg("保存失敗");
        System.out.println(e);
    }
    return ajaxRes;
}

編輯菜單

/*編輯菜單*/
$("#edit").click(function () {

    $("#menu_form").form("clear");
    /*獲取當前選中的行*/
    var rowData = $("#menu_datagrid").datagrid("getSelected");
    if(!rowData){
        $.messager.alert("提示","選擇一行數據進行編輯");
        return;
    }
    /*父菜單回顯*/
    if(rowData.parent){
        rowData["parent.id"] = rowData.parent.id;
    }else {/*回顯的placeholder*/
        $("#parentMenu").each(function(i){
            var span = $(this).siblings("span")[i];
            var targetInput = $(span).find("input:first");
            if(targetInput){
                $(targetInput).attr("placeholder", $(this).attr("placeholder"));
            }
        });
    }
    /*彈出對話框*/
    $("#menu_dialog").dialog("setTitle","編輯菜單");
    $("#menu_dialog").dialog("open");
    /*選中數據的回示*/
    $("#menu_form").form("load",rowData);
});			

刪除菜單

監聽刪除按鈕
$("#del").click(function () {
    /*獲取當前選中的行*/
    var rowData = $("#menu_datagrid").datagrid("getSelected");
    if(!rowData){
        $.messager.alert("提示","選擇一行數據進行刪除");
        return;
    }
    /*提醒用戶,是否做刪除操作*/
    $.messager.confirm("確認","是否做刪除操作",function (res) {
        if(res){
            /*做離職操作*/
            $.get("/deleteMenu?id="+rowData.id,function (data) {
                if (data.success){
                    $.messager.alert("溫馨提示",data.msg);
                    /*重新加載下拉列表數據*/
                    $("#parentMenu").combobox("reload");
                    /*重新加載數據表格*/
                    $("#menu_datagrid").datagrid("reload");
                } else {
                    $.messager.alert("溫馨提示",data.msg);
                }

            });
        }
    });
});			
處理業務邏輯
@Override
public AjaxRes deleteMenu(Long id) {

    AjaxRes ajaxRes = new AjaxRes();
    try {
        /*1.打破菜單關系*/
        menuMapper.updateMenuRel(id);
        /*2.刪除記錄*/
        menuMapper.deleteByPrimaryKey(id);
        ajaxRes.setMsg("刪除成功");
        ajaxRes.setSuccess(true);
    }catch (Exception e){
        ajaxRes.setSuccess(false);
        ajaxRes.setMsg("刪除失敗");
        System.out.println(e);
    }
    return ajaxRes;
}
<!--根據id刪除菜單-->
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long" >
  delete from menu
  where id = #{id,jdbcType=BIGINT}
</delete>

<!--根基id更新菜單-->
<update id="updateByPrimaryKey" parameterType="com.itlike.domain.Menu" >
  update menu
  set text = #{text},
    url = #{url},
    parent_id = #{parent.id}
  where id = #{id}
</update>

菜單權限

在**menu**數據表中, 添加外鍵, 每一個菜單對應一個權限,通過判斷用戶有沒有該權限來控制菜單的顯示隱藏
設置菜單對應權限並取出

1.在menu表中添加權限外鍵

2.在菜單domain當中添加權限對象

tree數據加載

$(function () {
    $("#tabs").tabs({
        fit:true
    })
    $('#tree').tree({
        url:"/getTreeData",
        lines:true,
        onSelect: function(node){
            /*在添加之前, 做判斷  判斷這個標簽是否存在 */
            var exists =   $("#tabs").tabs("exists",node.text);
            if(exists){
                /*存在,就讓它選中*/
                $("#tabs").tabs("select",node.text);
            }else {
                if (node.url !=''&& node.url !=null){
                    /*如果不存在 ,添加新標簽*/
                    $("#tabs").tabs("add",{
                        title:node.text,
                        /*href:node.attributes.url,*/  /*href  引入的是body當中*/
                        content:"<iframe src="+node.url+" frameborder='0' width='100%' height='100%'></iframe>",
                        closable:true
                    })
                }
            }
        },
        onLoadSuccess: function (node, data) {
            console.log(data[0].children[0].id);
            if (data.length > 0) {
                //找到第一個元素
                var n = $('#tree').tree('find', data[0].children[0].id);
                //調用選中事件
                $('#tree').tree('select', n.target);
            }
        }
    });
});

3.查詢菜單時, 把對應權限查出來, 檢查權限

@Override
public List<Menu> getTreeData() {
    List<Menu> treeData = menuMapper.getTreeData();
    /*
    判斷當前用戶有沒有對應的權限
    如果沒有就從集合當中移除
    */
    /*獲取用戶 判斷用戶是否是管理員 是管理就不需要做判斷*/
    Subject subject = SecurityUtils.getSubject();
    /*當前的用戶*/
    Employee employee = (Employee)subject.getPrincipal();
    if (!employee.getAdmin()){
        /*做檢驗權限*/
        checkPermission(treeData);
    }
    return treeData;
}

public void checkPermission(List<Menu> menus){
    //獲取主體
    Subject subject = SecurityUtils.getSubject();
    //遍歷所有的菜單及子菜單
    Iterator<Menu> iterator = menus.iterator();
    while (iterator.hasNext()){
        Menu menu = iterator.next();
        if (menu.getPermission() !=null){
            //判斷當前menu是否有權限對象,如果說沒有 當前遍歷的菜單從集合當中移除
            String presource = menu.getPermission().getPresource();
            if (!subject.isPermitted(presource)){
                //當前遍歷的菜單從集合當中移除
                iterator.remove();
                continue;
            }
        }
        /*判斷是否有子菜單  有子菜單也要做權限檢驗*/
        if (menu.getChildren().size() > 0){
            checkPermission(menu.getChildren());
        }
    }
}
<resultMap id="BaseResultMap" type="com.itlike.domain.Menu" >
  <id column="id" property="id" jdbcType="BIGINT" />
  <result column="text" property="text" jdbcType="VARCHAR" />
  <result column="url" property="url" jdbcType="VARCHAR" />

  <association property="parent" javaType="com.itlike.domain.Menu" columnPrefix="m_">
    <result property="id" column="id"/>
    <result property="text" column="text"/>
    <result property="url" column="url"/>
  </association>

  <association property="permission" javaType="com.itlike.domain.Permission">
    <result property="pid" column="pid"/>
    <result property="pname" column="pname"/>
    <result property="presource" column="presource"/>
  </association>

  <collection property="children" ofType="com.itlike.domain.Menu"  select="listChildMenu" column="id"/>

</resultMap>

<!--獲取樹形菜單數據
 分步查詢  先查根菜單
 根據根菜單的id  查詢出子菜單
-->
<select id="getTreeData" resultMap="BaseResultMap">
  select * from menu as m
  LEFT JOIN permission as p
  on m.permission_id = p.pid where parent_id is null
</select>

<!--根據根菜單的id  查詢出子菜單-->
<select id="listChildMenu" resultMap="BaseResultMap">
  select * from menu as m
  LEFT JOIN permission as p
  on m.permission_id = p.pid where parent_id = #{id}
</select>

系統日志

建立日志表和對應mapper

CREATE TABLE `systemlog` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `optime` datetime DEFAULT NULL,
  `ip` varchar(20) DEFAULT NULL,
  `function` varchar(255) DEFAULT NULL,
  `params` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

添加攔截器,記錄當前請求的ip

創建本地線程變量

public class RequestUtil {
    public static ThreadLocal<HttpServletRequest> local  = new ThreadLocal();

    public static HttpServletRequest getRequest(){
        return local.get();
    }

    public static void setRequest(HttpServletRequest request){
        local.set(request);
    }
}		

配置攔截器攔截所有請求

<!--配置攔截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/*"/>
        <bean class="com.itlike.interceptor.RequestInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>	

創建攔截器把當前請求寫入到本地線程變量

public class RequestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("來到了攔截器...");
        RequestUtil.setRequest(request);
        return true;
    }
}

Systemlog systemlog = new Systemlog();
//設置ip地址  request 添加攔截器  獲取請求對象
HttpServletRequest request = RequestUtil.getRequest();
if (request != null){
   String IP = request.getRemoteAddr();
   System.out.println(IP);
   systemlog.setIp(IP);
}

創建日志切面、在切面中獲取ip、獲取當前執行的方法及參數

public class SystemAspect {
    @Autowired
    private SystemlogMapper systemlogMapper;

    public void writeLog(JoinPoint joinPoint) throws JsonProcessingException {
        System.out.println("記錄日志");
        //設置時間
        Systemlog systemlog = new Systemlog();
        systemlog.setOptime(new Date());
        //設置ip地址  request 添加攔截器  獲取請求對象
        HttpServletRequest request = RequestUtil.getRequest();
        if (request != null){
           String IP = request.getRemoteAddr();
           System.out.println(IP);
           systemlog.setIp(IP);
        }
        //方法
        //獲取目標執行方法的全路徑
        String name = joinPoint.getTarget().getClass().getName();
        //獲取方法名稱
        String signature = joinPoint.getSignature().getName();
        String func = name+":"+signature;
        systemlog.setFunction(func);

        //獲取方法參數
       String params = new ObjectMapper().writeValueAsString(joinPoint.getArgs());
       systemlog.setParams(params);
       systemlogMapper.insert(systemlog);
    }
}

添加切面

<!-- aop配置 日志配置 -->
<bean id="SystemAspect" class="com.itlike.aspect.SystemAspect"></bean>

<aop:config>
    <aop:pointcut expression="execution(* com.itlike.service.*.*(..))" id="servicePoint" />
    <aop:aspect ref="SystemAspect">
        <aop:after method="writeLog" pointcut-ref="servicePoint"/>
    </aop:aspect>
</aop:config>

Excel導入導出

介紹

操作Excel的方式jxl和poi
官方文檔
	https://poi.apache.org/components/spreadsheet/quick-guide.html#CellContents
	參考文檔
	https://www.cnblogs.com/huajiezh/p/5467821.html
	依賴
	<dependency>
		<groupId>org.apache.poi</groupId>
  		<artifactId>poi</artifactId>
  		<version>4.0.1</version>
	</dependency>

導出

// Excel導出
$("#excelOut").click(function () {
   window.open('/downloadExcel')
});

@RequestMapping("/downloadExcel")
@ResponseBody
public void downloadExcel(HttpServletResponse response){
    try {
    System.out.println("---------downloadExcel---------");
    //1.從數據庫當中取列表數據
    QueryVo queryVo = new QueryVo();
    queryVo.setPage(1);
    queryVo.setRows(10);
    PageListRes plr = employeeService.getEmployee(queryVo);
    List<Employee> employees = (List<Employee>)plr.getRows();
    //2.創建Excel 寫到excel當中
    HSSFWorkbook wb = new HSSFWorkbook();
    HSSFSheet sheet = wb.createSheet("員工數據");
    //創建一行
    HSSFRow row = sheet.createRow(0);
    //設置行的每一列的數據
    row.createCell(0).setCellValue("編號");
    row.createCell(1).setCellValue("用戶名");
    row.createCell(2).setCellValue("入職日期");
    row.createCell(3).setCellValue("電話");
    row.createCell(4).setCellValue("郵件");

    HSSFRow employeeRow = null;
    /*取出每一個員工來去設置數據*/
    for(int i = 0; i < employees.size(); i++){
        Employee employee = employees.get(i);
        employeeRow = sheet.createRow(i+1);
        employeeRow.createCell(0).setCellValue(employee.getId());
        employeeRow.createCell(1).setCellValue(employee.getUsername());
        if (employee.getInputtime() !=null){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String format = sdf.format(employee.getInputtime());
            employeeRow.createCell(2).setCellValue(format);
        }else {
            employeeRow.createCell(2).setCellValue("");
        }
        employeeRow.createCell(3).setCellValue(employee.getTel());
        employeeRow.createCell(4).setCellValue(employee.getEmail());
    }

    //3.響應給瀏覽器
        String fileName = new String("員工數據.xls".getBytes("utf-8"), "iso8859-1");
        response.setHeader("content-Disposition","attachment;filename="+fileName);
        wb.write(response.getOutputStream());

    } catch (Exception e) {
        e.printStackTrace();
    }
}


導入

上傳界面

<div id="excelUpload">
	<form method="post" enctype="multipart/form-data">
		<tabel>
			<tr>
				<td><input type="file" name="excel" style="width: 180px; margin-top: 20px; margin-left: 5px;"></td>
				<td><a href="javascript:void(0);" id="downloadTml">下載模板</a></td>
			</tr>
		</tabel>
	</form>
</div>
$("#excelUpload").dialog({
        width:260,
        height:180,
        title:"導入Excel",
        buttons:[{
            text:'保存',
            handler:function(){

            }
        },{
            text:'關閉',
            handler:function(){
                $("#excelUpload").dialog("close");
            }
        }],
        closed:true
    })

    $("#excelImpot").click(function () {
        $("#excelUpload").dialog("open");
    });

下載模板

/*下載Excel模板*/
$("#downloadTml").click(function () {
    window.open('/downloadExcelTpl')
});		
/*下載模板*/
@RequestMapping("downloadExcelTpl")
@ResponseBody
public void downloadExcelTpl(HttpServletRequest request, HttpServletResponse response){
    FileInputStream is = null;
    try {
        String fileName = new String("EmployeeTpl.xls".getBytes("utf-8"), "iso8859-1");
        response.setHeader("content-Disposition","attachment;filename="+fileName);
       /*獲取文件路徑*/
        String realPath = request.getSession().getServletContext().getRealPath("static/ExcelTml.xls");
        is = new FileInputStream(realPath);
        IOUtils.copy(is,response.getOutputStream());
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        if (is != null){
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

上傳Excel處理

上傳模板

// 打開上傳窗口
$("#excelIn").click(function () {
    $("#excelUpload").dialog("open");
});

// Excel導入
$("#excelUpload").dialog({
    width:260,
    height:180,
    title:"導入Excel",
    buttons:[{
        text:'保存',
        handler:function(){
            $("#uploadForm").form("submit",{
                url:"uploadExcelFile",
                success:function (data) {
                    data = $.parseJSON(data);
                    if (data.success){
                        $.messager.alert("溫馨提示",data.msg);
                        /*關閉對話框 */
                        $("#excelUpload").dialog("close");
                        /*重新加載數據表格*/
                        $("#dg").datagrid("reload");
                    } else {
                        $.messager.alert("溫馨提示",data.msg);
                    }
                }
            })
        }
    },{
        text:'關閉',
        handler:function(){
            $("#excelUpload").dialog("close");
        }
    }],
    closed:true
});

業務處理

/*配置文件上傳解析器  mvc配置當中*/
@RequestMapping("/uploadExcelFile")
@ResponseBody
@RequiresPermissions("employee:add")
public AjaxRes uploadExcelFile(MultipartFile excel){
    AjaxRes ajaxRes = new AjaxRes();
    try {
        ajaxRes.setMsg("導入成功");
        ajaxRes.setSuccess(true);
        HSSFWorkbook wb = new HSSFWorkbook(excel.getInputStream());
        HSSFSheet sheet = wb.getSheetAt(0);
        /*獲取最大的行號*/
        int lastRowNum = sheet.getLastRowNum();
        Row employeeRow = null;
        if(1 <= lastRowNum)
        {
            employeeRow = sheet.getRow(0);
            if(!getCellValue(employeeRow.getCell(1)).toString().equals("用戶名"))
                throw new Exception("格式錯誤");
            else if(!getCellValue(employeeRow.getCell(2)).toString().equals("入職日期"))
                throw new Exception("格式錯誤");
            else if(!getCellValue(employeeRow.getCell(3)).toString().equals("電話"))
                throw new Exception("格式錯誤");
            else if(!getCellValue(employeeRow.getCell(4)).toString().equals("郵件"))
                throw new Exception("格式錯誤");
        }
        for (int i=1; i <= lastRowNum; i++){
            employeeRow = sheet.getRow(i);
            Employee employee = new Employee();
            employee.setState(true);
            employee.setUsername(getCellValue(employeeRow.getCell(1)).toString());

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date parse = sdf.parse(getCellValue(employeeRow.getCell(2)).toString());
            employee.setInputtime(parse);
            employee.setTel(getCellValue(employeeRow.getCell(3)).toString());
            employee.setEmail(getCellValue(employeeRow.getCell(4)).toString());
            employee.setPassword("123456");
            employeeService.saveEmployee(employee);
        }
    }catch (Exception e){
        e.printStackTrace();
        ajaxRes.setMsg("導入失敗!"+e.getMessage());
        ajaxRes.setSuccess(false);
    }
    return ajaxRes;
}

private Object getCellValue(Cell cell){
    switch (cell.getCellType()) {
        case STRING:
            return cell.getRichStringCellValue().getString();
        case NUMERIC:
            if (DateUtil.isCellDateFormatted(cell)) {
                return cell.getDateCellValue();
            } else {
                return cell.getNumericCellValue();
            }
        case BOOLEAN:
            return cell.getBooleanCellValue();
        case FORMULA:
            return cell.getCellFormula();
    }
    return cell;
}

配置文件上傳解析器

<!--配置文件上傳解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize">
        <value>1040000</value>
    </property>
</bean>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM