SSM众筹网站

本文详述了一个基于SSM(Spring、SpringMVC、MyBatis)的众筹网站的实现,涵盖了系统架构、模块划分、数据库配置、前端交互、用户管理、权限控制、Activiti5工作流的集成与应用,包括流程创建、部署、查询、分配任务、监听器设置等。此外,还涉及到了分页插件、文件上传、登录权限拦截、会员实名认证流程等多个功能的实现细节。
摘要由CSDN通过智能技术生成

注:本文为伪原创,代码主要参考尚硅谷教程。感谢巨人的肩膀,让我可以看得更远。

本文全部代码见https://github.com/BnKes/crowdfunding

详细目录见文章尾巴


1.系统架构

  • Atcrowdfunding-parent 父工程,聚合其他工程(pom)
  • Atcrowdfunding-main Web工程,存放所有页面,框架配置文件(war)
  • Atcrowdfunding-manager-impl 后台管理系统,存放控制器类,业务层实现类(jar)
  • Atcrowdfunding-manager-api 后台管理系统,存放业务层接口和DAO层接口(jar)
  • Atcrowdfunding-potal-impl 前台系统,存放控制器类,业务层实现类(jar)
  • Atcrowdfunding-potal-api 前台系统,存放业务层接口和DAO层接口(jar)
  • Atcrowdfunding-common 存放所有模块所需要的公共类(jar)
  • Atcrowdfunding-bean 存放所有模块的实体类(jar)

各工程依赖:

2.pom.xml

(1)parent

<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.atguigu.maven</groupId>
  <artifactId>01-Atcrowdfunding-parent</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
  <modules>
  	<module>../Atcrowdfunding-bean</module>
  	<module>../Atcrowdfunding-common</module>
  	<module>../Atcrowdfunding-main</module>
  	<module>../Atcrowdfunding-manager-api</module>
  	<module>../Atcrowdfunding-manager-impl</module>
  	<module>../Atcrowdfunding-potal-api</module>
  	<module>../Atcrowdfunding-potal-impl</module>
  </modules>
  
  <dependencyManagement>
  <dependencies>
		<dependency>
    		 <groupId>junit</groupId>
   			 <artifactId>junit</artifactId>
   			 <version>4.12</version>
   		</dependency> 
   		
		<dependency>
		    <groupId>org.mybatis.generator</groupId>
		    <artifactId>mybatis-generator-core</artifactId>
		    <version>1.3.5</version>
		</dependency>
  
  		<dependency> 
  		    <groupId>javax.servlet</groupId> 
 		    <artifactId>servlet-api</artifactId> 
		    <version>2.5</version> 
 		    <scope>provided</scope> 
		</dependency> 
		
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
		    <artifactId>jsp-api</artifactId>
		    <version>2.1.3-b06</version>
		    <scope>provided</scope><!-- 注意!!!! -->
		</dependency>
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-core</artifactId>
		    <version>4.0.0.RELEASE</version>
		</dependency> 
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.0.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>4.0.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>4.0.0.RELEASE</version> 
		</dependency> 
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>4.0.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.0.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>com.mchange</groupId>
			<artifactId>c3p0</artifactId>
			<version>0.9.5.4</version>
		</dependency>
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>2.2</version>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.6.8</version>
		</dependency>

		<!-- Spring整合MyBatis -->
		<!-- MyBatis中延迟加载需要使用Cglib -->
		<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.2.8</version>
		</dependency>

		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>1.2.2</version>
		</dependency>

		<!-- 控制日志输出:结合log4j -->
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.7</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.7</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.11</version>
		</dependency>
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- ********其他****************************** -->

		<!-- Ehcache二级缓存 -->
		<dependency>
			<groupId>net.sf.ehcache</groupId>
			<artifactId>ehcache</artifactId>
			<version>1.6.2</version>
		</dependency>


		<!-- 石英调度 - 开始 -->
		<dependency>
		    <groupId>org.quartz-scheduler</groupId>
		    <artifactId>quartz</artifactId>
		    <version>2.3.2</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>4.0.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>commons-collections</groupId>
			<artifactId>commons-collections</artifactId>
			<version>3.1</version>
		</dependency>
		<!-- 石英调度 - 结束 -->

		<dependency>
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-mapper-asl</artifactId>
			<version>1.9.2</version>
		</dependency>

		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.9</version>
		</dependency>

		<dependency>
			<groupId>org.jfree</groupId>
			<artifactId>jfreechart</artifactId>
			<version>1.0.19</version>
		</dependency>

		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3.3</version>
		</dependency>
		
		<dependency>
		    <groupId>org.freemarker</groupId>
		    <artifactId>freemarker</artifactId>
		    <version>2.3.19</version>
		</dependency>
		
		<dependency>
		    <groupId>org.activiti</groupId>
		    <artifactId>activiti-engine</artifactId>
		    <version>5.15.1</version>
		</dependency>
		
		<dependency>
		    <groupId>org.activiti</groupId>
		    <artifactId>activiti-spring</artifactId>
		    <version>5.15.1</version>
		</dependency>
		
		<dependency>
		    <groupId>org.apache.commons</groupId>
		    <artifactId>commons-email</artifactId>
		    <version>1.3.1</version>
		</dependency>
		
		<dependency>
		    <groupId>org.activiti</groupId>
		    <artifactId>activiti-explorer</artifactId>
		    <version>5.15.1</version>
		    <exclusions>
		        <exclusion>
		            <artifactId>groovy-all</artifactId>
		            <groupId>org.codehaus.groovy</groupId>
		        </exclusion>
		    </exclusions>
		</dependency>
	</dependencies>
	
</dependencyManagement>
</project>

(2)bean

<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>
  <artifactId>Atcrowdfunding-bean</artifactId>
  <dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
  </dependencies>
  <parent>
  	<groupId>com.atguigu.maven</groupId>
  	<artifactId>01-Atcrowdfunding-parent</artifactId>
  	<version>0.0.1-SNAPSHOT</version>
  </parent>
</project>

(3)common

<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>
	<artifactId>Atcrowdfunding-common</artifactId>

  	<parent>
		<groupId>com.atguigu.maven</groupId>
		<artifactId>01-Atcrowdfunding-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version> 
		<relativePath>../01-Atcrowdfunding-parent/pom.xml</relativePath>
	</parent>

	<dependencies>
		<dependency>
			<groupId>com.atguigu.maven</groupId>
			<artifactId>Atcrowdfunding-bean</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>

        <dependency>
              <groupId>javax.servlet</groupId>
              <artifactId>servlet-api</artifactId>
              <scope>provided</scope><!-- 注意!!!! -->
        </dependency> 
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <scope>provided</scope><!-- 注意!!!! -->
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>

        <!-- Spring整合MyBatis -->
        <!-- MyBatis中延迟加载需要使用Cglib -->
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
        </dependency>

        <!-- 控制日志输出:结合log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>

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

        <!-- ********其他****************************** -->

        <!-- Ehcache二级缓存 -->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>


        <!-- 石英调度 - 开始 -->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
        </dependency>
        <!-- 石英调度 - 结束 -->

        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
        </dependency>

        <dependency>
            <groupId>org.jfree</groupId>
            <artifactId>jfreechart</artifactId>
        </dependency>

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-email</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-explorer</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>groovy-all</artifactId>
                    <groupId>org.codehaus.groovy</groupId>
                </exclusion>
            </exclusions>
        </dependency>

	</dependencies>
</project>

(4)main

<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.atguigu.maven</groupId>
	<artifactId>Atcrowdfunding-main</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<parent>
		<groupId>com.atguigu.maven</groupId>
		<artifactId>01-Atcrowdfunding-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version> 
		<relativePath>../01-Atcrowdfunding-parent/pom.xml</relativePath>
	</parent>
	     
	<dependencies>
	
		<dependency>
    		<groupId>junit</groupId>
   			<artifactId>junit</artifactId>
   			<version>4.12</version>
   			<scope>test</scope>
     	</dependency>	
		<dependency>
		    <groupId>javax.servlet</groupId>
		    <artifactId>javax.servlet-api</artifactId>
		    <version>4.0.1</version>
		</dependency>
		<dependency>
		    <groupId>javax.servlet.jsp</groupId>
		    <artifactId>javax.servlet.jsp-api</artifactId>
		    <version>2.3.3</version>
		</dependency>
		<dependency>
			<groupId>com.atguigu.maven</groupId>
			<artifactId>Atcrowdfunding-potal-impl</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>com.atguigu.maven</groupId>
			<artifactId>Atcrowdfunding-manager-impl</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>
</project>

(5)manager-api

<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.atguigu.maven</groupId>
  <artifactId>Atcrowdfunding-manager-api</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  	<dependency>
  		<groupId>com.atguigu.maven</groupId>
  		<artifactId>Atcrowdfunding-common</artifactId>
  		<version>0.0.1-SNAPSHOT</version>
  	</dependency>
  	<dependency>
  		<groupId>com.atguigu.maven</groupId>
  		<artifactId>Atcrowdfunding-bean</artifactId>
  		<version>0.0.1-SNAPSHOT</version>
  	</dependency>
  </dependencies>
</project>

(6)manager-impl

<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>
	<artifactId>Atcrowdfunding-manager-impl</artifactId>
	<dependencies>
		<dependency>
			<groupId>com.atguigu.maven</groupId>
			<artifactId>Atcrowdfunding-manager-api</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
		</dependency>
		<dependency>
			<groupId>com.atguigu.maven</groupId>
			<artifactId>Atcrowdfunding-common</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>com.atguigu.maven</groupId>
			<artifactId>Atcrowdfunding-potal-api</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>
	<parent>
		<groupId>com.atguigu.maven</groupId>
		<artifactId>01-Atcrowdfunding-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
		<relativePath>../01-Atcrowdfunding-parent/pom.xml</relativePath>
	</parent>
</project>

(7)potal-api

<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.atguigu.maven</groupId>
  <artifactId>Atcrowdfunding-potal-api</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  	<dependency>
  		<groupId>com.atguigu.maven</groupId>
  		<artifactId>Atcrowdfunding-common</artifactId>
  		<version>0.0.1-SNAPSHOT</version>
  	</dependency>
  	<dependency>
  		<groupId>com.atguigu.maven</groupId>
  		<artifactId>Atcrowdfunding-bean</artifactId>
  		<version>0.0.1-SNAPSHOT</version>
  	</dependency>
  	<dependency>
  		<groupId>com.atguigu.maven</groupId>
  		<artifactId>Atcrowdfunding-manager-api</artifactId>
  		<version>0.0.1-SNAPSHOT</version>
  	</dependency>
  </dependencies>
