zoukankan      html  css  js  c++  java
  • 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="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:'姓名',100,align:'center'},
                {field:'inputtime',title:'入职时间',100,align:'center'},
                {field:'tel',title:'电话',100,align:'center'},
                {field:'email',title:'邮箱',100,align:'center'},
                {field:'department',title:'部门',100,align:'center',formatter: function(value,row,index){
                    if (value){
                        return value.name;
                    }
                }},
                {field:'state',title:'状态',100,align:'center',formatter: function(value,row,index){
                        if(row.state){
                            return "在职";
                        }else {
                            return "<font style='color: red'>离职</font>"
                        }
                    }},
                {field:'admin',title:'管理员',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:'姓名',100,align:'center'},
                {field:'inputtime',title:'入职时间',100,align:'center'},
                {field:'tel',title:'电话',100,align:'center'},
                {field:'email',title:'邮箱',100,align:'center'},
                {field:'department',title:'部门',100,align:'center',formatter: function(value,row,index){
                    if (value){
                        return value.name;
                    }
                }},
                {field:'state',title:'状态',100,align:'center',formatter: function(value,row,index){
                        if(row.state){
                            return "在职";
                        }else {
                            return "<font style='color: red'>离职</font>"
                        }
                    }},
                {field:'admin',title:'管理员',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({
        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({
    	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({
    	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:'姓名',100,align:'center'},
            {field:'inputtime',title:'入职时间',100,align:'center'},
            {field:'tel',title:'电话',100,align:'center'},
            {field:'email',title:'邮箱',100,align:'center'},
            {field:'department',title:'部门',100,align:'center',formatter: function(value,row,index){
                if (value){
                    return value.name;
                }
            }},
            {field:'state',title:'状态',100,align:'center',formatter: function(value,row,index){
                    if(row.state){
                        return "在职";
                    }else {
                        return "<font style='color: red'>离职</font>"
                    }
                }},
            {field:'admin',title:'管理员',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=" 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:'角色编号',100,align:'center'},
    		{field:'rname',title:'角色名称',100,align:'center'},
    	]],
    	fit:true,
    	fitColumns:true,
    	rownumbers:true,
    	pagination:true,
    	singleSelect:true,
    	striped:true,
    	toolbar:"#toolbar",
    });
    
    /*权限列表*/
    $("#role_data1").datagrid({
    	title:"所有权限",
    	250,
    	height:400,
    	fitColumns:true,
    	singleSelect:true,
    	url:'/permissionList',
    	columns:[[
    		{field:'pname',title:'权限名称',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:"已选权限",
    	250,
    	height:400,
    	singleSelect:true,
    	fitColumns:true,
    	columns:[[
    		{field:'pname',title:'权限名称',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({
        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:'角色编号',100,align:'center'},
            {field:'rname',title:'角色名称',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:'名称',1,align:'center'},
                {field:'url',title:'跳转地址',1,align:'center'},
                {field:'parent',title:'父菜单',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({
            300,
            height:240,
            closed:true,
            buttons:'#menu_dialog_bt'
        });
        /*加载选择父菜单*/
        $("#parentMenu").combobox({
            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({
            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=" 180px; margin-top: 20px; margin-left: 5px;"></td>
    				<td><a href="javascript:void(0);" id="downloadTml">下载模板</a></td>
    			</tr>
    		</tabel>
    	</form>
    </div>
    
    $("#excelUpload").dialog({
            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({
        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>
    
  • 相关阅读:
    多线程2
    多线程1
    Mybatis动态代理开发
    Mybatis的mapper.xml文件也是要加文件头的
    ssm框架只使用mybatis配置sqlmapconfig.xml
    ssm整合之web.xml配置
    SpringMVC三大组件的配置
    spring开启注解配置
    如何开发 Sublime Text 2 的插件
    ASP.NET MVC 5改进了基于过滤器的身份验证
  • 原文地址:https://www.cnblogs.com/mumuyinxin/p/11282898.html
Copyright © 2011-2022 走看看