</project>

(8)potal-impl

<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.atguigu.maven</groupId>
	<artifactId>Atcrowdfunding-potal-impl</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>com.atguigu.maven</groupId>
			<artifactId>Atcrowdfunding-potal-api</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>com.atguigu.maven</groupId>
			<artifactId>Atcrowdfunding-common</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
		</dependency>
	</dependencies>
	<parent>
		<groupId>com.atguigu.maven</groupId>
		<artifactId>01-Atcrowdfunding-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
		<relativePath>../01-Atcrowdfunding-parent/pom.xml</relativePath>
	</parent>
</project>

3.main/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>atcrowdfunding</display-name>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath*:spring/spring-*.xml</param-value>
	</context-param>

	<!-- 监听器 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- 字符编码过滤器 -->
	<filter>
		<filter-name>encoding</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>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encoding</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>


	<filter>
		<filter-name>HiddenHttpMethodFilter</filter-name>
		<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>HiddenHttpMethodFilter</filter-name>
		<servlet-name>springmvc</servlet-name>
	</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:spring/springmvc-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>*.htm</url-pattern>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>

	<!-- 会话超时时间 -->
	<session-config>
		<session-timeout>60</session-timeout>
	</session-config>

	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

 

4.main/spring-context.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:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<context:component-scan base-package="com.atguigu.atcrowdfunding.*" >
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
	</context:component-scan>

	<!-- 加载外部属性配置文件 -->
	<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations" value="classpath:config/jdbc.properties" />
	</bean>
	
	<!-- 配置C3P0数据源 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driver}"/>
		<property name="jdbcUrl" value="${jdbc.url}"/>
		<property name="user" value="${jdbc.user}"/>
		<property name="password" value="${jdbc.password}"/>
	</bean>
	
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	    <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
	    <property name="dataSource" ref="dataSource"></property>
	    <property name="mapperLocations">
	        <list>
	            <value>classpath*:mybatis/mapper-*.xml</value>
	        </list>
	    </property>
	</bean>
	
	<!-- 扫描Mapper映射配置 -->
	<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<!-- <property name="basePackage" value="com.atguigu.atcrowdfunding.manager.dao,com.atguigu.atcrowdfunding.potal.dao"/> -->
		<property name="basePackage" value="com.atguigu.atcrowdfunding.*.dao"/>
	</bean>

	<!-- 事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
	
	<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="*" propagation="REQUIRED" isolation="DEFAULT" rollback-for="java.lang.Exception"/>
			<tx:method name="query*" read-only="true"/>
			<tx:method name="get*" read-only="true"/>
		</tx:attributes>
	</tx:advice>
	
	<aop:config>
		<aop:advisor advice-ref="transactionAdvice" pointcut="execution(* com.atguigu.atcrowdfunding..*Service.*(..))"/>
	</aop:config>		

</beans>

 

5.main/springmvc-context.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:p="http://www.springframework.org/schema/p"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
		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-4.0.xsd">

    <context:component-scan base-package="com.atguigu.atcrowdfunding.*" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    <!-- 启用注解功能 -->
    <context:annotation-config />
    
    <!-- 字符串字符编码转换 -->
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" >
        <property name="messageConverters">   
	         <list>
	             <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">   
	                <property name="supportedMediaTypes">
	                      <list>
	                          <value>application/json;charset=UTF-8</value>
	                     </list>   
	                </property>   
	             </bean>   
	         </list>   
	    </property>
    </bean>
	
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    
    <bean id="exceptionResolver"  
        class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">  
        <property name="exceptionMappings">  
            <props>
                <prop key="java.lang.Exception">error/error</prop>
            </props>  
        </property>  
    </bean>

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="UTF-8">
        <property name="maxUploadSize" value="2097152"/>
        <property name="resolveLazily" value="true"/>
    </bean>
</beans>

 

6./Atcrowdfunding-main/src/main/resources/config/jdbc.properties

jdbc.user=root
jdbc.password=123456
jdbc.url=jdbc:mysql://172.20.184.149:3305/atcrowdfunding170615?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false
jdbc.driver=com.mysql.cj.jdbc.Driver

等号前后不能有空格,用户名密码前后不能用空格

7.log4j.properties


# DEBUG < INFO < WARN < ERROR < FATAL
log4j.rootLogger=DEBUG, stdout


log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss S} %5p %c:%l - %m%n



#log4j.logger.org.hibernate=INFO

8.使用弹窗提示消息

(1)加入弹窗库

<script type="text/javascript" src="${APP_PATH }/jquery/layer/layer.js"></script>

(2)代码

    function dologin() {
    	/* $("#loginForm").submit(); */
    	
    	var floginacct = $("#floginacct");
    	var fuserpswd = $("#fuserpswd");
    	var ftype = $("#ftype");
    	
    	if($.trim(floginacct.val())==""){
//    		alert("用户账号不能为空,请重新输入!");
/**
 * time:1000,  显示1000ms
 icon:5,    显示第5个图案,一个哭脸
 shift:6    弹窗抖动
 */
    		layer.msg("用户账号不能为空,请重新输入!",{time:1000, icon:5, shift:6}, function(){   
    			floginacct.val("");
        		floginacct.focus();
    		});
    		return false;  //结束if
    	}
    	
    	if($.trim(fuserpswd.val())==""){
    	//	alert("用户密码不能为空,请重新输入!");
    		layer.msg("用户密码不能为空,请重新输入!",{time:1000, icon:5, shift:6}, function(){
    		fuserpswd.val("");
    		fuserpswd.focus();
    		});
    		return false;
    	}
    	
    	var loadingIndex = -1 ;
    	
    	$.ajax({
    		type : "POST",
    		data : {
    			loginacct : floginacct.val(),
    			userpswd : fuserpswd.val(),
    			type : ftype.val()
    		},
    		url : "${APP_PATH}/doLogin.do",
    		beforeSend : function(){
    			loadingIndex = layer.msg('处理中', {icon: 16});//转圈的图案
    			//一般做表单数据校验.
    			return true ;
    		},
    		success : function(result){ //{"success":true}  或    {"success":false,"message":"登录失败!"}
    			if(result.success){    
    				layer.close(loadingIndex);//关闭loadingIndex = layer.msg('处理中', {icon: 16})的layer
    				window.location.href="${APP_PATH}/main.htm";
    			}else{
    				layer.msg(result.message, {time:1000, icon:5, shift:6});
    			}
    		},
    		error : function(){
    			layer.msg("登录失败!", {time:1000, icon:5, shift:6});
    		}	
    	});
}

 

9.用户查询,自己手写分页

(1)时序图

(2)手写分页,同步,见

https://blog.csdn.net/weixin_44595287/article/details/102949425

(3)手写分页,异步,见

https://blog.csdn.net/weixin_44595287/article/details/102953678

(4)用户模糊查询

①从表单中用id 提取模糊查询文本id="queryText" , 和激发按钮函数 id="queryBtn"

<form class="form-inline" role="form" style="float: left;">
	<div class="form-group has-feedback">
		<div class="input-group">
			<div class="input-group-addon">查询条件</div>
			<input id="queryText" class="form-control has-success" type="text"
				placeholder="请输入查询条件">
		</div>
	</div>
	<button id="queryBtn" type="button" class="btn btn-warning">
		<i class="glyphicon glyphicon-search"></i> 查询
	</button>
</form>

②用#提取queryText, 和激活按钮

$("#queryBtn").click(function(){
	var queryText = $("#queryText").val();
	jsonObj.queryText =  queryText ;  //将值传入jsonObj
	queryPageUser(1);
});

③修改UserController,注意对出现%时需要转义

//异步分页模糊查询
@ResponseBody
@RequestMapping("/doIndex")
public Object index(@RequestParam(value="pageno",required=false,defaultValue="1") Integer pageno,
@RequestParam(value="pagesize",required=false,defaultValue="10") Integer pagesize, String queryText){
	
	AjaxResult result = new AjaxResult();
	
	try {
		
		Map paramMap = new HashMap();
		paramMap.put("pageno", pageno);
		paramMap.put("pagesize", pagesize);
		
		if(StringUtil.isNotEmpty(queryText)){
			if(queryText.contains("%")){
				//sql語句中默认%为匹配任何字符,需要转义,还需要其他转义,所以一共需要4个\
				queryText = queryText.replaceAll("%", "\\\\%");  
			}
			paramMap.put("queryText", queryText);  // \%
		}
		
		Page page = userService.queryPage(paramMap);//Map可以使用Mybatis的条件函数
		
		result.setSuccess(true);
		result.setPage(page);
		
	} catch (Exception e) {
		result.setSuccess(false);
		e.printStackTrace();
		result.setMessage("查询数据失败!");
	}
	return result;  //以流的形式传入序列化JSON数据
}

④修改UserMapper.java

	//加模糊查询
	List<User> queryList(Map<String, Object> paramMap);
	Integer queryCount(Map<String, Object> paramMap);

⑤修改UsrMapper.xml,使用条件进行模糊查询。concat用于sql拼接字符串

<select id="queryList" resultMap="BaseResultMap ">
	select id, loginacct, userpswd,
	username, email, createtime
	from t_user 
	<where>
		<if test="queryText!=null">loginacct like concat("%",#{queryText},"%")</if>
	</where>
	limit #{startIndex},#{pagesize}
</select>

<select id="queryCount" resultType="int">
	select count(*)
	from t_user 
	<where>
		<if test="queryText!=null">loginacct like concat("%",#{queryText},"%")</if>
	</where>
</select>

10.新增user功能

(1)发出请求

<button type="button" class="btn btn-primary"
	style="float: right;" onclick="window.location.href='${APP_PATH}/user/add.htm'">
	<i class="glyphicon glyphicon-plus"></i> 新增
</button>

(2)UserController

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

//增加
@ResponseBody
@RequestMapping("/doAdd")
public Object doAdd(User user){  //由前端传来的数据自动封装成User
	
	AjaxResult result = new AjaxResult();
	
	try {
		int count = userService.saveUser(user);//需要在impl中手动添加默认密码和createtime
		
		result.setSuccess(count==1);			
		
	} catch (Exception e) {
		result.setSuccess(false);
		e.printStackTrace();
		result.setMessage("添加数据失败!");
	}
	return result;  //以流的形式传入序列化JSON数据
}

(3)提取表单数据    id="floginacct",for使用和id相同的值,可以使点击lable标签也能选中input表单,使用体验好

  <div class="form-group">
	<label for="floginacct">登陆账号</label>
	<input type="text" class="form-control" id="floginacct" placeholder="请输入登陆账号">
  </div>
  <div class="form-group">
	<label for="fusername">用户名称</label>
	<input type="text" class="form-control" id="fusername" placeholder="请输入用户名称">
  </div>
  <div class="form-group">
	<label for="femail">邮箱地址</label>
	<input type="email" class="form-control" id="femail" placeholder="请输入邮箱地址">
	<p class="help-block label label-warning">请输入合法的邮箱地址, 格式为: xxxx@xxxx.com</p>
  </div>

 (4)提取表单对象和值,传到后方封装

var floginacct = $("#floginacct");提取对象

"loginacct" : floginacct.val() 提取值
 

<script type="text/javascript">
	$(function () {
		$(".list-group-item").click(function(){
			if ( $(this).find("ul") ) {
				$(this).toggleClass("tree-closed");
				if ( $(this).hasClass("tree-closed") ) {
					$("ul", this).hide("fast");
				} else {
					$("ul", this).show("fast");
				}
			}
		});
	});
	
	$("#addBtn").click(function(){
		
		var floginacct = $("#floginacct");
		var fusername = $("#fusername");
		var femail = $("#femail");
		
		
		$.ajax({
			type : "POST",
			data : {
				"loginacct" : floginacct.val(),
				"username" : fusername.val(),
				"email" : femail.val()            			
			},
			url : "${APP_PATH}/user/doAdd.do",
			beforeSend : function() {            			
				return true ;
			},
			success : function(result){
				if(result.success){
					window.location.href="${APP_PATH}/user/index.htm";
				}else{
					layer.msg("保存用户失败", {time:1000, icon:5, shift:6}); 
				}
			},
			error : function(){
				layer.msg("保存失败", {time:1000, icon:5, shift:6}); 
			}
		});
		
	});
		
	
</script>

(5)成功后调回主页面

window.location.href="${APP_PATH}/user;成功后调回主页面

JavaScript中使用window.location.href跳转,为同步请求,异步用function

(6)重置功能

见笔记

$("#resetBtn").click(function(){
    $("#updateForm")[0].reset();
});

11.修改(加回显)、删除、批量删除

(1)先回显,再修改,

①同步使用发出请求,带上id用于查询后回显

οnclick="window.location.href=\'${APP_PATH}/user/toUpdate.htm?id='+n.id+'\' "

content+='	  <button type="button" onclick="window.location.href=\'${APP_PATH}/user/toUpdate.htm?id='+n.id+'\'" class="btn btn-primary btn-xs"><i class=" glyphicon glyphicon-pencil"></i></button>';

UserController.

查询回显数据,存入map返回

@RequestMapping("/toUpdate")
public String toUpdate(Integer id,Map map){
	
	User user = userService.getUserById(id);
	map.put("user", user);
	
	return "user/update";
}

②/user/update.jsp

回显,提取回显值

value="${user.loginacct }

<form id="updateForm">
	<div class="form-group">
		<label for="exampleInputPassword1">登陆账号</label> <input type="text"
			class="form-control" id="floginacct" value="${user.loginacct }">
	</div>
	<div class="form-group">
		<label for="exampleInputPassword1">用户名称</label> <input type="text"
			class="form-control" id="fusername" value="${user.username }">
	</div>
	<div class="form-group">
		<label for="exampleInputEmail1">邮箱地址</label> <input type="email"
			class="form-control" id="femail" value="${user.email }">
		<p class="help-block label label-warning">请输入合法的邮箱地址, 格式为:
			xxxx@xxxx.com</p>
	</div>

③修改,异步刷新

$("#updateBtn").click(function(){
	var floginacct = $("#floginacct");
	var fusername = $("#fusername");
	var femail = $("#femail");
	
	
	$.ajax({
		type : "POST",
		data : {
			"loginacct" : floginacct.val(),
			"username" : fusername.val(),
			"email" : femail.val(),
			"id" : "${user.id}"
		},
		url : "${APP_PATH}/user/doUpdate.do",
		beforeSend : function() {            			
			return true ;
		},
		success : function(result){
			if(result.success){
				window.location.href="${APP_PATH}/user/index.htm";
			}else{
				layer.msg("修改用户失败", {time:1000, icon:5, shift:6}); 
			}
		},
		error : function(){
			layer.msg("修改失败", {time:1000, icon:5, shift:6}); 
		}
	});            	
});

(2)删除

①发出请求,异步

异步使用

οnclick="deleteUser('+n.id+',\''+n.loginacct+'\')"   //进入方法

content+='	  <button type="button" onclick="deleteUser('+n.id+',\''+n.loginacct+'\')" class="btn btn-danger btn-xs"><i class=" glyphicon glyphicon-remove"></i></button>';
function deleteUser(id,loginacct){
	layer.confirm("确认要删除["+loginacct+"]用户吗?",  {icon: 3, title:'提示'}, function(cindex){
		layer.close(cindex);
		$.ajax({
    		type : "POST",
    		data : {
    			"id" : id
    		},
    		url : "${APP_PATH}/user/doDelete.do",
    		beforeSend : function() {   
    			return true ;
    		},
    		success : function(result){
    			if(result.success){
    				window.location.href="${APP_PATH}/user/index.htm";
         			}else{
         				layer.msg("删除用户失败", {time:1000, icon:5, shift:6}); 
         			}
         		},
         		error : function(){
         			layer.msg("删除失败", {time:1000, icon:5, shift:6}); 
         		}
         	});
}, function(cindex){
    layer.close(cindex);
});            	         
     	
     }

 

②在UserController中添加doDelete方法,并返回result

@ResponseBody
@RequestMapping("/doDelete")
public Object doDelete(Integer id){  
	
	AjaxResult result = new AjaxResult();
	
	try {
		int count = userService.deleteUser(id);
		
		result.setSuccess(count==1);			
		
	} catch (Exception e) {
		result.setSuccess(false);
		e.printStackTrace();
		result.setMessage("删除数据失败!");
	}
	return result; 
}
    }

 (3)批量删除(每一行封装为难点)

①取出全选框allcheckbox的对象

<th width="30"><input id="allCheckbox" type="checkbox"></th>
content+='  <td><input id="'+n.id+'" name="'+n.loginacct+'" type="checkbox"></td>';

②取出allcheckbox的当前是否被选中的值"#allCheckbox".checked

当点击全选框时,将全选框的值赋给表单的每个框

var checkStatus  = this.checked;  // 选中时为true,未选中时为false

$("tbody tr td input[type='checkbox']")  //表示标签tbody下的tr下的td下的input里面type='checkbox'对象

prop("checked",checkStatus);赋值操作,将checkStatus复制给checked属性

$("#allCheckbox").click(function(){
	var checkStatus  = this.checked;
	/* alert(checkStatus); */
	$("tbody tr td input[type='checkbox']").prop("checked",checkStatus);
});

 

③点批量删除操作

<button type="button" class="btn btn-danger" id="deleteBatchBtn"
	style="float: right; margin-left: 10px;">
	<i class=" glyphicon glyphicon-remove"></i> 删除
</button>

④checkbox中放入值供取出

content+='  <td><input id="'+n.id+'" loginacct="'+n.loginacct+'" type="checkbox"></td>';

 

$("#deleteBatchBtn").click(function(){
	var selectCheckbox = $("tbody tr td input:checked"); //true取出被选择的对象
	if(selectCheckbox.length==0){    //计算选择对象的个数
		layer.msg("请至少选择一个用户删除", {time:1000, icon:5, shift:6});
		return false;
	}
	
	var jsonObj = {};   //将选择的每一行封装为一个对象
	
	$.each(selectCheckbox,function(i,n){  //n为selectCheckbox里的元素,i为当前元素索引
		jsonObj["datas["+i+"].id"] = n.id;
		jsonObj["datas["+i+"].loginacct"] = n.loginacct;  //从checkbox中取值
	})
	layer.confirm("确认要删除所选用户吗?",  {icon: 3, title:'提示'}, function(cindex){
		layer.close(cindex);
		$.ajax({
			type : "POST",
			data : jsonObj,
			url : "${APP_PATH}/user/doDeleteBatch.do",
			beforeSend : function() {   
				return true ;
			},
			success : function(result){
				if(result.success){
					window.location.href="${APP_PATH}/user/index.htm";
				}else{
					layer.msg("删除用户失败", {time:1000, icon:5, shift:6}); 
				}
			},
			error : function(){
				layer.msg("删除失败", {time:1000, icon:5, shift:6}); 
			}
		});
	}, function(cindex){
		layer.close(cindex);
	});            	         
				
});

⑤Data.java

public class Data {

	private List<User> datas = new ArrayList<User>();

	public List<User> getDatas() {
		return datas;
	}

	public void setDatas(List<User> datas) {
		this.datas = datas;
	}

}

⑥UserController

@ResponseBody
@RequestMapping("/doDeleteBatch")
public Object doDeleteBatch(Data data){  //由前端传来的数据自动封装成User
	
	AjaxResult result = new AjaxResult();
	
	try {
		int count = userService.deleteBatchUserByVO(data);
		
		result.setSuccess(count==data.getDatas().size());			
		
	} catch (Exception e) {
		result.setSuccess(false);
		e.printStackTrace();
		result.setMessage("批量删除数据失败!");
	}
	return result; 
}

⑦UserService

int deleteBatchUserByVO(Data data);

⑧UserServiceImpl

@Override
public int deleteBatchUserByVO(Data data) {		
	return userMapper.deleteBatchUserByVO(data.getDatas());
}

⑨UserMapper.java  (MyBatis中使用List必须要指名@Param("userList")

int deleteBatchUserByVO(@Param("userList") List<User> userList);

⑩UserMapper.xml

<delete id="deleteBatchUserByVO" >
	delete from t_user where id in
	<foreach collection="userList" open="(" close=")" separator="," item="user">
		#{user.id}
	</foreach>
</delete>

12.抽取menu.jsp和top.jsp

两种方法引用

方法1:

<jsp:include page="/WEB-INF/common/top.jsp"></jsp:include>

方法2:

<%@ include file="/WEB-INF/jsp/common/top.jsp" %>

 top.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<li style="padding-top: 8px;">
	<div class="btn-group">
		<button type="button"
			class="btn btn-default btn-success dropdown-toggle"
			data-toggle="dropdown">
			<i class="glyphicon glyphicon-user"></i>${sessionScope.user.username }<span
				class="caret"></span>
		</button>
		<ul class="dropdown-menu" role="menu">
			<li><a href="#"><i class="glyphicon glyphicon-cog"></i> 个人设置</a></li>
			<li><a href="#"><i class="glyphicon glyphicon-comment"></i>
					消息</a></li>
			<li class="divider"></li>
			<li><a href="${APP_PATH }/logout.do"><i
					class="glyphicon glyphicon-off"></i> 退出系统</a></li>
		</ul>
	</div>
</li>
<li style="margin-left: 10px; padding-top: 8px;">
	<button type="button" class="btn btn-default btn-danger">
		<span class="glyphicon glyphicon-question-sign"></span> 帮助
	</button>
</li>

menu.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<ul style="padding-left:0px;" class="list-group">
	<c:forEach items="${sessionScope.permissionRoot.children }" var="permission">
		<c:if test="${empty permission.children}">
			<li class="list-group-item tree-closed" >
				<a href="${APP_PATH }/${permission.url }"><i class="${permission.icon}"></i> ${permission.name }</a> 
			</li>
		</c:if>
		<c:if test="${not empty permission.children}" >
			<li class="list-group-item tree-closed">
				<span><i class="${permission.icon}"></i> ${permission.name } <span class="badge" style="float:right">${fn:length(permission.children)}    <%-- ${permission.children.size() } --%></span></span> 
				<ul style="margin-top:10px;display:none;">
					<c:forEach items="${permission.children }" var="innerPermission">
						<li style="height:30px;">					
							<a href="${APP_PATH }/${innerPermission.url}"><i class="${innerPermission.icon }"></i> ${innerPermission.name }</a> 
						</li>
					</c:forEach>
				</ul>
			</li>
		</c:if>
	</c:forEach> 
	
</ul>

13.被选中的菜单默认展开,并标红

(1)抽取为menu.js文件

function showMenu(){
	var href = window.location.href ; // http://localhost:8888/Atcrowdfunding-main/user/index.htm
	var host = window.location.host ;// localhost:8888
	var index = href.indexOf(host);//7
	var path = href.substring(index + host.length); // /Atcrowdfunding-main/user/index.htm
	var contextPath = "${APP_PATH}"; //  /Atcrowdfunding-main
	var pathAddress = path.substring(contextPath.length+1);// user/index.htm
	
	var alink = $(".list-group a[href*='"+pathAddress+"']");//取出class="list-group"里面<a href*与pathAddress匹配成功的标签
	
	alink.css("color","red");//设为红色
	
	alink.parent().parent().parent().removeClass("tree-closed");//alink 的父父父标签,即<li class="list-group-item去掉tree-closed,即不关闭
	alink.parent().parent().show();
}

(2)引用

<script type="text/javascript" src="${APP_PATH }/script/menu.js"></script>

(3)在函数中使用showMenu()调用

<script type="text/javascript">
	$(function () {
		$(".list-group-item").click(function(){
			if ( $ (this).find("ul") ) {
				$(this).toggleClass("tree-closed");
				if ( $(this).hasClass("tree-closed") ) {
					$("ul", this).hide("fast");
				} else {
					$("ul", this).show("fast");
				}
			}
		});
		queryPageUser(0);
		showMenu();
	});

 

14.用户管理模块,分配角色

(1)首先显示已有角色

①发出请求user/index.jsp

content+='	  <button type="button" onclick="window.location.href=\'${APP_PATH}/user/assignRole.htm?id='+n.id+'\'" class="btn btn-success btn-xs"><i class=" glyphicon glyphicon-check"></i></button>';

②UserController

@RequestMapping("/assignRole")
public String assignRole(Integer id,Map map){
	
	List<Role> allListRole = userService.queryAllRole();
	List<Integer> roleIds = userService.queryRoleByUserid(id);
	
	List<Role> leftRoleList = new ArrayList<Role>(); //未分配角色
	List<Role> rightRoleList = new ArrayList<Role>(); //已分配角色
	
	for (Role role : allListRole) {
		if(roleIds.contains(role.getId())){
			rightRoleList.add(role);
		}else{
			leftRoleList.add(role);
		}
	}
	
	map.put("leftRoleList", leftRoleList);
	map.put("rightRoleList", rightRoleList);
	
	return "user/assignrole";
}

③UserMapper.xml

<select id="queryRoleByUserid" parameterType="int" resultType="int">
    select roleid from t_user_role where userid = #{id}
</select>

④显示已有和未有角色user/assignrole.jsp

<form role="form" class="form-inline">
  <div class="form-group">
	<label for="exampleInputPassword1">未分配角色列表</label><br>
	<select id="leftRoleList" class="form-control" multiple size="10" style="width:250px;overflow-y:auto;">
		<c:forEach items="${leftRoleList }" var="role">
			<option value="${role.id }">${role.name }</option>
		</c:forEach>                      
	</select>
  </div>
  <div class="form-group">
		<ul>
		    <li id="leftToRightBtn" class="btn btn-default glyphicon glyphicon-chevron-right"></li>
			<br/>
		    <li id="rightToLeftBtn" class="btn btn-default glyphicon glyphicon-chevron-left" style="margin-top:20px;"></li>
		</ul>
  </div>
  <div class="form-group" style="margin-left:40px;">
	<label for="exampleInputPassword1">已分配角色列表</label><br>
	<select id="rightRoleList" class="form-control" multiple size="10" style="width:250px;overflow-y:auto;">
		<c:forEach items="${rightRoleList }" var="role">
			<option value="${role.id }">${role.name }</option>
		</c:forEach>  
	</select>
  </div>
</form>

(2)添加和删除角色

①异步操作

$("#leftToRightBtn").click(function(){
	var selectedOptions = $("#leftRoleList option:selected");//选中的对象

	var num  = selectedOptions.size();//计算选中的个数
	
	if(num==0){
		layer.msg("左侧请至少选择一个角色", {time:1000, icon:5, shift:6});
		return false;
	} 

	var jsonObj = {
		userid : "${param.id}"
	};
	
	$.each(selectedOptions,function(i,n){
		jsonObj["ids["+i+"]"] = this.value ;  
	});
	
	var loadingIndex = -1 ;
	$.ajax({
			type : "POST",
			data : jsonObj,
			url : "${APP_PATH}/user/doAssignRole.do",
			beforeSend : function(){      
				loadingIndex = layer.load(2, {time: 10*1000});
				return true ;
			},
			success : function(result){
				layer.close(loadingIndex);
				if(result.success){
					$("#rightRoleList").append(selectedOptions.clone());//rightRoleList中添加选中的option对象
					selectedOptions.remove();//移除选中的option对象
				}else{
					layer.msg(result.message, {time:1000, icon:5, shift:6});
				}
			},
			error : function(){
				layer.msg("操作失败!", {time:1000, icon:5, shift:6});
			}
			
		});
});

$("#rightToLeftBtn").click(function(){
	var selectedOptions = $("#rightRoleList option:selected");
	
	var num  = selectedOptions.size();
	if(num==0){
		layer.msg("右侧请至少选择一个角色", {time:1000, icon:5, shift:6});
		return false;
	}
	
	var jsonObj = {
		userid : "${param.id}"
	};
	
	$.each(selectedOptions,function(i,n){
		jsonObj["ids["+i+"]"] = this.value ;  
	});
	
	var loadingIndex = -1 ;
		$.ajax({
			type : "POST",
			data : jsonObj,
			url : "${APP_PATH}/user/doUnAssignRole.do",
			beforeSend : function() { 
				loadingIndex = layer.load(2, {time: 10*1000});
				return true ;
			},
			success : function(result){
				layer.close(loadingIndex);
				if(result.success){
					$("#leftRoleList").append(selectedOptions.clone());
					selectedOptions.remove();
				}else{
					layer.msg(result.message, {time:1000, icon:5, shift:6});
				}
			},
			error : function(){
				layer.msg("操作失败!", {time:1000, icon:5, shift:6}); 
				layer.close(loadingIndex);
			}
		});	         
});

②UserController

@ResponseBody
@RequestMapping("/doAssignRole")
public Object doAssignRole(Integer userid, Data data){  //List<Integer> ids
	
	AjaxResult result = new AjaxResult();
	
	try {
		int count = userService.saveUserRoleRelationship(userid,data);
		
		result.setSuccess(true);			
		
	} catch (Exception e) {
		result.setSuccess(false);
		e.printStackTrace();
		result.setMessage("添加角色失败!");
	}
	return result; 
}

@ResponseBody
@RequestMapping("/doUnAssignRole")
public Object doUnAssignRole(Integer userid,Data data){  //List<Integer> ids
	
	AjaxResult result = new AjaxResult();
	
	try {
		userService.deleteUserRoleRelationship(userid,data);;
		
		result.setSuccess(true);			
		
	} catch (Exception e) {
		result.setSuccess(false);
		e.printStackTrace();
		result.setMessage("取消角色失败!");
	}
	return result; 
}

③UserMapper.xml

<insert id="saveUserRoleRelationship">
	<foreach collection="data.ids" item="roleid" separator=";">
		insert into t_user_role(userid,roleid) values(#{userid},#{roleid})
	</foreach>
</insert>

<delete id="deleteUserRoleRelationship" >
	delete from t_user_role where userid=#{userid} and roleid in
	<foreach collection="data.ids" item="roleid" open="(" separator="," close=")">
		#{roleid}
	</foreach>
</delete>

15.以树形z-tree展示权限图,添加,修改,删除【本项目一共3层,根节点->一级节点->叶子节点】

(1)引入z-tree插件

<script src="${APP_PATH }/ztree/jquery.ztree.all-3.5.min.js"></script>

(2)permission/index.jsp

<script type="text/javascript">
	$(function () {
		$(".list-group-item").click(function(){
			if ( $(this).find("ul") ) {
				$(this).toggleClass("tree-closed");
				if ( $(this).hasClass("tree-closed") ) {
					$("ul", this).hide("fast");
				} else {
					$("ul", this).show("fast");
				}
			}
		});
		
		loadData();
		
	});   
	
	
	
  
	var setting = {
		view : {
			addDiyDom: function(treeId, treeNode){
				var icoObj = $("#" + treeNode.tId + "_ico"); // tId = permissionTree_1, $("#permissionTree_1_ico")
				if ( treeNode.icon ) {
					icoObj.removeClass("button ico_docu ico_open").addClass(treeNode.icon).css("background","");
				}
			},
			addHoverDom: function(treeId, treeNode){   //设置自定义按钮组,在节点后面悬停显示增删改按钮组.
				var aObj = $("#" + treeNode.tId + "_a"); // tId = permissionTree_1, ==> $("#permissionTree_1_a")
				aObj.attr("href", "javascript:;"); // 取消当前链接事件.
				if (treeNode.editNameFlag || $("#btnGroup"+treeNode.tId).length>0) return;
				var s = '<span id="btnGroup'+treeNode.tId+'">';
				if ( treeNode.level == 0 ) { //根节点
					s += '<a class="btn btn-info dropdown-toggle btn-xs" style="margin-left:10px;padding-top:0px;" href="#" onclick="window.location.href=\'${APP_PATH}/permission/toAdd.htm?id='+treeNode.id+'\'" >&nbsp;&nbsp;<i class="fa fa-fw fa-plus rbg "></i></a>';
				} else if ( treeNode.level == 1 ) { //分支节点
					s += '<a class="btn btn-info dropdown-toggle btn-xs" style="margin-left:10px;padding-top:0px;"  href="#" onclick="window.location.href=\'${APP_PATH}/permission/toUpdate.htm?id='+treeNode.id+'\'" title="修改权限信息">&nbsp;&nbsp;<i class="fa fa-fw fa-edit rbg "></i></a>';
					if (treeNode.children.length == 0) {
						s += '<a class="btn btn-info dropdown-toggle btn-xs" style="margin-left:10px;padding-top:0px;" href="#" onclick="deletePermission('+treeNode.id+',\''+treeNode.name+'\')">&nbsp;&nbsp;<i class="fa fa-fw fa-times rbg "></i></a>';
					}                                                                                                               
					s += '<a class="btn btn-info dropdown-toggle btn-xs" style="margin-left:10px;padding-top:0px;" href="#" onclick="window.location.href=\'${APP_PATH}/permission/toAdd.htm?id='+treeNode.id+'\'">&nbsp;&nbsp;<i class="fa fa-fw fa-plus rbg "></i></a>';
				} else if ( treeNode.level == 2 ) { //叶子节点
					s += '<a class="btn btn-info dropdown-toggle btn-xs" style="margin-left:10px;padding-top:0px;"  href="#"  onclick="window.location.href=\'${APP_PATH}/permission/toUpdate.htm?id='+treeNode.id+'\'" title="修改权限信息">&nbsp;&nbsp;<i class="fa fa-fw fa-edit rbg "></i></a>';
					s += '<a class="btn btn-info dropdown-toggle btn-xs" style="margin-left:10px;padding-top:0px;" href="#" onclick="deletePermission('+treeNode.id+',\''+treeNode.name+'\')">&nbsp;&nbsp;<i class="fa fa-fw fa-times rbg "></i></a>';
				}

				s += '</span>';
				aObj.after(s);
			},
			removeHoverDom: function(treeId, treeNode){
				$("#btnGroup"+treeNode.tId).remove();
			}

	   }
	};

	/* var zNodes =[
		{ name:"父节点1 - 展开", open:true,
			children: [
				{ name:"父节点11 - 折叠",
					children: [
						{ name:"叶子节点111"},
						{ name:"叶子节点112"},
						{ name:"叶子节点113"},
						{ name:"叶子节点114"}
					]},
				{ name:"父节点12 - 折叠",
					children: [
						{ name:"叶子节点121"},
						{ name:"叶子节点122"},
						{ name:"叶子节点123"},
						{ name:"叶子节点124"}
					]},
				{ name:"父节点13 - 没有子节点", isParent:true}
			]},
		{ name:"父节点2 - 折叠",
			children: [
				{ name:"父节点21 - 展开", open:true,
					children: [
						{ name:"叶子节点211"},
						{ name:"叶子节点212"},
						{ name:"叶子节点213"},
						{ name:"叶子节点214"}
					]},
				{ name:"父节点22 - 折叠",
					children: [
						{ name:"叶子节点221"},
						{ name:"叶子节点222"},
						{ name:"叶子节点223"},
						{ name:"叶子节点224"}
					]},
				{ name:"父节点23 - 折叠",
					children: [
						{ name:"叶子节点231"},
						{ name:"叶子节点232"},
						{ name:"叶子节点233"},
						{ name:"叶子节点234"}
					]}
			]},
		{ name:"父节点3 - 没有子节点", isParent:true}

	]; */
	
	

	 function loadData(){
		$.ajax({
			
			url:"${APP_PATH}/permission/loadData.do",
			type:"post",
			success:function(result){
				if(result.success){
					 var zNodes = result.data ;
					 $.fn.zTree.init($("#treeDemo"), setting, zNodes);
				}else{
					alert("加载数据失败...");
				}
			}
			
		});
	}
																																											 
	
	/* $(document).ready(function(){
		$.fn.zTree.init($("#treeDemo"), setting, zNodes);
	}); */
	
	function deletePermission(id,name){
		
		layer.confirm("确定要删除["+name+"]许可吗?",  {icon: 3, title:'提示'}, function(cindex){
			layer.close(cindex);
			$.ajax({
				
				url:"${APP_PATH}/permission/deletePermission.do",
				data : {
					"id" : id
				},
				type:"post",
				success:function(result){
					if(result.success){
						loadData();
					}else{
						alert("删除许可数据失败...");
					}
				}
				
			});
		}, function(cindex){
			layer.close(cindex);
		});
	}
	
	
	
</script>

(3)PermissionController.java

只查询一次数据库,数据放入map中,后用于调用,效率高

	@RequestMapping("/index")
	public String index(){
		return "permission/index";
	}
	
	@ResponseBody
	@RequestMapping("/loadData")
	public Object loadData(){
		AjaxResult result = new AjaxResult();
		try {
			List<Permission> root = new ArrayList<Permission>();
			List<Permission> childrenPermissions = permissionService.queryAllPermission();
			
			Map<Integer,Permission> map = new HashMap<Integer,Permission>();
			
			for(Permission innerpermission: childrenPermissions){
				map.put(innerpermission.getId(),innerpermission );//把查出来的数据全部放入map中使用,不
			}
			
			for(Permission permission : childrenPermissions){  //利用递归,一个嵌套的Jason数据,通过F12-network看请求发送的数据
				Permission child = permission;
				
				if(child.getPid()==null){
					root.add(child);
				}else{
					Permission parent = map.get(child.getPid());
					parent.getChildren().add(child);
				}
			}
			result.setSuccess(true);		
			result.setData(root);
		} catch (Exception e) {
			result.setSuccess(false);
			e.printStackTrace();
			result.setMessage("加载许可数失败!");
		}

		return result ;
	}

递归最后得到的data(root)结果为嵌套的json,传回前端由z-tree自动解析树形展示

/*     * {"success":true,"message":null,"page":null,
     * "data":[{"id":null,"pid":null,"name":"系统权限菜单","icon":null,"url":null,"open":true,
     * "children":[{"id":null,"pid":null,"name":"控制面板","icon":null,"url":null,"open":false,"children":null},
     * {"id":null,"pid":null,"name":"权限管理","icon":null,"url":null,"open":false,"children":null}]}]}*/

(4)修改、删除和role操作差不多,省略

16.为每位角色分配权限

(1)显示权限树,并在已有权限复选框打勾

role/assignPermission.jsp

<script src="${APP_PATH }/jquery/jquery-2.1.1.min.js"></script>
<script src="${APP_PATH }/bootstrap/js/bootstrap.min.js"></script>
<script src="${APP_PATH }/script/docs.min.js"></script>
<script src="${APP_PATH }/ztree/jquery.ztree.all-3.5.min.js"></script>
<script src="${APP_PATH}/jquery/layer/layer.js"></script>
	<script type="text/javascript">
		$(function () {
			$(".list-group-item").click(function(){
				if ( $(this).find("ul") ) {
					$(this).toggleClass("tree-closed");
					if ( $(this).hasClass("tree-closed") ) {
						$("ul", this).hide("fast");
					} else {
						$("ul", this).show("fast");
					}
				}
			});
			
	                var setting = {
				check : {
					enable : true  //在树节点前显示复选框
				},
				view: {
					selectedMulti: true,//不支持多选
					addDiyDom: function(treeId, treeNode){
						var icoObj = $("#" + treeNode.tId + "_ico"); // tId = permissionTree_1, $("#permissionTree_1_ico")
						if ( treeNode.icon ) {
							icoObj.removeClass("button ico_docu ico_open").addClass(treeNode.icon).css("background","");
						}
					},
				},
				async: {
					enable: true, //采用异步
					url:"${APP_PATH}/role/loadDataAsync.do?roleid=${param.roleid}", // ?id=1&n=xxx&lv=2
					autoParam:["id", "name=n", "level=lv"]
				},
				callback: {
					onClick : function(event, treeId, json) {

					}
				}
			};
			
			//异步加载树:注意问题,服务器端返回的结果必须是一个数组.
			$.fn.zTree.init($("#treeDemo"), setting); //异步加载树的数据.
			//$.fn.zTree.init($("#treeDemo"), setting , ztreeJSON);//同步加载树的数据.
		});
		
		$("#assignPermissionBtn").click(function(){
			
				var jsonObj = {
					"roleid" : "${param.roleid}"
				};
				
				var treeObj = $.fn.zTree.getZTreeObj("treeDemo");

				var checkedNodes = treeObj.getCheckedNodes(true); // 获取被选中的节点

				
				$.each(checkedNodes,function(i,n){
					jsonObj["ids["+i+"]"] = n.id;
				});
				
				
				if(checkedNodes.length == 0){
					layer.msg("请选择分配许可,至少分配一个许可!", {time:1000, icon:5, shift:6}); 
				}else{
					var loadingIndex = -1 ;
					$.ajax({
						type : "POST",
						url : "${APP_PATH}/role/doAssignPermission.do",    			     
						data : jsonObj,  
						beforeSend : function(){
							loadingIndex = layer.msg('正在分配许可...', {icon: 16});
							return true ;
						},
						success : function(result){
							
							layer.close(loadingIndex);
							
							if(result.success){	            			
								layer.msg("分配成功", {time:1000, icon:6}); 

							}else{
								layer.msg("分配失败", {time:1000, icon:5, shift:6}); 
							}
							
						},
						error : function(){
							layer.msg("操作失败!", {time:1000, icon:5, shift:6}); 
						}
					});
				}
			
		});
		
	</script>    

(2)在已有的权限复选框打勾,用checked控制,checke为true时打勾(由z-tree提供)

RoleController.java

@ResponseBody
@RequestMapping("/loadDataAsync")
public Object loadDataAsync(Integer roleid){
	
	List<Permission> root = new ArrayList<Permission>();
	
	List<Permission> childredPermissons =  permissionService.queryAllPermission();
	
	
	//根据角色id查询该角色之前所分配过的许可.
	List<Integer> permissonIdsForRoleid = permissionService.queryPermissionidsByRoleid(roleid);
	
	
	Map<Integer,Permission> map = new HashMap<Integer,Permission>();//100
	
	for (Permission innerpermission : childredPermissons) {
		map.put(innerpermission.getId(), innerpermission);
		if(permissonIdsForRoleid.contains(innerpermission.getId())){
			innerpermission.setChecked(true); //checked默认false,如果权限已有设checked为true
		}
	}
	
	
	for (Permission permission : childredPermissons) { //100
		//通过子查找父
		//子菜单
		Permission child = permission ; //假设为子菜单
		if(child.getPid() == null ){
			root.add(permission);
		}else{
			//父节点
			Permission parent = map.get(child.getPid());
			parent.getChildren().add(child);
		}
	}
	
	return root ;
}

(3)点击分配许可,流程为,先删除所有的权限,再将勾选的权限保存

①RoleController

@ResponseBody
@RequestMapping("/doAssignPermission")
public Object doAssignPermission(Integer roleid, Data datas){
	AjaxResult result = new AjaxResult();
	try {
		int count = roleService.saveRolePermissionRelationship(roleid,datas);
		
		result.setSuccess(count==datas.getIds().size());
		
	} catch (Exception e) {
		e.printStackTrace();
		result.setSuccess(false);
	}
	
	return result;
}

②RoleServiceImpl

@Override
public int saveRolePermissionRelationship(Integer roleid, Data datas) {
	
	roleDao.deleteRolePermissionRelationship(roleid);//先删除
	
	int totalCount = 0 ;
	List<Integer> ids = datas.getIds();
	for (Integer permissionid : ids) {
		RolePermission rp = new RolePermission();
		rp.setRoleid(roleid);
		rp.setPermissionid(permissionid);
		int count = roleDao.insertRolePermission(rp);//后保存
		totalCount += count ;
	}
	
	return totalCount;
}

17.分配登录人员的显示菜单

(1)menu.jsp

<c:forEach items="${sessionScope.permissionRoot.children }" var="permission">
	<c:if test="${empty permission.children}">
		<li class="list-group-item tree-closed" >
			<a href="${APP_PATH }/${permission.url }"><i class="${permission.icon}"></i> ${permission.name }</a> 
		</li>
	</c:if>
	<c:if test="${not empty permission.children}" >
		<li class="list-group-item tree-closed">
			<span><i class="${permission.icon}"></i> ${permission.name } <span class="badge" style="float:right">${fn:length(permission.children)}    <%-- ${permission.children.size() } --%></span></span> 
			<ul style="margin-top:10px;display:none;">
				<c:forEach items="${permission.children }" var="innerPermission">
					<li style="height:30px;">					
						<a href="${APP_PATH }/${innerPermission.url}"><i class="${innerPermission.icon }"></i> ${innerPermission.name }</a> 
					</li>
				</c:forEach>
			</ul>
		</li>
	</c:if>
</c:forEach> 

(2)DispatcherController.java

@ResponseBody
@RequestMapping("/doLogin")
public Object doLogin(String loginacct,String userpswd,String type,HttpSession session){
	
	AjaxResult result = new AjaxResult();
	
	try {
		Map<String,Object> paramMap = new HashMap<String,Object>();
		paramMap.put("loginacct", loginacct);
		paramMap.put("userpswd", MD5Util.digest(userpswd));
		paramMap.put("type", type);

		User user = userService.queryUserLogin(paramMap);
		
		session.setAttribute(Const.LOGIN_USER, user);
		
		//加载当前用户所拥有的许可权限
		List<Permission> myPermissions = userService.queryPermissionByUserid(user.getId());
		Permission permissionRoot = null;
		
		Map<Integer,Permission> map = new HashMap<Integer,Permission>();
		
		for(Permission innerpermission: myPermissions){
			map.put(innerpermission.getId(),innerpermission );//把查出来的数据全部放入map中使用,不
		}
		
		for(Permission permission : myPermissions){  //利用递归,一个嵌套的Jason数据,通过F12-network看请求发送的数据
			Permission child = permission;
			
			if(child.getPid()==null){
				permissionRoot=permission;
			}else{
				Permission parent = map.get(child.getPid());
				parent.getChildren().add(child);
			}
		}
		
		session.setAttribute("permissionRoot", permissionRoot);
		result.setSuccess(true);
	
	} catch (Exception e) {
		result.setMessage("登录失败,用户名或密码错误");
		e.printStackTrace();
		
		result.setSuccess(false);
	}
	
	return result;
}

(3)UserMapper.xml,五表联查

<select id="queryPermissionByUserid" parameterType="int" resultType="com.atguigu.atcrowdfunding.bean.Permission">
	SELECT DISTINCT t_permission.id, t_permission.pid, t_permission.name,t_permission.icon,t_permission.url
	FROM t_user,t_role,t_user_role,t_role_permission,t_permission
	WHERE 
	t_user.`id`=t_user_role.`userid`
	AND t_user_role.`roleid`=t_role_permission.`roleid`
	AND  t_role_permission.`permissionid`=t_permission.`id`
	AND t_user.id=#{id} order by t_permission.id
</select>

18.登录权限拦截

(1)LoginInterceptor.java

public class LoginInterceptor extends HandlerInterceptorAdapter {
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		Set<String> uri = new HashSet<String>();  //白名单,不拦截
                uri.add("/index.htm");
		uri.add("/user/reg.do");   
		uri.add("/user/reg.htm");
		uri.add("/login.htm");
		uri.add("/doLogin.do");
		uri.add("/loginout.do");
		
		//获取请求路径
		String servletPath = request.getServletPath();
		if(uri.contains(servletPath)){
			return true; //放行,进入postHandle
		}
		
		HttpSession session = request.getSession();
		User user = (User) session.getAttribute(Const.LOGIN_USER);
		if(user!=null){     //已登录
			return true;
		}else{
			response.sendRedirect(request.getContextPath()+"/login.htm");
			return false;
		}
	}
}

(2)在springmvc_context中声明拦截器

    <!-- 声明拦截对象 -->
    <mvc:interceptors>
    	<bean id="loginInterceptor" class="com.atguigu.atcrowdfunding.interceptor.LoginInterceptor"></bean>
    </mvc:interceptors>

19.访问权限拦截

(1)服务器加载时,查询出所有需要控制权限的路径,放入application域供使用,避免每次都要查询数据库

StartSystemListener.java

public class StartSystemListener implements ServletContextListener {

	//在服务器启动时,创建application对象时需要执行的方法.
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		//1.将项目上下文路径(request.getContextPath())放置到application域中.
		ServletContext application = sce.getServletContext();
		String contextPath = application.getContextPath();
		application.setAttribute("APP_PATH", contextPath);
		
		//加载所有的pemission路径
		ApplicationContext ioc = WebApplicationContextUtils.getWebApplicationContext(application);
		PermissionService permissionService = ioc.getBean(PermissionService.class);
		List<Permission> queryAllPermission = permissionService.queryAllPermission();
		Set<String> allURIs = new HashSet<String>();
		
		for(Permission permission:queryAllPermission){
			allURIs.add("/"+permission.getUrl());
		}
		
		application.setAttribute(Const.ALL_PERMISSION_URI, allURIs);
	}
}

(2)AuthInterceptor.java

public class AuthInterceptor extends HandlerInterceptorAdapter {
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		 
		Set<String> allURIs = (Set<String>) request.getSession().getServletContext().getAttribute(Const.ALL_PERMISSION_URI);
		 String servletPath = request.getServletPath();
		 
		 if(allURIs.contains(servletPath)){
			 
			 Set<String> myURIs = (Set<String>) request.getSession().getAttribute(Const.MY_URIS);
			 if(myURIs.contains(servletPath)){
				 return true;
			 }else{
				 response.sendRedirect(request.getContextPath()+"/login.htm");//权限不足,返回登录界面
				 return false;
			 }
		 }else{
			 return true; //不属于分辨是否要拦截的路径,任何人都可以访问
		 }
	}
}

(3)在springmvc_context中声明拦截器

    <!-- 声明拦截对象 -->
    <mvc:interceptors>
    	<bean id="loginInterceptor" class="com.atguigu.atcrowdfunding.interceptor.LoginInterceptor"></bean>
    	<bean id="authInterceptor" class="com.atguigu.atcrowdfunding.interceptor.AuthInterceptor"></bean> 	
    </mvc:interceptors>

20.广告表单文件功能上传(单个图片格式校验,照片预览,上传)

(1)表单要设属性enctype="multipart/form-data", method="post",并在springmv-context.xml中配置

①add.jsp

<form id="advertForm" method="post" action="" enctype="multipart/form-data">
		  <div class="form-group">
			<label for="name">广告名称</label>
			<input type="text" class="form-control" id="name" name="name" placeholder="请输入广告名称">
		  </div>
		  <div class="form-group">
			<label for="url">广告地址</label>
			<input type="text" class="form-control" id="url" name="url" placeholder="请输入广告地址">
                        <br>
			<img src="" style="display:none">
		  </div>
		  <div class="form-group">
			<label for="advpic">广告图片</label>
			<input type="file" class="form-control" id="advpic" name="advpic" placeholder="请输入广告图片">
		  </div>
		  <button id="saveBtn" type="button" class="btn btn-success"><i class="glyphicon glyphicon-plus"></i> 新增</button>
		  <button id="resetBtn" type="button" class="btn btn-danger"><i class="glyphicon glyphicon-refresh"></i> 重置</button>
		</form>

②springmvc-context.xml

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="UTF-8">
	<property name="maxUploadSize" value="2097152"/>   //所有文件最大的大小,不是单个的大小
	<property name="resolveLazily" value="true"/>
</bean>

(2)表单值异步提交

①需要加入jquery-form.min.js

<script src="${APP_PATH }/jquery/jquery-form/jquery-form.min.js"></script>

②add.jsp

图片预览,表单中一定要有

<br>
<img src="" style="display:none">

//图片格式校验
$(":file").change(function(event){	
	var f = $("#advpic").val();
	if(!/\.(gif|jpg|jpeg|png|GIF|JPG|PNG)$/.test(f)){
		 layer.msg("图片类型必须是.gif,jpeg,jpg,png中的一种", {time:1000, icon:5, shift:6});
		 setTimeout(function(){
				   //延时要执行的事件
			 /*  window.location.href = "${APP_PATH}/advert/add.htm"; */
			 $("#advertForm")[0].reset(); 
			 },500);   
		return false;
	}
	
	//图片预览
	var files = event.target.files;
	var file;
	
	if (files && files.length > 0) {
		  file = files[0];
		 var URL = window.URL || window.webkitURL;
		  // 本地图片路径
		  var imgURL = URL.createObjectURL(file);
		  
		  var imgObj = $(this).next().next(); //获取同辈紧邻的下一个元素
		  //console.log(imgObj);
		  imgObj.attr("src", imgURL);
		  imgObj.show();
		  }          
		 });
	
	//异步保存带图片的表单数据
	$("#saveBtn").click(function(){
		 var options = {
			url:"${APP_PATH}/advert/doAdd.do",
			beforeSubmit : function(){
				loadingIndex = layer.msg('数据正在保存中', {icon: 6});
				return true ; //必须返回true,否则,请求终止.
			},
			success : function(result){
				layer.close(loadingIndex);
				if(result.success){
					layer.msg("广告数据保存成功", {time:1000, icon:6});
					window.location.href="${APP_PATH}/advert/index.htm";
				}else{
					layer.msg("广告数据保存失败", {time:1000, icon:5, shift:6});
				}	
			}	
		};
		
		$("#advertForm").ajaxSubmit(options); 
		        		                	
	});	
	
	$("#resetBtn").click(function(){
		$("#advertForm")[0].reset(); 
	});

③AdvertController.java

@ResponseBody
@RequestMapping("/doAdd")
public Object doAdd(HttpServletRequest request, Advert advert ,HttpSession session) {
	AjaxResult result = new AjaxResult();
	System.out.println(33);
	
	try {
		MultipartHttpServletRequest mreq = (MultipartHttpServletRequest)request;//文件需要将request转换为MultipartHttpServletRequest
		
		MultipartFile mfile = mreq.getFile("advpic");
		
		String name = mfile.getOriginalFilename();//java.jpg
		String extname = name.substring(name.lastIndexOf(".")); // .jpg
		
		String iconpath = UUID.randomUUID().toString()+extname; //232243343.jpg
		
		ServletContext servletContext = session.getServletContext();
		String realpath = servletContext.getRealPath("/pics");
		System.out.println(realpath);
		String path =realpath+ "\\adv\\"+iconpath;
		
		mfile.transferTo(new File(path));   //上传图片
		
		User user = (User)session.getAttribute(Const.LOGIN_USER);
		advert.setUserid(user.getId());
		advert.setStatus("1");   //未审核
		advert.setIconpath(iconpath);
		
		int count = advertService.insertAdvert(advert);
		result.setSuccess(count==1);
	} catch ( Exception e ) {
		e.printStackTrace();
		result.setSuccess(false);
	}
	
	return result;
}

④AdvertService,AdvertServieImpl,AdvertMapper省略

⑤异步提交文件表单方法解析

var options = {  
   target: '#output',          //把服务器返回的内容放入id为output的元素中      
   beforeSubmit: showRequest,  //提交前的回调函数  
   success: showResponse,      //提交后的回调函数  
   //url: url,                 //默认是form的action, 如果申明,则会覆盖  
   //type: type,               //默认是form的method(get or post),如果申明,则会覆盖  
   //dataType: null,           //html(默认), xml, script, json...接受服务端返回的类型  
   //clearForm: true,          //成功提交后,清除所有表单元素的值  
   //resetForm: true,          //成功提交后,重置所有表单元素的值  
   timeout: 3000               //限制请求的时间,当请求大于3秒后,跳出请求  
}  
  
function showRequest(formData, jqForm, options){  
   //formData: 数组对象,提交表单时,Form插件会以Ajax方式自动提交这些数据,格式如:[{name:user,value:val },{name:pwd,value:pwd}]  
   //jqForm:   jQuery对象,封装了表单的元素     
   //options:  options对象  
   var queryString = $.param(formData);   //name=1&address=2  
   var formElement = jqForm[0];              //将jqForm转换为DOM对象  
   var address = formElement.address.value;  //访问jqForm的DOM元素  
   return true;  //只要不返回false,表单都会提交,在这里可以对表单元素进行验证  
};  
  
function showResponse(responseText, statusText){  
   //dataType=xml  
   var name = $('name', responseXML).text();  
   var address = $('address', responseXML).text();  
   $("#xmlout").html(name + "  " + address);  
   //dataType=json  
   $("#jsonout").html(data.name + "  " + data.address);  
};

$("#formID").ajaxSubmit(options);

21.利用分页插件做分页(以user/index.jsp为例)

(1)引入pagination.css

<link rel="stylesheet" href="${APP_PATH }/jquery/pagination/pagination.css">

(2)引入jquery.pagination.js,并修改把最后一行注释

<script src="${APP_PATH}/jquery/pagination/jquery.pagination.js"></script>

 修改,否则会一直触发回调函数:

/**
 * This jQuery plugin displays pagination links inside the selected elements.
 *
 * @author Gabriel Birke (birke *at* d-scribe *dot* de)
 * @version 1.2
 * @param {int} maxentries Number of entries to paginate
 * @param {Object} opts Several options (see README for documentation)
 * @return {Object} jQuery Object
 */
jQuery.fn.pagination = function(maxentries, opts){
	opts = jQuery.extend({
		items_per_page:10,
		num_display_entries:10,
		current_page:0,
		num_edge_entries:0,
		link_to:"#",
		prev_text:"Prev",
		next_text:"Next",
		ellipse_text:"...",
		prev_show_always:true,
		next_show_always:true,
		callback:function(){return false;}
	},opts||{});
	
	return this.each(function() {
		/**
		 * 计算最大分页显示数目
		 */
		function numPages() {
			return Math.ceil(maxentries/opts.items_per_page);
		}	
		/**
		 * 极端分页的起始和结束点,这取决于current_page 和 num_display_entries.
		 * @返回 {数组(Array)}
		 */
		function getInterval()  {
			var ne_half = Math.ceil(opts.num_display_entries/2);
			var np = numPages();
			var upper_limit = np-opts.num_display_entries;
			var start = current_page>ne_half?Math.max(Math.min(current_page-ne_half, upper_limit), 0):0;
			var end = current_page>ne_half?Math.min(current_page+ne_half, np):Math.min(opts.num_display_entries, np);
			return [start,end];
		}
		
		/**
		 * 分页链接事件处理函数
		 * @参数 {int} page_id 为新页码
		 */
		function pageSelected(page_id, evt){
			current_page = page_id;
			drawLinks();
			var continuePropagation = opts.callback(page_id, panel);
			if (!continuePropagation) {
				if (evt.stopPropagation) {
					evt.stopPropagation();
				}
				else {
					evt.cancelBubble = true;
				}
			}
			return continuePropagation;
		}
		
		/**
		 * 此函数将分页链接插入到容器元素中
		 */
		function drawLinks() {
			panel.empty();
			var interval = getInterval();
			var np = numPages();
			// 这个辅助函数返回一个处理函数调用有着正确page_id的pageSelected。
			var getClickHandler = function(page_id) {
				return function(evt){ return pageSelected(page_id,evt); }
			}
			//辅助函数用来产生一个单链接(如果不是当前页则产生span标签)
			var appendItem = function(page_id, appendopts){
				page_id = page_id<0?0:(page_id<np?page_id:np-1); // 规范page id值
				appendopts = jQuery.extend({text:page_id+1, classes:""}, appendopts||{});
				if(page_id == current_page){
					var lnk = jQuery("<span class='current'>"+(appendopts.text)+"</span>");
				}else{
					var lnk = jQuery("<a>"+(appendopts.text)+"</a>")
						.bind("click", getClickHandler(page_id))
						.attr('href', opts.link_to.replace(/__id__/,page_id));		
				}
				if(appendopts.classes){lnk.addClass(appendopts.classes);}
				panel.append(lnk);
			}
			// 产生"Previous"-链接
			if(opts.prev_text && (current_page > 0 || opts.prev_show_always)){
				appendItem(current_page-1,{text:opts.prev_text, classes:"prev"});
			}
			// 产生起始点
			if (interval[0] > 0 && opts.num_edge_entries > 0)
			{
				var end = Math.min(opts.num_edge_entries, interval[0]);
				for(var i=0; i<end; i++) {
					appendItem(i);
				}
				if(opts.num_edge_entries < interval[0] && opts.ellipse_text)
				{
					jQuery("<span>"+opts.ellipse_text+"</span>").appendTo(panel);
				}
			}
			// 产生内部的些链接
			for(var i=interval[0]; i<interval[1]; i++) {
				appendItem(i);
			}
			// 产生结束点
			if (interval[1] < np && opts.num_edge_entries > 0)
			{
				if(np-opts.num_edge_entries > interval[1]&& opts.ellipse_text)
				{
					jQuery("<span>"+opts.ellipse_text+"</span>").appendTo(panel);
				}
				var begin = Math.max(np-opts.num_edge_entries, interval[1]);
				for(var i=begin; i<np; i++) {
					appendItem(i);
				}
				
			}
			// 产生 "Next"-链接
			if(opts.next_text && (current_page < np-1 || opts.next_show_always)){
				appendItem(current_page+1,{text:opts.next_text, classes:"next"});
			}
		}
		
		//从选项中提取current_page
		var current_page = opts.current_page;
		//创建一个显示条数和每页显示条数值
		maxentries = (!maxentries || maxentries < 0)?1:maxentries;
		opts.items_per_page = (!opts.items_per_page || opts.items_per_page < 0)?1:opts.items_per_page;
		//存储DOM元素,以方便从所有的内部结构中获取
		var panel = jQuery(this);
		// 获得附加功能的元素
		this.selectPage = function(page_id){ pageSelected(page_id);}
		this.prevPage = function(){ 
			if (current_page > 0) {
				pageSelected(current_page - 1);
				return true;
			}
			else {
				return false;
			}
		}
		this.nextPage = function(){ 
			if(current_page < numPages()-1) {
				pageSelected(current_page+1);
				return true;
			}
			else {
				return false;
			}
		}
		// 所有初始化完成,绘制链接
		drawLinks();
        // 回调函数
//        opts.callback(current_page, this);
	});
}


 

(3)插件的页数pageIndex默认从0开始,所以0代表第1页

<ul id="Pagination" class="pagination">
//插入分页组件部分
</ul>
var jsonObj = {
		"pageno" : 1,
		"pagesize" : 10 
	};

var loadingIndex = -1 ;
function queryPageUser(pageIndex){     //参数默认pageIndex
	jsonObj.pageno = pageIndex + 1;
	$.ajax({
		type : "POST",
		data : jsonObj,
		url : "${APP_PATH}/user/doIndex.do",
		beforeSend : function(){
			loadingIndex = layer.load(2, {time: 10*1000});
			return true ;
		},
		success : function(result){
			layer.close(loadingIndex);
			if(result.success){
				var page = result.page ;
				var data = page.data ;
				
				var content = '';
				
				$.each(data,function(i,n){ 
					content+='<tr>';
					content+='  <td>'+(i+1)+'</td>';
					content+='  <td><input id="'+n.id+'" loginacct="'+n.loginacct+'" type="checkbox"></td>';
					content+='  <td>'+n.loginacct+'</td>';
					content+='  <td>'+n.username+'</td>';
					content+='  <td>'+n.email+'</td>';
					content+='  <td>';
					content+='	  <button type="button" onclick="window.location.href=\'${APP_PATH}/user/assignRole.htm?id='+n.id+'\'" class="btn btn-success btn-xs"><i class=" glyphicon glyphicon-check"></i></button>';
					content+='	  <button type="button" onclick="window.location.href=\'${APP_PATH}/user/toUpdate.htm?id='+n.id+'\'" class="btn btn-primary btn-xs"><i class=" glyphicon glyphicon-pencil"></i></button>';
					content+='	  <button type="button" onclick="deleteUser('+n.id+',\''+n.loginacct+'\')" class="btn btn-danger btn-xs"><i class=" glyphicon glyphicon-remove"></i></button>';
					content+='  </td>';
					content+='</tr>';
				});
				
				
				$("tbody").html(content);
				// 创建分页
				$("#Pagination").pagination(page.totalsize, {    //page.totalsize查询出的总条数
					num_edge_entries: 2, 			//边缘页数                             
					num_display_entries: 3, 		//主体页数			
					callback: queryPageUser,		//回调函数,回调自己
					items_per_page: 10, //每页显示页数       //与自己设置的pagesize一致
					current_page:(page.pageno-1),          //当前页,0代表第1页
					prev_text : "上一页",                   //“前一页”分页按钮上显示的文字
					next_text : "下一页"			//“下一页”分页按钮上显示的文字
				});
				
			}else{
				layer.msg(result.message, {time:1000, icon:5, shift:6});
			}
		},
		error : function(){
			layer.msg("加载数据失败!", {time:1000, icon:5, shift:6});
		}
	});
}

(4)分页插件参数详解

 

插件简介:

  • 此jQuery插件为Ajax分页插件,一次性加载,故分页切换时无刷新与延迟,如果数据量较大不建议用此方法,因为加载会比较慢。
  • 原插件CSS不太合理,使用浮动,故无法方便实现左右方向的定位,且未清除浮动,在中文修改版中我对其进行了优化,使其支持text-align的定位。

使用方法:

跟一般的jQuery插件一样,此插件使用也很简单便捷。方法是pagination,例如$("#page").pagination(100);

参数:

参数名 描述 参数值
maxentries 总条目数 必选参数,整数
items_per_page 每页显示的条目数 可选参数,默认是10
num_display_entries 连续分页主体部分显示的分页条目数 可选参数,默认是10
current_page 当前选中的页面 可选参数,默认是0,表示第1页
num_edge_entries 两侧显示的首尾分页的条目数 可选参数,默认是0
link_to 分页的链接 字符串,可选参数,默认是"#"
prev_text “前一页”分页按钮上显示的文字 字符串参数,可选,默认是"Prev"
next_text “下一页”分页按钮上显示的文字 字符串参数,可选,默认是"Next"
ellipse_text 省略的页数用什么文字表示 可选字符串参数,默认是"..."
prev_show_always 是否显示“前一页”分页按钮 布尔型,可选参数,默认为true,即显示“前一页”按钮
next_show_always 是否显示“下一页”分页按钮 布尔型,可选参数,默认为true,即显示“下一页”按钮
callback 回调函数 默认无执行效果

举例:

$("#Pagination").pagination(56, {
    num_edge_entries: 2,
    num_display_entries: 4,
    callback: pageselectCallback,
    items_per_page:1
});

这段代码表示的含义是:总共有56(maxentries)个列表项,首尾两侧分页显示2(num_edge_entries)个,连续分页主体数目显示4(num_display_entries)个,回调函数为pageselectCallback(callback),每页显示的列表项为1(items_per_page)个。

22.Activiti5(test)

(1)首先引入Activiti5插件,并配置spring/spring-flow.xml

将activiti-designer-5.14拷贝到eclipse安装目录dropins目录下,并重启查看是否安装成功

spring-flow.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:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">
  
    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
    	<property name="dataSource" ref="dataSource" />
    	<property name="transactionManager" ref="transactionManager" />
    	<property name="databaseSchemaUpdate" value="true" />
    	<property name="jobExecutorActivate" value="true" />
    	<property name="labelFontName" value="宋体" />
    	<property name="activityFontName" value="宋体" />
        <property name="customFormTypes">
          <list>
            <bean class="org.activiti.explorer.form.UserFormType"/>
            <bean class="org.activiti.explorer.form.ProcessDefinitionFormType"/> 
            <bean class="org.activiti.explorer.form.MonthFormType"/>   
          </list>
        </property>
    </bean>
  
    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean" destroy-method="destroy">
  	    <property name="processEngineConfiguration" ref="processEngineConfiguration" />
    </bean>

    <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
    <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
    <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
    <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
</beans>

(2)创建请假流程图,可以用property操作框操作值

MyProcess1.bpmn

(3)activiti流程初始化,创建引擎,数据库产生23张表

TestActiviti.java

public class TestActiviti {
	ApplicationContext ioc = new ClassPathXmlApplicationContext("spring/spring-*.xml");
	ProcessEngine processEngine = (ProcessEngine) ioc.getBean("processEngine");
	//1.创建流程引擎,创建23张表
	@Test
	public void test01(){
		System.out.println("processEngine="+processEngine);
	}
}

(4)部署自己创建的流程

//2.部署流程定义,存入数据库中
@Test
public void test02(){
	RepositoryService repositoryService = processEngine.getRepositoryService();
	Deployment deploy = repositoryService.createDeployment().addClasspathResource("MyProcess1.bpmn").deploy();
	System.out.println("deploy="+deploy);
}

(5)查询、部署、分配任务、变量、网关

①查询部署流程定义(内容)

//3.查询部署流程定义(内容)
@Test
public void test03(){
	RepositoryService repositoryService = processEngine.getRepositoryService();
	ProcessDefinitionQuery processDefinitionQuery= repositoryService.createProcessDefinitionQuery();
	List<ProcessDefinition> list  = processDefinitionQuery.list();

	
	for(ProcessDefinition processionDefinition : list){
		System.out.println("Id="+processionDefinition.getId());
		System.out.println("Key="+processionDefinition.getKey());
		System.out.println("Name="+processionDefinition.getName());
		System.out.println("Version="+processionDefinition.getVersion());
		System.out.println("-------------------------");
	}
	
	long count = processDefinitionQuery.count();
	System.out.println("count="+count);
	System.out.println("*****************");
	
	//查询最后一次部署的流程定义
	ProcessDefinition processDefinition = processDefinitionQuery.latestVersion().singleResult();
	System.out.println("Id="+processDefinition.getId());
	System.out.println("Key="+processDefinition.getKey());
	System.out.println("Name="+processDefinition.getName());
	System.out.println("Version="+processDefinition.getVersion());
	System.out.println("################################");
	
	//排序、分页查询流程定义
	ProcessDefinitionQuery definitionQuery  = processDefinitionQuery.orderByProcessDefinitionVersion().desc();
	List<ProcessDefinition> listPage = definitionQuery.listPage(0, 2);
	for(ProcessDefinition processDefinition2 : listPage){
		System.out.println("Id="+processDefinition2.getId());
		System.out.println("Key="+processDefinition2.getKey());
		System.out.println("Name="+processDefinition2.getName());
		System.out.println("Version="+processDefinition2.getVersion());
		System.out.println("====================");
	}
	
	System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
	//根据流程定义的 Key 查询流程定义对象
	ProcessDefinition processDefinition2 = processDefinitionQuery.processDefinitionKey("myProcess").latestVersion().singleResult();
	System.out.println("Id="+processDefinition2.getId());
	System.out.println("Key="+processDefinition2.getKey());
	System.out.println("Name="+processDefinition2.getName());
	System.out.println("Version="+processDefinition2.getVersion());
	
}

②启动流程实例

//4.启动流程实例
/**
 * act_hi_actinst, 历史的活动的任务表.
 * act_hi_procinst, 历史的流程实例表.
 * act_hi_taskinst, 历史的流程任务表
 * act_ru_execution, 正在运行的任务表.
 * act_ru_task, 运行的任务数据表.
 */
@Test
public void test04(){
	ProcessDefinition processDefinition = processEngine.getRepositoryService().createProcessDefinitionQuery().latestVersion().singleResult();
	
	RuntimeService runtimeService = processEngine.getRuntimeService();
	ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
	System.out.println("processInstance"+processInstance);
}

③查询流程实例的任务数据

@Test
public void test05(){
	ProcessDefinition processDefinition = processEngine.getRepositoryService().createProcessDefinitionQuery().latestVersion().singleResult();

	TaskService taskService = processEngine.getTaskService();
	TaskQuery createTaskQuery = taskService.createTaskQuery();
	List<Task> list1 = createTaskQuery.taskAssignee("zhangsan").list();
	List<Task> list2 = createTaskQuery.taskAssignee("lisi").list();
	
	//zhangsan的任务:
	System.out.println("zhangsan的任务:");
	for (Task task : list1) {
		System.out.println("id="+task.getId());
		System.out.println("name="+task.getName());
		//zhangsan完成任务
		taskService.complete(task.getId());
	}
	System.out.println("------------------------------------");
	//lisi的任务:
	System.out.println("lisi的任务:");
	for (Task task : list2) {
		System.out.println("id="+task.getId());
		System.out.println("name="+task.getName());
		taskService.complete(task.getId());
	}
	System.out.println("========================================");
	
	
	list1 = createTaskQuery.taskAssignee(&
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值