当前位置:网站首页>Over 100000 words_ Ultra detailed SSM integration practice_ Manually implement permission management

Over 100000 words_ Ultra detailed SSM integration practice_ Manually implement permission management

2022-07-07 09:23:00 I'm Bo Li Bo

SSM Integrate _ Basic configuration


	SSM The framework contains Spring,SpringMVC,Mybatis. and Spring And SpringMVC All are Spring Framework Module , No consolidation required . Just put the Mybatis And Spring Just integrate .

One 、 Integration concerns

	1、Spring stay web Application in the project .
		 stay web When the project starts , Read applicationContext.xml The configuration file , establish IOC Containers .
		
	2、 Use connection pool as data source .  
		 Connect directly to the data source or Spring Data sources in (DriverManagerDataSource), Connection efficiency is too low . Use the Druid connection pool under Alibaba (druid) As a connection data source .

	3、Mybatis And Spring The combination of .
		 adopt Spring Of IOC Container management SqlSessionFactory、mapper The proxy object of the interface .

Two 、 Import dependence

2.1 Spring rely on

<!-- spring Core packages -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>
<!-- springbean package  -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>
<!-- springcontext package  -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>
<!-- spring Expression package  -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>
<!-- springAOP package  -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>
<!-- springAspects package  -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>
<!-- springJDBC package  -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>
<!-- spring Transaction package  -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>
<!-- spring Yes web Support for  -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>
<!-- springwebMVC -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>

2.2 Mybatis rely on

<!-- mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
<!-- mybatis The paging assistant for -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.2</version>
</dependency>

2.3 Mybatis And Spring Integration dependence

<!--Mybatis And Spring Integrated package -->
<!--  course : SSH: Spring Struts2 Hibernate  And Hibernate/ibatis The integration package of is made up of Spring Provide ,spring-orm SSM: Spring SpringMVC Mybatis  And Mybatis The integration package of is made up of Mybatis Provide ,mybatis-spring -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.2</version>
</dependency>

2.4 Connection pool and database driver depend

<!-- oracle drive -->
<dependency>
    <groupId>com.oracle</groupId>
    <artifactId>ojdbc6</artifactId>
    <version>11.2.0</version>
</dependency>
<!-- mysql drive  -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.49</version>
</dependency>
<!-- Connection pool : Druid data source -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>

2.5 JavaWeb Environment depends on

<!-- servlet-api -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
<!-- jsp-api -->
<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.1</version>
    <scope>provided</scope>
</dependency>
<!-- jstl -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

2.6 Optional plug-in dependencies

<!--  Upload package  -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
<!-- jackson -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.5</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.5</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.5</version>
</dependency>
<!-- hibernate The verification framework of -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.4.1.Final</version>
</dependency>
<!-- log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
<!-- junit-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

3、 ... and 、 Directory structure

 Insert picture description here

	src/main/java Create under directory Java Software package structure .
	
	src/main/resources Various configuration files and resource files are stored in the directory .
	
	webapp Store in the directory web Project static resources and WEB-INF Catalog , among jsp Pages are stored in WEB-INF Next .

Four 、 The configuration file

4.1 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">

</web-app>

4.1.1 Character encoding filter

	 use Spring The character encoding filter provided in CharacterEncodingFilter.
<!-- Character encoding filter -->
<filter>
    <filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

4.1.2 IOC Monitor of container

	 stay web When the project starts , Context object ServletContext After object initialization , Read Spring And create IOC Container object , Finally, put it into the context scope .
	
	 use Spring Provided in ContextLoaderListener Monitor .
<!--  Initialization parameters of upper and lower objects  -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <!--  Use wildcards * Load multiple profiles  -->
    <param-value>classpath:applicationContext*.xml</param-value>
</context-param>
<!-- springIOC Containers  -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

4.1.3 Front controller

<!--  Configure front end controller  -->
<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:springmvc.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>

4.1.4 The welcome page

<welcome-file-list>
    <welcome-file>/WEB-INF/views/index.jsp</welcome-file>
</welcome-file-list>

4.1.5 Other configuration

<!--  This problem is solved by hiding the domain parameters form Form PUT And DELETE Method request  -->
<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!--  solve put The problem of requesting parameters -->
<filter>
    <filter-name>HttpPutFormContentFilter</filter-name>
    <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>HttpPutFormContentFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

4.2 Mybatis The configuration file

before mybatis-config.xml China needs load resources Global parameter Type the alias Paging plug-ins Connect to the database environment Load mapping file Other configuration . But with Spring After integration , load resources Connect to the database environment Must move into Spring Middle configuration , Load mapping file It is suggested to move into Spring in ( You can use wildcards ), The other two are ok . If you move everything into Spring Middle configuration , Then this file can disappear .

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- Load external resource file : move Spring The configuration of ( The abolition of )-->
    <!--<properties resource="db.properties"></properties>-->

    <!-- Global parameter : You can move in Spring Configuration of -->
    <settings>
        <!-- Start the sliding line and turn to the hump -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!-- Turn on mybatis SQL journal ,SSM After integration, there is no log output , It needs to be configured separately -->
        <setting name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/>
    </settings>

    <!-- Type the alias : You can move in Spring Configuration of -->
    <!--<typeAliases> <package name="com.newcapec.entity"/> </typeAliases>-->

    <!-- plug-in unit : You can move in Spring Configuration of -->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <property name="reasonable" value="true"/>
        </plugin>
    </plugins>

    <!-- Environmental Science : move Spring The configuration of ( The abolition of : Use third-party data source objects )-->
    <!--<environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="${jdbc.mysql.driver}"/> <property name="url" value="${jdbc.mysql.url}"/> <property name="username" value="${jdbc.mysql.username}"/> <property name="password" value="${jdbc.mysql.password}"/> </dataSource> </environment> </environments>-->

    <!--  Load mapping file : move Spring The configuration of ( The abolition of :Spring Can be loaded in batches mapper file ) -->
    <!--<mappers> <mapper resource="mapper/EmpMapper.xml"/> </mappers>-->
</configuration>

db.properties:

#mysql
jdbc.mysql.driver=com.mysql.jdbc.Driver
jdbc.mysql.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&useSSL=false
jdbc.mysql.username=root
jdbc.mysql.password=root

#oracle
jdbc.oracle.driver=oracle.jdbc.driver.OracleDriver
jdbc.oracle.url=jdbc:oracle:thin:@localhost:1521:orcl
jdbc.oracle.username=system
jdbc.oracle.password=123456

log4j.properties:

# A pound sign indicates a comment , The configuration content is in the format of key value pair , Each row can only have one key value pair , Between key value pairs = Connect 
# Appoint logger
# Set up log4j Log level and destination of output 
#INFO The level of logging  ,Console and logfile The destination of the output 
# Grade  OFF,ERROR,WARN,INFO,DEBUG,TRACE,ALL
log4j.rootLogger=DEBUG,Console

# Appoint appender
# Set up Logger Of Console, among Console For custom name , The type is console output 
log4j.appender.Console=org.apache.log4j.ConsoleAppender

# Set up Logger Of logfile, among logfile For custom name , The type is file 
#org.apache.log4j.FileAppender file 
#org.apache.log4j.RollingFileAppender When the file size reaches the specified size, a new file is generated 
#org.apache.log4j.DailyRollingFileAppender Generate a log file every day 
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
# Set the output path of the file 
log4j.appender.logfile.File=d:/log/test.log
# Set maximum file size    Units can make KB,MB,GB
log4j.appender.logfile.MaxFileSize=2048KB

# Output format 
# Set up appender Layout Layout
#   %d  Date and time of the output log , Specify the format :%d{yyyy-MM-dd HH:mm:ss SSS}
#   %p  Log level of output 
#   %c  Output the full class name of the class 
#   %M  Method name 
#   %m  The message specified in the output code 
#   %n  A line break 
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d %p %c.%M() --%m%n
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p %c.%M() --%m%n

4.3 Spring The configuration file

	 because Spring Too many configurations in , Can be Spring It is divided into multiple files for separate configuration .
	
	 stay web.xml You can load them together through wildcards (classpath:spring/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:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" 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/util http://www.springframework.org/schema/util/spring-util.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">

</beans>

4.3.1 applicationContext.xml

  • Annotation scan :
     To configure : The basic package is a public package (com.newcapec), And filter it out @Controller annotation .

     Ideas :Spring And SpringMVC Scan their content separately ,SpingMVC Scan the classes of the presentation layer (Controller), and Spring Scan other .
<!-- Component scan ( Open component )-->
<context:component-scan base-package="com.newcapec">
    <!-- Filter Controller annotation , stay SpringMVC scanning -->
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
  • data source :
	 To configure : Read db.properties file , The data source object adopts the Druid connection pool under Alibaba , And configure the basic information of the connection database and the key information of the connection pool .
<!--  Import external resource file -->
<context:property-placeholder location="classpath:db.properties"/>

<!--  Configuration of data source : Druid connection pool -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <!--  Basic configuration  -->
    <property name="driverClassName" value="${jdbc.mysql.driver}"/>
    <property name="url" value="${jdbc.mysql.url}"/>
    <property name="username" value="${jdbc.mysql.username}"/>
    <property name="password" value="${jdbc.mysql.password}"/>
    <!--  Key configuration  -->
    <!--  Number of physical connections established during initialization . Initialization occurs in the display call init Method , Or for the first time getConnection when  -->
    <property name="initialSize" value="${druid.initialSize}" />
    <!--  Minimum number of connection pools  -->
    <property name="minIdle" value="${druid.minIdle}" />
    <!--  Maximum number of connection pools  -->
    <property name="maxActive" value="${druid.maxActive}" />
    <!--  Configure the timeout time for getting connection waiting  -->
    <property name="maxWait" value="${druid.maxWait}" />
</bean>
#mysql
jdbc.mysql.driver=com.mysql.jdbc.Driver
jdbc.mysql.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&useSSL=false
jdbc.mysql.username=root
jdbc.mysql.password=root

#oracle
jdbc.oracle.driver=oracle.jdbc.driver.OracleDriver
jdbc.oracle.url=jdbc:oracle:thin:@localhost:1521:orcl
jdbc.oracle.username=system
jdbc.oracle.password=123456

#druid
druid.initialSize=5
druid.minIdle=5
druid.maxActive=15
druid.maxWait=10000
  • Mybatis
	 To configure :SqlSessionFactory object bean and mapper The proxy object of the interface bean.  

	 Ideas :  
		1、SqlSessionFactory The best use range of is the whole application running period , Once created, it can be reused , Usually managed in singleton mode . adopt mybatis-spring In the integration package SqlSessionFactoryBean To create a singleton SqlSessionFactory.
		
		2、SqlSessionFactoryBean The property of must be configured with the data source , Optional loading Mybatis Global configuration file for ( If part of the content remains ), load mapper The mapping file ( It is recommended to configure , You can use the unified character to load in batches ), Type the alias , Plug in and other information .
		
    	3、Mybatis Medium mapper Proxy objects can be passed for each interface MapperFactoryBean To configure separately , Just tell Dao The fully qualified name of the interface . shortcoming : In large and medium-sized projects Dao When there are too many interfaces , Too much configuration , Not recommended .
    	
    	4、 adopt MapperScannerConfigurer To configure mapper Agent scanners can be configured in batches mapper Proxy object , Just tell Dao The storage package name and SqlSessionFactory that will do .
<!--mybatis Configuration of : SqlSessionFactory factory = new SqlSessionFactoryBuilder().build( Read configuration file ) SqlSession sqlSession = factory.openSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class) -->
<!--SqlSessionFactory object -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!-- Data source object -->
    <property name="dataSource" ref="dataSource"/>

    <!-- load mybatis Global configuration file for -->
    <property name="configLocation" value="classpath:mybatis-config.xml"/>

    <!-- load mapper file :  Support wildcard batch loading , And you can specify any directory -->
    <property name="mapperLocations" value="classpath:mapper/*Mapper.xml"/>

    <!-- Type the alias -->
    <!--<property name="typeAliasesPackage" value="com.newcapec.entity"/>-->

    <!-- plug-in unit -->
    <!--<property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties" value="reasonable=true"/> </bean> </array> </property>-->

    <!-- Global parameter -->
    <!--<property name="configuration"> <bean class="org.apache.ibatis.session.Configuration"> <property name="mapUnderscoreToCamelCase" value="true"/> <property name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/> </bean> </property>-->
</bean>
<!-- To configure mapper Proxy object @Mapper-->
<bean id="empDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <!-- The fully qualified name of the interface implemented by the proxy object -->
    <property name="mapperInterface" value="com.newcapec.dao.EmpDao"/>
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<bean id="deptDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.newcapec.dao.DeptDao"/>
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!-- To configure mapper Agent scanner @MapperScan-->
<!--  effect : 1. scanning dao Interface all packages  2. For all scanned dao Interface to create mapper Proxy object  3. Will all mapper The proxy object is placed IOC Containers  -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!-- scanning dao Basic package :  Multiple packages can be separated by commas -->
    <property name="basePackage" value="com.newcapec.dao"/>
    <!-- Inject SqlSessionFactory object -->
    <!--<property name="sqlSessionFactory" ref="sqlSessionFactory"/>-->
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

mapper File template :

<?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="">


</mapper>

4.3.2 applicationContext-tx.xml

  • Transaction Management Profile
     To configure : Transaction manager object , Business , Transaction properties , Business entry point .
    
     Ideas :
		1、 Transaction related configurations are placed in this file , Separate from other configurations , Reduce the bloated configuration file , Convenient for later maintenance .
        
        2、 Use of persistence layer Mybatis frame , The transaction manager uses JDBC The transaction manager of (DataSourceTransactionManager), And inject the data source object .
        
        3、 The transaction attributes can be configured better and reasonably according to different needs .
        
        4、 Transaction pointcuts pass transactions through AOP Is applied to the specified tangent expression .
<!--  Transaction manager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--  Inject data source -->
    <property name="dataSource" ref="dataSource"/>
</bean>

<!--  Business -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--  Configure transaction properties -->
    <tx:attributes>
        <tx:method name="add*" isolation="READ_COMMITTED" rollback-for="java.lang.Exception"/>
        <tx:method name="edit*" isolation="READ_COMMITTED" rollback-for="java.lang.Exception"/>
        <tx:method name="remove*" isolation="READ_COMMITTED" rollback-for="java.lang.Exception"/>
        <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
        <tx:method name="query*" propagation="SUPPORTS" read-only="true"/>
        <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
        <!--  The name of the method to which the transaction attribute applies ,* Means all methods -->
        <tx:method name="*"/>
    </tx:attributes>
</tx:advice>

<!--  Business entry point -->
<aop:config>
    <aop:pointcut id="exp" expression="execution(* com.newcapec.service..*Impl.*(..))"/>
    <!--  Relate pointcut expressions to transactions -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="exp"/>
</aop:config>

4.4 SpringMVC The configuration file

<?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:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" 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/util http://www.springframework.org/schema/util/spring-util.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.xsd">

</beans>
  • Annotation scan
	 To configure : The basic package is the software package of the presentation layer .
	
	 Ideas :SpingMVC Only the classes responsible for scanning the presentation layer (Controller).
	
	 analysis :
		SpingMVC Annotation scanning in also places the scanned object into IOC In the container . When web After the project is started, the first configuration is Spring Initialization of container , And then there was SpringMVC Front end controller for (DispatchServlet), When the configuration is complete DispatchServlet I'll be in Spring Create a new container in the container . Actually, these are two containers ,Spring As a parent container ,SpringMVC As a sub container ( Here's the picture ),SpringMVC The objects in the sub container can be accessed Spring Objects in the parent container , But objects in the parent container cannot access objects in the child container .
		 Usually in Service In the injection Dao, And then Controller Infuse Service, This means that as SpringMVC The child container of is the parent container that can be accessed Spring Object's , If you put Controller Injection into Service It must be impossible . Assume that Dao,Serive,Controller All in the same container , Then there is no problem with dependency injection between objects , But it must all be SpringMVC Sub containers of ( stay SpringMVC Scan all ). If Dao,Serive,Controller All put in Spring In the parent container of ( stay Spring Scan all ), And then SpringMVC There is no... In the container Controller object , So the mapping will not be found when loading the processor adapter Controller object , So... Will appear on the page 404 Error of .  

 Insert picture description here

<context:component-scan base-package="com.newcapec.controller"/>
  • Annotation driven
<mvc:annotation-driven conversion-service="conversionService"/>
  • view resolver
<!-- view resolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
</bean>
  • Formatting and type conversion services
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.newcapec.util.DateConverter"/>
        </set>
    </property>
</bean>
  • Static resource processing
<mvc:default-servlet-handler/>
<mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>
  • Other configuration
<!--  File upload parser -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--  Set upload file size , The unit is byte , The size is 100MB -->
    <property name="maxUploadSize" value="104857600"/>
    <!--  Set the character encoding for uploading -->
    <property name="defaultEncoding" value="utf-8"/>
    <!--  Set cache size , The size is 10KB-->
    <property name="maxInMemorySize" value="10240"/>
</bean>

<!--  Configure interceptors  -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <!--  Exclude paths that are not blocked -->
        <mvc:exclude-mapping path="/login"/>
        <bean class="com.newcapec.intercepor.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

<!--  Complete interceptor configuration  -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <!-- Dynamic page Jump request and static resource mapping request -->
        <mvc:exclude-mapping path="/page/**"/>
        <mvc:exclude-mapping path="/static/**"/>
        <mvc:exclude-mapping path="/auth/login"/>
        <bean class="com.newcapec.interceptor.LoginInterceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/page/login"/>
        <mvc:exclude-mapping path="/page/index"/>
        <mvc:exclude-mapping path="/static/**"/>
        <mvc:exclude-mapping path="/auth/**"/>
        <mvc:exclude-mapping path="/permission/findMenu"/>
        <bean class="com.newcapec.interceptor.PermissionInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

SSM Integrate _ Synchronize cases

	 This case is only used to verify whether the configuration is correct , All cases and projects in the later stage , All adopt asynchronous implementation .

One 、 Table structure

--  Student list 
CREATE TABLE `student` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(20) DEFAULT NULL,
    `gender` varchar(20) DEFAULT NULL,
    `major` varchar(20) DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

--  data 
INSERT INTO `student` VALUES (1, ' Xiao Ming ', '1', ' Software Engineering ');
INSERT INTO `student` VALUES (2, ' Xiaohong ', '0', ' Network engineering ');
INSERT INTO `student` VALUES (3, ' Little black ', '1', ' Information security ');
INSERT INTO `student` VALUES (4, ' The small white ', '0', ' Network engineering ');
INSERT INTO `student` VALUES (5, ' Zhang San ', '1', ' Software Engineering ');
INSERT INTO `student` VALUES (6, ' Li Si ', '0', ' Art design ');
INSERT INTO `student` VALUES (7, ' Wang Wu ', '1', ' Game design ');
INSERT INTO `student` VALUES (8, ' Horse six ', '1', ' Mobile Internet ');

Two 、 Entity class

	 The package name of the entity class is entity/domain. Table name as entity class name , The fields in the table are used as member variable names in the entity class .
	
	 notes : Name according to the actual naming rules .
/** *  Student entity  */
public class Student {
    
    
    private Integer id;
    private String name;
    private String gender;
    private String major;

    public Integer getId() {
    
        return id;
    }

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

    public String getName() {
    
        return name;
    }

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

    public String getGender() {
    
        return gender;
    }

    public void setGender(String gender) {
    
        this.gender = gender;
    }

    public String getMajor() {
    
        return major;
    }

    public void setMajor(String major) {
    
        this.major = major;
    }
}

3、 ... and 、 Persistence layer

	 The persistence layer package is named dao. Persistence layer interface name naming convention : Entity class name +Dao.
	
	 Method naming conventions in the persistence layer :
		insert newly added 
		update modify 
		delete Just delete 
		deleteBatch Batch deletion 
		select Batch query 
		selectById Just check 
	
	 notes : There is a set of naming norms in enterprises , Not absolutely .

3.1 Interface

public interface StudentDao {
    

    /* *  How to add new students  * @param student  Add student data  */
    void insert(Student student);

    /* *  Modify students' methods  * @param student  Modify student data  */
    void update(Student student);

    /* *  according to id Single deletion method  * @param id  Delete the student's id */
    void delete(Integer id);

    /* *  according to id Batch deletion method  * @param ids  Delete the student's id */
    void deleteBatch(Integer[] ids);

    /* *  How to query students in batches  * @param student  Entities that contain conditional data for querying students  * @return List<Student>  Student data queried  */
    List<Student> select(Student student);

    /* *  according to id How to query students  * @param id  Student id * @return Student  Student data queried  */
    Student selectById(Integer id);
}

3.2 Mapper file

<?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 Agent development requirements 1:namespace Be consistent with the fully qualified pathname of the interface -->
<mapper namespace="com.newcapec.dao.StudentDao">

    <!--Mapper Agent development requirements 2: Labeled id The value is consistent with the method name in the interface -->
    <!--Mapper Agent development requirements 3: Labeled parameterType The value is consistent with the method parameter in the interface -->
    <!--Mapper Agent development requirements 4: Labeled resultType The value is consistent with the method return value in the interface -->
    <insert id="insert" parameterType="com.newcapec.entity.Student" useGeneratedKeys="true" keyProperty="id">
        insert into student(name, gender, major)
        values (#{name}, #{gender}, #{major})
    </insert>

    <update id="update" parameterType="com.newcapec.entity.Student">
        update student
        <set>
            <if test="name != null">
                name = #{name},
            </if>
            <if test="gender != null">
                gender = #{gender},
            </if>
            <if test="major != null">
                major = #{major}
            </if>
        </set>
        where id = #{id}
    </update>

    <delete id="delete" parameterType="java.lang.Integer">
        delete
        from student
        where id = #{id}
    </delete>

    <delete id="deleteBatch" parameterType="java.lang.Integer">
        delete from student where id in
        <foreach collection="array" open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </delete>

    <select id="select" parameterType="com.newcapec.entity.Student" resultType="com.newcapec.entity.Student">
        select id, name, gender, major from student
        <where>
            <if test="name != null and name != ''">
                name like concat('%', #{name}, '%')
            </if>
            <if test="gender != null and gender != ''">
                gender = #{gender}
            </if>
            <if test="major != null and major != ''">
                major like concat('%', #{major}, '%')
            </if>
        </where>
    </select>

    <select id="selectById" parameterType="java.lang.Integer" resultType="com.newcapec.entity.Student">
        select id, name, gender, major
        from student
        where id = #{id}
    </select>
</mapper>

Four 、 The business layer

	 The business layer package is named service. Business layer interface name naming specification : Entity class +Service.
	
	 Method naming conventions in the business layer :
		add newly added 
		edit edit 
		remove Delete 
		remove Batch deletion 
		find Batch query 
		findById Single query 
		
	service Layer naming and dao Layer naming :
		1、 Later, the business becomes more and more complex , It is easy to distinguish by method name .
		2、 For standard Spring Transaction configuration .

4.1 Interface

public interface StudentService {
    

    void add(Student student);

    void edit(Student student);

    void remove(Integer id);

    void removeBatch(Integer[] ids);

    List<Student> find(Student student);

    PageInfo findPage(Integer pageNum, Integer pageSize, Student student);

    Student findById(Integer id);
}

4.2 Implementation class

@Service
public class StudentServiceImpl implements StudentService {
    

    @Autowired
    private StudentDao studentDao;

    @Override
    public void add(Student student) {
    
        studentDao.insert(student);
    }

    @Override
    public void edit(Student student) {
    
        studentDao.update(student);
    }

    @Override
    public void remove(Integer id) {
    
        studentDao.delete(id);
    }

    @Override
    public void removeBatch(Integer[] ids) {
    
        studentDao.deleteBatch(ids);
    }

    @Override
    public List<Student> find(Student student) {
    
        return studentDao.select(student);
    }

    @Override
    public PageInfo findPage(Integer pageNum, Integer pageSize, Student student) {
    
        // Paging business implementation 
        PageHelper.startPage(pageNum, pageSize);

        List<Student> list = studentDao.select(student);

        PageInfo<Student> pageInfo = new PageInfo<>(list);

        return pageInfo;
    }

    @Override
    public Student findById(Integer id) {
    
        return studentDao.selectById(id);
    }
}

5、 ... and 、web layer

	web The layer package is named controller. The naming convention of the class : Entity class name +Controller.
	
	 Synchronous request processing : Yes HTTP Limit GET( Query and delete ) and POST( Add and modify ).
@Controller
@RequestMapping("/student")
public class StudentController {
    

    @Autowired
    private StudentService studentService;

    /* *  newly added  */
    @PostMapping("/add")
    public String add(Student student) {
    
        studentService.add(student);
        return "redirect:/student/find";
    }

    /* *  modify  */
    @PostMapping("/edit")
    public String edit(Student student) {
    
        studentService.edit(student);
        return "redirect:/student/find";
    }

    /* *  Delete  */
    @GetMapping("/remove/{id}")
    public String remove(@PathVariable Integer id) {
    
        studentService.remove(id);
        return "redirect:/student/find";
    }

    /* *  Batch deletion  */
    @GetMapping("/remove")
    public String removeBatch(Integer[] ids) {
    
        studentService.removeBatch(ids);
        return "redirect:/student/find";
    }

    /* *  Single query  */
    @GetMapping("/find/{id}")
    public String findById(@PathVariable Integer id, Model model) {
    
        Student student = studentService.findById(id);
        model.addAttribute("student", student);
        // Jump to modify the student's view 
        return "stu/edit";
    }

    /* *  Paging query  * @param pageNum  Page number  * @param pageSize  Number of entries per page  * @param student  Entities containing query criteria  * @param model  Used to direct to request Domain stores data ui * @return java.lang.String  Jump to the view of the student list page  * *  The request received did not pageNum, The default value is 1 *  The request received did not pageSize, The default value is 5 */
    @GetMapping("/find")
    public String findPage(@RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                           @RequestParam(value = "pageSize", required = false, defaultValue = "5") Integer pageSize,
                           Student student, Model model) {
    
        PageInfo pageInfo = studentService.findPage(pageNum, pageSize, student);
        model.addAttribute("pageInfo", pageInfo);
        return "stu/list";
    }
}

6、 ... and 、 Front page implementation

6.1 home page

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center">
        <h1> This is the home page </h1>
        <a href="student/find"> Student information management </a>
    </div>
</body>
</html>

6.2 Student list page

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
    <style>
        .container {
            width: 600px;
            margin: auto;
        }

        .container > h1 {
            text-align: center;
        }

        table {
            width: 100%;
            border-collapse: collapse;
        }

        table, td, th {
            border: 1px solid black;
        }

        tr {
            height: 36px;
        }

        tr td:nth-child(1) {
            text-align: center;
        }

        .pager {
            text-align: center;
            padding: 10px 0;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1> Student data list </h1>
        <p>
            <%-- No direct access WEB-INF The following resources , Need to pass through Controller transit --%>
            <%--<a href="WEB-INF/views/stu/add.jsp"> New students </a>--%>
    
            <a href="page/stu/add"> New students </a> &emsp;
            <a href="javascript:removeBatch();"> Batch deletion </a>
        </p>
        <%-- With the help of form Forms can be deleted synchronously in batches --%>
        <form action="student/remove" method="GET" id="removeForm">
            <table>
                <thead>
                <tr>
                    <th><input type="checkbox"></th>
                    <th> The student's name </th>
                    <th> Student gender </th>
                    <th> departments / major </th>
                    <th> operation </th>
                </tr>
                </thead>
                <tbody>
                <c:forEach items="${pageInfo.list}" var="student">
                    <tr>
                        <td><input type="checkbox" name="ids" value="${student.id}"></td>
                        <td>${student.name}</td>
                        <td>${student.gender == '1'?' male ':' Woman '}</td>
                        <td>${student.major}</td>
                        <td>
                            <a href="student/find/${student.id}"> modify </a> &emsp;
                            <a href="student/remove/${student.id}" οnclick="return confirm(' Are you sure you want to delete this data ?')"> Delete </a>
                        </td>
                    </tr>
                </c:forEach>
                </tbody>
            </table>
        </form>
        <div class="pager">
             The current page / Total number of pages : ${pageInfo.pageNum}/${pageInfo.pages}
            <c:if test="${pageInfo.hasPreviousPage}">
                <a href="student/find?pageNum=${pageInfo.prePage}"> The previous page </a>
            </c:if>
            <c:forEach begin="1" end="${pageInfo.pages}" var="p">
                <c:if test="${pageInfo.pageNum != p}">
                    <a href="student/find?pageNum=${p}">【${p}】</a>
                </c:if>
                <c:if test="${pageInfo.pageNum == p}">
                    【${p}】
                </c:if>
            </c:forEach>
            <c:if test="${pageInfo.hasNextPage}">
                <a href="student/find?pageNum=${pageInfo.nextPage}"> The next page </a>
            </c:if>
        </div>
    </div>
    
    <script type="text/javascript" src="static/js/jquery-3.3.1.min.js"></script>
    <script type="text/javascript">
        function removeBatch() {
            console.log($)
    
            if ($(":checkbox:checked").length > 0) {
                if (confirm(" Are you sure you want to delete the data ?")) {
                    $("#removeForm").get(0).submit();
                }
            } else {
                alert(" Please select the student to delete !")
            }
        }
    </script>
</body>
</html>

SystemController.java:

/** *  The processor used to realize page Jump  */
@Controller
@RequestMapping("/page")
public class SystemController {
    

    @GetMapping("/stu/add")
    public String stuAdd() {
    
        return "stu/add";
    }
}

6.3 New page

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
    <style>
        .container {
            width: 600px;
            margin: auto;
        }

        .container > h1 {
            text-align: center;
        }


    </style>
</head>
<body>
    <div class="container">
        <h1> New student page </h1>
        <form action="student/add" method="POST">
            <p>
                <label for="name"> The student's name :</label>
                <input type="text" name="name" id="name" placeholder=" Please enter the student's name ">
            </p>
            <p>
                <label> Student gender :</label>
                <input type="radio" name="gender" value="1">  male 
                <input type="radio" name="gender" value="0">  Woman 
            </p>
            <p>
                <label for="major"> departments / major :</label>
                <input type="text" name="major" id="major" placeholder=" Please enter the Department / major ">
            </p>
            <p>
                <button type="submit"> newly added </button>
                <button type="reset"> Reset </button>
            </p>
        </form>
    </div>
</body>
</html>

6.4 Modify page

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
    <style>
        .container {
            width: 600px;
            margin: auto;
        }

        .container > h1 {
            text-align: center;
        }


    </style>
</head>
<body>
<div class="container">
    <h1> Students modify the page </h1>
    <form action="student/edit" method="POST">
        <input type="hidden" name="id" value="${student.id}">
        <p>
            <label for="name"> The student's name :</label>
            <input type="text" name="name" id="name" placeholder=" Please enter the student's name " value="${student.name}">
        </p>
        <p>
            <label> Student gender :</label>
            <input type="radio" name="gender" value="1" <c:if test="${student.gender == '1'}">checked</c:if>>  male 
            <input type="radio" name="gender" value="0" <c:if test="${student.gender == '0'}">checked</c:if>>  Woman 
        </p>
        <p>
            <label for="major"> departments / major :</label>
            <input type="text" name="major" id="major" placeholder=" Please enter the Department / major " value="${student.major}">
        </p>
        <p>
            <button type="submit"> Confirm modification </button>
            <button type="reset"> Reset </button>
        </p>
    </form>
</div>
</body>
</html>

SSM Integrate _ Asynchronous case

One 、 Table structure

-- ----------------------------
--  Permissions on the table 
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_permission`;
CREATE TABLE `t_sys_permission`  (
    `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
    `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ' Permission to name ',
    `type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' Authority type :1 Catalog  2 menu  3 Button ',
    `url` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '#' COMMENT ' Access address ',
    `percode` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' Authority code ',
    `parent_id` int(11) NULL DEFAULT 0 COMMENT ' Parent node ID',
    `sort` int(11) NULL DEFAULT NULL COMMENT ' According to the order ',
    `del` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT ' Whether or not to delete :0 normal 1 Delete ',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ' Permission information table ' ROW_FORMAT = Dynamic;

-- ----------------------------
--  Permission table data 
-- ----------------------------
INSERT INTO `t_sys_permission` VALUES (1, ' System management ', '1', '', 'system', 0, 1, '0');
INSERT INTO `t_sys_permission` VALUES (2, ' User list ', '2', '', 'user', 1, 11, '0');
INSERT INTO `t_sys_permission` VALUES (3, ' User query ', '3', '', 'user:query', 2, 111, '0');
INSERT INTO `t_sys_permission` VALUES (4, ' New users ', '3', '', 'user:add', 2, 112, '0');
INSERT INTO `t_sys_permission` VALUES (5, ' User edit ', '3', '', 'user:edit', 2, 113, '0');
INSERT INTO `t_sys_permission` VALUES (6, ' User deletion ', '3', '', 'user:remove', 2, 114, '0');
INSERT INTO `t_sys_permission` VALUES (7, ' Character list ', '2', '', 'role', 1, 12, '0');
INSERT INTO `t_sys_permission` VALUES (8, ' Role search ', '3', '', 'role:query', 7, 121, '0');
INSERT INTO `t_sys_permission` VALUES (9, ' Role addition ', '3', '', 'role:add', 7, 122, '0');
INSERT INTO `t_sys_permission` VALUES (10, ' Role editor ', '3', '', 'role:edit', 7, 123, '0');
INSERT INTO `t_sys_permission` VALUES (11, ' Character delete ', '3', '', 'role:remove', 7, 124, '0');
INSERT INTO `t_sys_permission` VALUES (12, ' Permission list ', '2', '', 'permission', 1, 13, '0');
INSERT INTO `t_sys_permission` VALUES (13, ' Permission query ', '3', '', 'permission:query', 12, 131, '0');
INSERT INTO `t_sys_permission` VALUES (14, ' New permission ', '3', '', 'permission:add', 12, 132, '0');
INSERT INTO `t_sys_permission` VALUES (15, ' Permission edit ', '3', '', 'permission:edit', 12, 133, '0');
INSERT INTO `t_sys_permission` VALUES (16, ' Permission deletion ', '3', '', 'permission:remove', 12, 134, '0');

-- ----------------------------
--  Role table 
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_role`;
CREATE TABLE `t_sys_role`  (
    `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
    `role_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ' Character encoding ',
    `role_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ' Character name ',
    `description` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' describe ',
    `del` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT ' Whether or not to delete :0 normal 1 Delete ',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ' Role information sheet ' ROW_FORMAT = Dynamic;

-- ----------------------------
--  Role table data 
-- ----------------------------
INSERT INTO `t_sys_role` VALUES (1, 'admin', ' Administrators ', ' Administrators ', '0');
INSERT INTO `t_sys_role` VALUES (2, 'user', ' Ordinary users ', ' Ordinary users ', '0');

-- ----------------------------
--  Role authority middle table 
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_role_permission`;
CREATE TABLE `t_sys_role_permission`  (
    `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ' Primary key ',
    `role_id` int(11) NOT NULL COMMENT ' role ID',
    `permission_id` int(11) NOT NULL COMMENT ' jurisdiction ID',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ' Role and permission association table ' ROW_FORMAT = Dynamic;

-- ----------------------------
--  Role permission intermediate table data 
-- ----------------------------
INSERT INTO `t_sys_role_permission` VALUES (1, 1, 1);
INSERT INTO `t_sys_role_permission` VALUES (2, 1, 2);
INSERT INTO `t_sys_role_permission` VALUES (3, 1, 3);
INSERT INTO `t_sys_role_permission` VALUES (4, 1, 4);
INSERT INTO `t_sys_role_permission` VALUES (5, 1, 5);
INSERT INTO `t_sys_role_permission` VALUES (6, 1, 6);
INSERT INTO `t_sys_role_permission` VALUES (7, 1, 7);
INSERT INTO `t_sys_role_permission` VALUES (8, 1, 8);
INSERT INTO `t_sys_role_permission` VALUES (9, 1, 9);
INSERT INTO `t_sys_role_permission` VALUES (10, 1, 10);
INSERT INTO `t_sys_role_permission` VALUES (11, 1, 11);
INSERT INTO `t_sys_role_permission` VALUES (12, 1, 12);
INSERT INTO `t_sys_role_permission` VALUES (13, 1, 13);
INSERT INTO `t_sys_role_permission` VALUES (14, 2, 1);
INSERT INTO `t_sys_role_permission` VALUES (15, 2, 2);
INSERT INTO `t_sys_role_permission` VALUES (16, 2, 6);
INSERT INTO `t_sys_role_permission` VALUES (17, 2, 10);

-- ----------------------------
--  User table 
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_user`;
CREATE TABLE `t_sys_user`  (
    `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ' Primary key ',
    `username` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ' Login account ',
    `mobile` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' Phone number ',
    `nickname` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ' The user nickname ',
    `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' User mailbox ',
    `userpwd` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' password ',
    `salt` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'newedu' COMMENT ' Encrypting salt ',
    `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT ' state :1 You can use 2 Unavailable ',
    `del` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT ' Whether or not to delete :0 normal 1 Delete ',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ' User information sheet ' ROW_FORMAT = Dynamic;

-- ----------------------------
--  User table data 
-- ----------------------------
INSERT INTO `t_sys_user` VALUES (1, 'admin', '13612345678', ' Administrators ', '[email protected]', '8f32e9f68d6886d095b230b93e7a2c86', 'newedu', '1', '0');
INSERT INTO `t_sys_user` VALUES (2, 'tom', '12345678901', ' Tom ', '[email protected]', '8f32e9f68d6886d095b230b93e7a2c86', 'newedu', '1', '0');

-- ----------------------------
--  User role middle table 
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_user_role`;
CREATE TABLE `t_sys_user_role`  (
    `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ' Primary key ',
    `user_id` int(11) NOT NULL COMMENT ' user ID',
    `role_id` int(11) NOT NULL COMMENT ' role ID',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ' User and role association table ' ROW_FORMAT = Dynamic;

-- ----------------------------
--  User role middle table data 
-- ----------------------------
INSERT INTO `t_sys_user_role` VALUES (1, 1, 1);
INSERT INTO `t_sys_user_role` VALUES (2, 1, 2);
INSERT INTO `t_sys_user_role` VALUES (3, 2, 2);

Two 、 Basic packaging

2.1 System code

package com.newcapec.constant;

/* *  System code : No Http Response code of the Protocol , It is our customized response code for some situations  *  effect : When the background responds to the front , In addition to the response data , Also respond to some coding , Through these codes, the front end can judge whether the operation is successful , Or failure , And the reasons for the failure . *  For example, the user name and password are not code errors , It just doesn't match the corresponding data , But from a business perspective, it's wrong , We can respond to the specified code to inform the front end of the problem . * */
public enum SystemCode {
    
    OK(200, " success "),
    USERNAME_EXISTS(401, " User name already exists "),
    USERNAME_ERROR(402, " Wrong user name or password "),
    NO_USER(403, " The user doesn't exist "),
    NOT_LOGIN(404, " The user is not logged in "),
    NO_PERMISSION(405, " Insufficient authority , Blocking access "),
    ERROR(500, " Failure ");

    int code;
    String message;

    SystemCode(int code, String message) {
    
        this.code = code;
        this.message = message;
    }

    public int getCode() {
    
        return code;
    }

    public void setCode(int code) {
    
        this.code = code;
    }

    public String getMessage() {
    
        return message;
    }

    public void setMessage(String message) {
    
        this.message = message;
    }
}

2.2 Common constant

package com.newcapec.constant;

/** *  Common constant , Try to avoid constant values in the system , Cause difficulties in later maintenance . *  such as : Before Controller As defined in pageNum,pageSize Are constant values , If you want to change the name later , All must be modified , Not conducive to maintenance . */
public class CommonConstant {
    

    /* *  Page name  */
    public static final String PAGE_NUM = "pageNum";
    /* *  Number of entries per page name  */
    public static final String PAGE_SIZE = "pageSize";
    /* *  Name of total records  */
    public static final String PAGE_TOTAL = "total";
    /* *  Data name of each page  */
    public static final String PAGE_LIST = "list";
    /* *  Page number defaults  */
    public static final String PAGE_NUM_DEFAULT = "1";
    /* *  The default value of entries per page  */
    public static final String PAGE_SIZE_DEFAULT = "10";
    /* *  Default password  */
    public static final String PASSWORD_DEFAULT = "123456";
}

2.3 Response format class

package com.newcapec.utils;

import com.newcapec.constant.SystemCode;

/** *  Response format class  *  effect : Unify the response data format of the server  */
public class Result<T> {
    

    /** *  Response code  */
    private int code;
    /** *  Response information  */
    private String message;
    /** *  The response data  */
    private T data;

    public Result(int code, String message, T data) {
    
        this.code = code;
        this.message = message;
        this.data = data;
    }

    /** *  A successful response : Do not transfer data to the page  */
    public static Result success() {
    
        return new Result(SystemCode.OK.getCode(), SystemCode.OK.getMessage(), null);
    }

    /** *  A successful response : Transfer data to the page  */
    public static <T> Result success(T data) {
    
        return new Result(SystemCode.OK.getCode(), SystemCode.OK.getMessage(), data);
    }

    /** *  Failed response : Do not transfer data to the page  */
    public static Result error() {
    
        return new Result(SystemCode.ERROR.getCode(), SystemCode.ERROR.getMessage(), null);
    }

    /** *  Failed response : Transfer data to the page  */
    public static <T> Result error(T data) {
    
        return new Result(SystemCode.ERROR.getCode(), SystemCode.ERROR.getMessage(), data);
    }

    /** *  Failed response : Transfer data to the page , And pass the response code and response information  */
    public static <T> Result error(int code, String message, T data) {
    
        return new Result(code, message, data);
    }

    public int getCode() {
    
        return code;
    }

    public void setCode(int code) {
    
        this.code = code;
    }

    public String getMessage() {
    
        return message;
    }

    public void setMessage(String message) {
    
        this.message = message;
    }

    public T getData() {
    
        return data;
    }

    public void setData(T data) {
    
        this.data = data;
    }
}

2.4 Persistence layer public interface

package com.newcapec.utils;

import java.util.List;

/* *  Persistence layer public interface  */
public interface BaseDao<T> {
    
    /* *  The new method  */
    void insert(T entity);

    /* *  Modification method  */
    void update(T entity);

    /* *  according to id Single deletion method  */
    void delete(Integer id);

    /* *  according to id Batch deletion method  */
    void deleteBatch(Integer[] ids);

    /* *  Batch query method  */
    List<T> select(T entity);

    /* *  according to id How to query  */
    T selectById(Integer id);
}

2.5 Business layer public interface

package com.newcapec.utils;

import java.util.List;
import java.util.Map;

/* *  Business layer public interface  */
public interface BaseService<T> {
    
    void add(T entity);

    void edit(T entity);

    void remove(Integer id);

    void removeBatch(Integer[] ids);

    List<T> find(T entity);

    /* *  In the synchronization case : Paging condition query , Our feedback is PageInfo object  *  however PageHelper It is recommended not to cross layers , For later maintenance . *  such as : Later we passed Mybatis-plus Replace mybatis, So if cross layer , It needs to be changed in many places . */
    Map<String, Object> findPage(Integer pageNum, Integer pageSize, T entity);

    T findById(Integer id);
}

3、 ... and 、 System user module

3.1 Entity class

package com.newcapec.entity;

/** *  System user entity class :  Basic functions for user table CURD Implementation of operations  */
public class SysUser {
    
    
    private Integer id;
    private String username;
    private String mobile;
    private String nickname;
    private String email;
    private String userpwd;
    private String salt;
    private String status;
    private String del;

    public Integer getId() {
    
        return id;
    }

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

    public String getUsername() {
    
        return username;
    }

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

    public String getMobile() {
    
        return mobile;
    }

    public void setMobile(String mobile) {
    
        this.mobile = mobile;
    }

    public String getNickname() {
    
        return nickname;
    }

    public void setNickname(String nickname) {
    
        this.nickname = nickname;
    }

    public String getEmail() {
    
        return email;
    }

    public void setEmail(String email) {
    
        this.email = email;
    }

    public String getUserpwd() {
    
        return userpwd;
    }

    public void setUserpwd(String userpwd) {
    
        this.userpwd = userpwd;
    }

    public String getSalt() {
    
        return salt;
    }

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

    public String getStatus() {
    
        return status;
    }

    public void setStatus(String status) {
    
        this.status = status;
    }

    public String getDel() {
    
        return del;
    }

    public void setDel(String del) {
    
        this.del = del;
    }
}

3.2 Persistence layer

Dao Interface :

package com.newcapec.dao;

import com.newcapec.entity.SysUser;
import com.newcapec.utils.BaseDao;

/* *  Inherit BaseDao The method defined in , It can also be extended . */
public interface SysUserDao extends BaseDao<SysUser> {
    

    /* *  Query according to user name  * 1、 register : Duplicate user name check  * 2、 The user login ( Refinement prompt use , First judge the user name , Then judge the password ) */
    SysUser selectByUsername(String username);
}

Mapper file :

<?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.newcapec.dao.SysUserDao">

    <insert id="insert" parameterType="com.newcapec.entity.SysUser" useGeneratedKeys="true" keyProperty="id">
        insert into t_sys_user(username, mobile, nickname, email, userpwd, salt)
        values (#{username}, #{mobile}, #{nickname}, #{email}, #{userpwd}, #{salt})
    </insert>

    <update id="update" parameterType="com.newcapec.entity.SysUser">
        update t_sys_user
        <set>
            <if test="username != null">
                username = #{username},
            </if>
            <if test="mobile != null">
                mobile = #{mobile},
            </if>
            <if test="nickname != null">
                nickname = #{nickname},
            </if>
            <if test="email != null">
                email = #{email},
            </if>
            <if test="userpwd != null">
                userpwd = #{userpwd},
            </if>
            <if test="salt != null">
                salt = #{salt},
            </if>
            <if test="status != null">
                status = #{status}
            </if>
        </set>
        where id = #{id}
    </update>

    <delete id="delete" parameterType="java.lang.Integer">
        update t_sys_user
        set del = 1
        where id = #{id}
    </delete>

    <delete id="deleteBatch" parameterType="java.lang.Integer">
        update t_sys_user set del = 1 where id in
        <foreach collection="array" open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </delete>


    <resultMap id="BaseResultMap" type="com.newcapec.entity.SysUser">
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="mobile" property="mobile"/>
        <result column="nickname" property="nickname"/>
        <result column="email" property="email"/>
        <result column="userpwd" property="userpwd"/>
        <result column="salt" property="salt"/>
        <result column="status" property="status"/>
    </resultMap>
    <select id="select" parameterType="com.newcapec.entity.SysUser" resultMap="BaseResultMap">
        select id, username, mobile, nickname, email, userpwd, salt, status from t_sys_user
        <where>
            <if test="username != null and username != ''">
                username like concat('%',#{username},'%')
            </if>
            <if test="nickname != null and nickname != ''">
                and nickname like concat('%',#{nickname},'%')
            </if>
            and del=0
        </where>
    </select>

    <select id="selectById" parameterType="java.lang.Integer" resultType="com.newcapec.entity.SysUser">
        select id, username, mobile, nickname, email, userpwd, salt, status from t_sys_user
        where id = #{id} and del=0
    </select>

    <select id="selectByUsername" parameterType="java.lang.String" resultType="com.newcapec.entity.SysUser">
        select id, username, mobile, nickname, email, userpwd, salt from t_sys_user
        where username = #{username} and del=0
    </select>
</mapper>

3.3 The business layer

Service Interface :

package com.newcapec.service;

import com.newcapec.entity.SysUser;
import com.newcapec.utils.BaseService;

public interface SysUserService extends BaseService<SysUser> {
    

    SysUser findByUsername(String username);
}

Service Interface implementation class :

package com.newcapec.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.newcapec.constant.CommonConstant;
import com.newcapec.dao.SysUserDao;
import com.newcapec.entity.Student;
import com.newcapec.entity.SysUser;
import com.newcapec.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Service
public class SysUserServiceImpl implements SysUserService {
    

    @Autowired
    private SysUserDao sysUserDao;

    @Override
    public SysUser findByUsername(String username) {
    
        return sysUserDao.selectByUsername(username);
    }

    @Override
    public void add(SysUser entity) {
    
        SysUser sysUser = findByUsername(entity.getUsername());
        // Background verification , Guarantee safety , Prevent third-party tools from registering (PostMan)
        if (sysUser == null) {
    
            entity.setUserpwd(CommonConstant.PASSWORD_DEFAULT);
            sysUserDao.insert(entity);
        }
    }

    @Override
    public void edit(SysUser entity) {
    
        SysUser sysUser = findByUsername(entity.getUsername());
        if (sysUser != null) {
    
            sysUserDao.update(entity);
        }
    }

    @Override
    public void remove(Integer id) {
    
        sysUserDao.delete(id);
    }

    @Override
    public void removeBatch(Integer[] ids) {
    
        sysUserDao.deleteBatch(ids);
    }

    @Override
    public List<SysUser> find(SysUser entity) {
    
        return sysUserDao.select(entity);
    }

    @Override
    public Map<String, Object> findPage(Integer pageNum, Integer pageSize, SysUser entity) {
    
        // Paging business implementation 
        PageHelper.startPage(pageNum, pageSize);

        List<SysUser> list = sysUserDao.select(entity);

        PageInfo<SysUser> pageInfo = new PageInfo<>(list);

        /* *  Feed back the data needed by the front desk  * 1、 Current page data ( Data list ) * 2、 Total records of this query  */
        Map<String, Object> pageMap = new HashMap<>();
        pageMap.put(CommonConstant.PAGE_LIST, list);
        pageMap.put(CommonConstant.PAGE_TOTAL, pageInfo.getTotal());

        return pageMap;
    }

    @Override
    public SysUser findById(Integer id) {
    
        return sysUserDao.selectById(id);
    }
}

3.4 Control layer

package com.newcapec.controller;

import com.newcapec.constant.CommonConstant;
import com.newcapec.constant.SystemCode;
import com.newcapec.entity.SysUser;
import com.newcapec.service.SysUserService;
import com.newcapec.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

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

    @Autowired
    private SysUserService sysUserService;

    /** *  newly added  */
    @PostMapping("/add")
    public Result add(@RequestBody SysUser sysUser) {
    
        sysUserService.add(sysUser);
        return Result.success();
    }

    /** *  edit  */
    @PutMapping("/edit")
    public Result edit(@RequestBody SysUser sysUser) {
    
        sysUserService.edit(sysUser);
        return Result.success();
    }

    /** *  Delete  */
    @DeleteMapping("/remove/{id}")
    public Result remove(@PathVariable Integer id) {
    
        sysUserService.remove(id);
        return Result.success();
    }

    /** *  Batch deletion  */
    @DeleteMapping("/remove")
    public Result removeBatch(Integer[] ids) {
    
        sysUserService.removeBatch(ids);
        return Result.success();
    }

    /** *  Single query  */
    @GetMapping("/find/{id}")
    public Result findById(@PathVariable Integer id) {
    
        return Result.success(sysUserService.findById(id));
    }

    /** *  Paging query  */
    @GetMapping("/find")
    public Result findPage(@RequestParam(value = CommonConstant.PAGE_NUM, required = false, defaultValue = CommonConstant.PAGE_NUM_DEFAULT) Integer pageNum,
                           @RequestParam(value = CommonConstant.PAGE_SIZE, required = false, defaultValue = CommonConstant.PAGE_SIZE_DEFAULT) Integer pageSize,
                           SysUser sysUser) {
    
        return Result.success(sysUserService.findPage(pageNum, pageSize, sysUser));
    }

    /** *  Determine if the user name is duplicate  */
    @GetMapping("/findExists/{username}")
    public Result findUsernameExists(@PathVariable String username) {
    
        SysUser sysUser = sysUserService.findByUsername(username);
        if (sysUser == null) {
    
            return Result.success();
        }
        return Result.error(SystemCode.USERNAME_EXISTS.getCode(), SystemCode.USERNAME_EXISTS.getMessage(), null);
    }
}

3.5 test

	 All queries are Get request , You can test directly through the browser .
	
	 But increase 、 Delete 、 Change , The background programmer test can pass Postman.

Batch query test :

 Insert picture description here

Single query test ( Path parameter ):

 Insert picture description here

 Insert picture description here

Paging query test ( Path parameter splicing ):

 Insert picture description here

New test :

 Insert picture description here

Revision Test :

 Insert picture description here

Single delete test :

 Insert picture description here

Batch delete test :

 Insert picture description here

3.6 Foreground page

3.6.1 home page

	 be based on Layui Classic layout revision .
	
	 Address :https://www.layuion.com/doc/element/layout.html#admin
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title> Background management system </title>
    <!-- introduce Layui The style file -->
    <link rel="stylesheet" href="static/layui/css/layui.css">
</head>
<body>
<!-- introduce layui Classic layout and revision -->
<div class="layui-layout layui-layout-admin">
    <!-- Page header -->
    <div class="layui-header">
        <div class="layui-logo layui-hide-xs layui-bg-black"> Background management system </div>
        <ul class="layui-nav layui-layout-right">
            <li class="layui-nav-item layui-hide layui-show-md-inline-block">
                <a href="javascript:;">
                    <img src="//tva1.sinaimg.cn/crop.0.0.118.118.180/5db11ff4gw1e77d3nqrv8j203b03cweg.jpg"
                         class="layui-nav-img">
                     Administrators 
                </a>
                <dl class="layui-nav-child">
                    <dd><a href=""> Personal information </a></dd>
                    <dd><a href=""> System settings </a></dd>
                    <dd><a href=""> Exit the system </a></dd>
                </dl>
            </li>
        </ul>
    </div>

    <div class="layui-side layui-bg-black">
        <div class="layui-side-scroll">
            <!--  Left navigation area ( Compatible layui Existing vertical navigation ) -->
            <ul class="layui-nav layui-nav-tree" lay-filter="test">
                <li class="layui-nav-item layui-nav-itemed">
                    <a class="" href="javascript:;"> System management </a>
                    <dl class="layui-nav-child">
                        <dd><a href="page/sys/user" target="mainFrame"> User list </a></dd>
                        <dd><a href="page/sys/role" target="mainFrame"> Character list </a></dd>
                        <dd><a href="page/sys/permission" target="mainFrame"> Permission list </a></dd>
                    </dl>
                </li>
                <li class="layui-nav-item">
                    <a href="javascript:;"> The business management </a>
                    <dl class="layui-nav-child">
                        <dd><a href="student/find" target="mainFrame"> Student list </a></dd>
                        <dd><a href="javascript:;"> List of employees </a></dd>
                        <dd><a href="javascript:;"> Department list </a></dd>
                    </dl>
                </li>
            </ul>
        </div>
    </div>

    <div class="layui-body">
        <!--  Content subject area  -->
        <iframe name="mainFrame" frameborder="0" style="width:100%;height: 100%" src="page/welcome"></iframe>
    </div>

    <div class="layui-footer">
        <!--  Bottom fixed area  -->
         Bottom fixed area 
    </div>
</div>

<!-- introduce layui.js file -->
<script type="text/javascript" src="static/layui/layui.js"></script>
</body>
</html>

structure :

 Insert picture description here

welcome.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
    <style>
        h1 {
            text-align: center;
            margin-top: 120px;
        }
    </style>
</head>
<body>
    <h1> Welcome to the background management system </h1>
</body>
</html>

SystemController.java:

package com.newcapec.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

/** *  The processor used to realize page Jump  */
@Controller
@RequestMapping("/page")
public class SystemController {
    

    @GetMapping("/stu/add")
    public String stuAdd() {
    
        return "stu/add";
    }

    @GetMapping("/welcome")
    public String welcome() {
    
        return "welcome";
    }

    @GetMapping("/sys/user")
    public String sysUser() {
    
        return "sys/user";
    }

    @GetMapping("/sys/role")
    public String sysRole() {
    
        return "sys/role";
    }

    @GetMapping("/sys/permission")
    public String sysPermission() {
    
        return "sys/permission";
    }

    @GetMapping("/emp")
    public String emp() {
    
        return "emp/find";
    }

    @GetMapping("/dept")
    public String dept() {
    
        return "dept/find";
    }

    @GetMapping("/index")
    public String index() {
    
        return "index";
    }

    @GetMapping("/login")
    public String login() {
    
        return "login";
    }
}

3.6.2 User management page

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
    <!-- introduce Layui The style file -->
    <link rel="stylesheet" href="static/layui/css/layui.css">
    <style>
        .layui-inline {
            margin-right: 15px
        }

        .layui-fluid {
            padding-top: 15px;
        }

        /*layui Data table check box correction */
        .layui-table-view .layui-form-checkbox i {
            margin-top: 5px;
        }
    </style>
</head>
<body>
<div class="layui-fluid">
    <!--  User list page header area : Show the search box 、 Search button 、 Add a button 、 Batch delete button  -->
    <blockquote class="layui-elem-quote">
        <form class="layui-form" action="">
            <div class="layui-inline">
                <input type="text" id="username" name="username" placeholder=" user name " class="layui-input">
            </div>
            <div class="layui-inline">
                <input type="text" id="nickname" name="nickname" placeholder=" nickname " class="layui-input">
            </div>
            <div class="layui-inline">
                <a class="layui-btn" id="searchBtn"> Search for </a>
                <a class="layui-btn layui-btn-normal" id="addBtn"> add to </a>
                <a class="layui-btn layui-btn-danger" id="removeBatchBtn"> Batch deletion </a>
            </div>
        </form>
    </blockquote>

    <!--  Data table : Display data , The contents and data in the table are through js Rendered  -->
    <table id="dataTable" lay-filter="dataTable"></table>

    <!--  Operation data template  -->
    <script type="text/html" id="operateBar">
        <a class="layui-btn layui-btn-sm layui-btn-warm" lay-event="edit"> edit </a>
        <a class="layui-btn layui-btn-sm layui-btn-danger" lay-event="remove"> Delete </a>
    </script>

    <!--dataWindow Page layer -->
    <div id="dataWindow" style="display: none;padding: 10px">
        <form id="dataForm" class="layui-form" lay-filter="dataForm">
            <!--layui There are hidden fields that cannot get values bug, The following wording is recommended -->
            <input type="text" name="id" style="display: none">
            <div class="layui-form-item">
                <label class="layui-form-label"> user name </label>
                <div class="layui-input-block">
                    <input type="text" id="dataFormUsername" name="username" required
                           lay-verify="required|usernameVerify"
                           placeholder=" Please enter a user name "
                           class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label"> cell-phone number </label>
                <div class="layui-input-block">
                    <input type="text" name="mobile" required lay-verify="required|phone" placeholder=" Please enter your mobile number "
                           class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label"> nickname </label>
                <div class="layui-input-block">
                    <input type="text" name="nickname" required lay-verify="required" placeholder=" Please enter your nickname "
                           class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label"> mailbox </label>
                <div class="layui-input-block">
                    <input type="text" name="email" required lay-verify="required|email" placeholder=" Please enter email address "
                           class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label"> Encrypting salt </label>
                <div class="layui-input-block">
                    <input type="text" name="salt" required lay-verify="required" placeholder=" Please enter encryption salt "
                           class="layui-input">
                </div>
            </div>

            <div class="layui-form-item">
                <label class="layui-form-label"> User state </label>
                <div class="layui-input-block">
                    <select name="status" lay-verify="required">
                        <option value=""></option>
                        <option value="1"> normal </option>
                        <option value="2"> Ban </option>
                    </select>
                </div>
            </div>
            <!-- The button to actually submit data , By the pop-up layer yes Callback trigger -->
            <button id="submitBtn" lay-submit lay-filter="submitBtn" style="display: none"> Submit... Immediately </button>
        </form>
    </div>
</div>

<!-- introduce layui.js file -->
<script type="text/javascript" src="static/layui/layui.js"></script>
<script type="text/javascript">
    // Load module 
    layui.use(['table', 'form', 'layer'], function () {
        var table = layui.table,
            form = layui.form,
            layer = layui.layer,
            $ = layui.$;

        // Table data rendering 
        table.render({
            //id: Set container unique  id.id  It is a necessary transfer condition for the data operation of the table .
            id: 'dataTable',
            elem: '#dataTable',
            //height: 312,
            method: 'get',
            url: 'user/find', // Data interface 
            page: true,  // Open paging 
            limit: '10', // Data requested per page 
            limits: [10, 20, 30, 40, 50],
            cols: [[ // Header 
                {type: 'checkbox', width: 50, fixed: 'left'},
                {field: 'id', title: 'ID', minWidth: 50, fixed: 'left', align: 'center'},
                {field: 'username', title: ' user name ', minWidth: 100, fixed: 'left', align: 'center'},
                {field: 'mobile', title: ' cell-phone number ', align: 'center'},
                {field: 'nickname', title: ' nickname ', align: 'center'},
                {field: 'email', title: ' mailbox ', align: 'center'},
                {field: 'salt', title: ' Encrypting salt ', align: 'center'},
                {
                    field: 'status', title: ' User state ', align: 'center', templet: function (d) {
                        return d.status == '1' ? ' normal ' : ' Ban ';
                    }
                },
                {title: ' operation ', minWidth: 150, fixed: 'right', align: 'center', templet: '#operateBar'},
            ]],
            parseData: function (res) { //res  That is, the original returned data 
                return {
                    "code": res.code, // Parse interface state 
                    "msg": res.message, // Parse prompt text 
                    "count": res.data.total, // Parse data length 
                    "data": res.data.list // Parse data list 
                };
            },
            request: {
                pageName: 'pageNum', // Parameter name of page number , Default :page
                limitName: 'pageSize' // Parameter name of data volume per page , Default :limit
            },
            response: {
                // Specify the successful status code , Default :0
                statusCode: 200
            }
        });

        // Conditions of the query 
        $("#searchBtn").click(function () {
            tableReload();
        });

        $("#addBtn").click(function () {
            // Add without passing id value 
            addOrEdit();
        })

        var window_index = -1; // Default form index value 
        function addOrEdit(id) {
            // Page layer 
            layer.open({
                type: 1,
                title: id ? ' Modify the user ' : ' New users ',
                content: $('#dataWindow'),
                area: ['500px', '500px'], // Wide and high 
                btn: [' determine ', ' Cancel '],
                yes: function (index) {
                    // If you set yes Callback , Manual closing is required 
                    //layer.close(index);
                    window_index = index;

                    // Click the OK button , Submit form data 
                    $("#submitBtn").click();
                },
                end: function () {
                    window_index = -1; // Reset form index defaults 
                    // Reset form 
                    $('#dataForm')[0].reset();

                    $("#dataFormUsername").prop('readonly', '');
                    $("#dataFormUsername").attr('lay-verify', 'required|usernameVerify');
                }
            });
        }

        // Add a form submission event 
        form.on('submit(submitBtn)', function (data) {
            // All form fields of the current container , Name value pair form :{name: value}
            console.log(data.field)
            // Judge the form id Whether the field has a value , If it's worth it , Perform modification operations , Otherwise, execute new .
            var url = 'user/add', method = 'post';
            if (data.field.id) {
                url = 'user/edit';
                method = 'put';
            }
            //console.log(data);
            $.ajax(url, {
                type: method,
                contentType: 'application/json',
                data: JSON.stringify(data.field),
                success: function (res) {
                    if (res.code == 200) {
                        // Close page layer 
                        layer.close(window_index);
                        layer.msg(res.message);
                        tableReload();
                    }
                }
            })
            return false; // Prevent form jump . If you need a form jump , Just remove this paragraph .
        });

        form.verify({
            usernameVerify: function (value) { //value: Value of form 、item: Form DOM object 
                if (!new RegExp("^[a-zA-Z0-9_\u4e00-\u9fa5\\s·]+$").test(value)) {
                    return ' The user name cannot have special characters ';
                }
                if (/(^\_)|(\__)|(\_+$)/.test(value)) {
                    return ' The beginning and end of the user name cannot be underlined \'_\'';
                }
                if (/^\d+\d+\d$/.test(value)) {
                    return ' The user name cannot be all numbers ';
                }

                // Verify the uniqueness of the user name 
                var result = '';
                $.ajax('user/findExists/' + value, {
                    async: false,
                    type: 'get',
                    success: function (res) {
                        if (res.code == 401) {
                            result = res.message;
                        }
                    }
                })
                return result;
            }

        });


        $("#removeBatchBtn").click(function () {
            // Call the function to delete data in batch 
            removeBatch();
        });

        // Toolbar events 
        // notes :tool  Is the toolbar event name ,test  yes  table  Properties of the original container  lay-filter=" Corresponding value "
        table.on('tool(dataTable)', function (obj) {
            var data = obj.data; // Get current row data 
            var layEvent = obj.event; // get  lay-event  Corresponding value ( It can also be in the header  event  The corresponding value of the parameter )

            if (layEvent === 'remove') { // Delete 
                remove(data.id);
            } else if (layEvent === 'edit') { // edit 
                // The echo data 
                // Assign values to the form :dataForm  namely  class="layui-form"  Attribute of the element  lay-filter=""  Corresponding value 
                form.val("dataForm", data);

                /*
                *  When the user performs an editing operation :
                *   1、 The user name is read-only 
                *   2、 User name does not need unique verification 
                * */
                $("#dataFormUsername").prop('readonly', 'readonly');
                $("#dataFormUsername").attr('lay-verify', '');

                addOrEdit(data.id);
            }

        });

        // A single function to delete data 
        function remove(id) {
            layer.confirm(' Are you sure you want to delete ?', function (index) {
                // Send delete instruction to the server 
                $.ajax('user/remove/' + id, {
                    type: 'delete',
                    success: function (res) {
                        if (res.code == 200) {
                            layer.msg(res.message);
                            // Reload table data 
                            tableReload();
                        }
                    }
                })
            });
        }

        // A single function to delete data 
        function removeBatch() {

            var checkStatus = table.checkStatus('dataTable'); //dataTable  Is the basic parameter  id  Corresponding value 

            var data = checkStatus.data; // Get the data of the selected row 

            if (data.length == 0) {
                layer.msg(" Please select the data to delete !");
            } else {
                layer.confirm(' Are you sure you want to delete ?', function (index) {
                    var ids = [];

                    data.forEach(function (item) {
                        ids.push(item.id);
                    })

                    // Send delete instruction to the server 
                    $.ajax('user/remove?ids=' + ids.join(), {
                        type: 'delete',
                        success: function (res) {
                            if (res.code == 200) {
                                layer.msg(res.message);
                                // Reload table data 
                                tableReload();
                            }
                        }
                    })
                });
            }
        }

        // Reload table functions 
        function tableReload() {
            table.reload('dataTable', {
                // Combined with the following search 
                where: {
                    username: $("#username").val(),
                    nickname: $("#nickname").val()
                }
            })
        }
    });
</script>
</body>
</html>

Four 、 System role module

4.1 Entity class

package com.newcapec.entity;

public class SysRole {
    

    private Integer id;
    private String roleCode;
    private String roleName;
    private String description;
    private String del;

    public Integer getId() {
    
        return id;
    }

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

    public String getRoleCode() {
    
        return roleCode;
    }

    public void setRoleCode(String roleCode) {
    
        this.roleCode = roleCode;
    }

    public String getRoleName() {
    
        return roleName;
    }

    public void setRoleName(String roleName) {
    
        this.roleName = roleName;
    }

    public String getDescription() {
    
        return description;
    }

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

    public String getDel() {
    
        return del;
    }

    public void setDel(String del) {
    
        this.del = del;
    }
}

4.2 Persistence layer

Dao Interface :

package com.newcapec.dao;

import com.newcapec.entity.SysRole;
import com.newcapec.utils.BaseDao;

public interface SysRoleDao extends BaseDao<SysRole> {
    

}

Mapper file :

<?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.newcapec.dao.SysRoleDao">

    <insert id="insert" parameterType="com.newcapec.entity.SysRole" useGeneratedKeys="true" keyProperty="id">
        insert into t_sys_role(role_code, role_name, description)
        values(#{roleCode}, #{roleName}, #{description})
    </insert>

    <update id="update" parameterType="com.newcapec.entity.SysRole">
        update t_sys_role
        <set>
            <if test="roleCode != null">
                role_code = #{roleCode},
            </if>
            <if test="roleName != null">
                role_name = #{roleName},
            </if>
            <if test="description != null">
                description = #{description},
            </if>
        </set>
        where id = #{id}
    </update>

    <delete id="delete" parameterType="java.lang.Integer">
        update t_sys_role set del=1 where id = #{id}
    </delete>

    <delete id="deleteBatch" parameterType="java.lang.Integer">
        update t_sys_role set del=1 where id in
        <foreach collection="array" open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </delete>

    <resultMap id="BaseResultMap" type="com.newcapec.entity.SysRole">
        <id column="id" property="id"/>
        <result column="role_code" property="roleCode"/>
        <result column="role_name" property="roleName"/>
        <result column="description" property="description"/>
    </resultMap>
    <select id="select" parameterType="com.newcapec.entity.SysRole" resultMap="BaseResultMap">
        select id, role_code, role_name, description from t_sys_role
        <where>
            <if test="roleCode != null and roleCode != ''">
                role_code like concat('%',#{roleCode},'%')
            </if>
            <if test="roleName != null and roleName != ''">
                and role_name like concat('%',#{roleName},'%')
            </if>
            and del=0
        </where>
    </select>


    <select id="selectById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
        select id, role_code, role_name, description from t_sys_role
        where id = #{id} and del=0
    </select>

</mapper>

4.3 The business layer

Service Interface :

package com.newcapec.service;

import com.newcapec.entity.SysRole;
import com.newcapec.utils.BaseService;

public interface SysRoleService extends BaseService<SysRole> {
    
}

Service Interface implementation class :

package com.newcapec.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.newcapec.constant.CommonConstant;
import com.newcapec.dao.SysRoleDao;
import com.newcapec.entity.SysRole;
import com.newcapec.service.SysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Service
public class SysRoleServiceImpl implements SysRoleService {
    

    @Autowired
    private SysRoleDao sysRoleDao;

    @Override
    public void add(SysRole entity) {
    
        sysRoleDao.insert(entity);
    }

    @Override
    public void edit(SysRole entity) {
    
        sysRoleDao.update(entity);
    }

    @Override
    public void remove(Integer id) {
    
        sysRoleDao.delete(id);
    }

    @Override
    public void removeBatch(Integer[] ids) {
    
        sysRoleDao.deleteBatch(ids);
    }

    @Override
    public List<SysRole> find(SysRole entity) {
    
        return sysRoleDao.select(entity);
    }

    @Override
    public Map<String, Object> findPage(Integer pageNum, Integer pageSize, SysRole entity) {
    
        // Paging service 
        PageHelper.startPage(pageNum, pageSize);
        List<SysRole> list = sysRoleDao.select(entity);
        PageInfo<SysRole> pageInfo = new PageInfo<>(list);
        //1. Current page data ( Data list )2. Total records of this query 
        Map<String, Object> pageMap = new HashMap<>();
        pageMap.put(CommonConstant.PAGE_LIST, list);
        pageMap.put(CommonConstant.PAGE_TOTAL, pageInfo.getTotal());
        return pageMap;
    }

    @Override
    public SysRole findById(Integer id) {
    
        return sysRoleDao.selectById(id);
    }
}

4.4 Control layer

package com.newcapec.controller;

import com.newcapec.constant.CommonConstant;
import com.newcapec.entity.SysRole;
import com.newcapec.service.SysRoleService;
import com.newcapec.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/role")
public class SysRoleController {
    

    @Autowired
    private SysRoleService sysRoleService;

    /** *  newly added  */
    @PostMapping("/add")
    public Result add(@RequestBody SysRole sysRole) {
    
        sysRoleService.add(sysRole);
        return Result.success();
    }

    /** *  edit  */
    @PutMapping("/edit")
    public Result edit(@RequestBody SysRole sysRole) {
    
        sysRoleService.edit(sysRole);
        return Result.success();
    }

    /** *  Delete  */
    @DeleteMapping("/remove/{id}")
    public Result remove(@PathVariable Integer id) {
    
        sysRoleService.remove(id);
        return Result.success();
    }

    /** *  Batch deletion  */
    @DeleteMapping("/remove")
    public Result removeBatch(Integer[] ids) {
    
        sysRoleService.removeBatch(ids);
        return Result.success();
    }

    /** *  Single query  */
    @GetMapping("/find/{id}")
    public Result findById(@PathVariable Integer id) {
    
        return Result.success(sysRoleService.findById(id));
    }

    /** *  Paging query  */
    @GetMapping("/findPage")
    public Result findPage(@RequestParam(value = CommonConstant.PAGE_NUM, required = false, defaultValue = CommonConstant.PAGE_NUM_DEFAULT) Integer pageNum,
                           @RequestParam(value = CommonConstant.PAGE_SIZE, required = false, defaultValue = CommonConstant.PAGE_SIZE_DEFAULT) Integer pageSize,
                           SysRole sysRole) {
    
        return Result.success(sysRoleService.findPage(pageNum, pageSize, sysRole));
    }

    /** *  Inquire about  */
    @GetMapping("/find")
    public Result find(SysRole sysRole) {
    
        return Result.success(sysRoleService.find(sysRole));
    }
}

4.5 Foreground page

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
    <link rel="stylesheet" href="static/layui/css/layui.css">
    <style>
        /*layui Data table check box correction */
        .layui-table-view .layui-form-checkbox i {
            margin-top: 5px;
        }
    </style>
</head>
<body>
<div style="padding: 10px">
    <blockquote class="layui-elem-quote">
        <form class="layui-form">
            <div class="layui-inline">
                <input type="text" id="roleCode" name="roleCode" placeholder=" Character encoding " class="layui-input">
            </div>
            <div class="layui-inline">
                <input type="text" id="roleName" name="roleName" placeholder=" Character name " class="layui-input">
            </div>
            <div class="layui-inline">
                <a class="layui-btn searchBtn"> Search for </a>
                <a class="layui-btn layui-btn-normal addBtn"> add to </a>
                <a class="layui-btn layui-btn-danger removeBtn"> Batch deletion </a>
            </div>
        </form>
    </blockquote>
    <table id="tab" lay-filter="tab"></table>

    <!-- Operations in the table -->
    <script type="text/html" id="roleBar">
        <a class="layui-btn layui-btn-xs layui-btn-warm" lay-event="edit"> edit </a>
        <a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="remove"> Delete </a>
    </script>

    <!-- Forms -->
    <div id="dataWindow" style="display: none;padding: 10px;">
        <form id="dataForm" class="layui-form" lay-filter="dataForm">
            <input type="text" name="id" style="display: none;">
            <div class="layui-form-item">
                <label class="layui-form-label"> Character encoding </label>
                <div class="layui-input-block">
                    <input type="text" name="roleCode" lay-verify="required" placeholder=" Please enter the character code " class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label"> Character name </label>
                <div class="layui-input-block">
                    <input type="text" name="roleName" lay-verify="required" placeholder=" Please enter the role name " class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label"> describe </label>
                <div class="layui-input-block">
                    <input type="text" name="description" lay-verify="required" placeholder=" Please enter a description " class="layui-input">
                </div>
            </div>
            <%--<div class="layui-form-item">
                <label class="layui-form-label"> jurisdiction </label>
                <div class="layui-input-block">
                    <div id="permissionTree"></div>
                </div>
            </div>--%>

            <button class="submitBtn" lay-submit lay-filter="submitBtn" style="display: none;"> Submit... Immediately </button>
        </form>
    </div>
</div>
<script type="text/javascript" src="static/layui/layui.js"></script>
<script type="text/javascript">
    layui.use(['table', 'form', 'layer', 'tree'], function () {
        var form = layui.form,
            layer = layui.layer,
            table = layui.table,
            tree = layui.tree,
            $ = layui.$;

        // Asynchronous table initialization 
        table.render({
            id: 'roleTable',
            elem: '#tab',
            // Asynchronous requests 
            method: 'get',
            url: 'role/findPage',
            // Pagination 
            page: true,
            limit: 10,
            limits: [10, 20, 30, 50],
            // Set the header 
            cols: [[
                {type: 'checkbox', width: 50, fixed: 'left'},
                {field: 'id', title: 'ID', minWidth: 50, fixed: 'left', align: 'center'},
                {field: 'roleCode', title: ' Character encoding ', minWidth: 100, fixed: 'left', align: 'center'},
                {field: 'roleName', title: ' Character name ', align: 'center'},
                {field: 'description', title: ' describe ', align: 'center'},
                {title: ' operation ', minWidth: 150, fixed: 'right', align: 'center', templet: '#roleBar'}
            ]],
            //res  It is the data of the background response 
            parseData: function (res) {
                return {
                    // Parse interface state 
                    'code': res.code,
                    // Parse prompt text 
                    'msg': res.message,
                    // Parse data length 
                    'count': res.data.total,
                    // Parse data list 
                    'data': res.data.list
                };
            },
            request: {
                // Parameter name of page number , Default :page
                pageName: 'pageNum',
                // Parameter name of data volume per page , Default :limit
                limitName: 'pageSize'
            },
            response: {
                // Specify the successful status code , Default :0
                statusCode: 200
            }
        });

        // Conditions of the query 
        $('.searchBtn').click(function () {
            tableReload();
        });

        // Line tool Events 
        // notes :tool  Is the toolbar event name ,test  yes  table  Properties of the original container  lay-filter=" Corresponding value "
        table.on('tool(tab)', function (obj) {
            // Get current row data 
            var data = obj.data;
            // get  lay-event  Corresponding value ( It can also be in the header  event  The corresponding value of the parameter )
            var layEvent = obj.event;

            if (layEvent == 'edit') {
                // The echo data 
                form.val("dataForm", data);

                // Click the edit button 
                addOrEdit(data.id);
            } else if (layEvent == 'remove') {
                // Click the delete button 
                remove(data.id);
            }
        });

        // Single delete function 
        function remove(id) {
            layer.confirm(' Are you sure you want to delete ?', function () {
                // Delete by asynchronous request 
                $.ajax('role/remove/' + id, {
                    type: 'delete',
                    success: function (res) {
                        if (res.code == 200) {
                            layer.msg(res.message);
                            // Table overload 
                            tableReload();
                        }
                    }
                });
            });
        }

        // Batch delete function 
        function removeBatch() {
            // Get the selected data status of the table 
            var checkStatus = table.checkStatus('roleTable');
            // Get selected data 
            var checkData = checkStatus.data;
            if (checkData.length == 0) {
                layer.msg(' Please select the data to delete ');
            } else {
                layer.confirm(' Are you sure you want to delete ?', function () {
                    var array = [];
                    checkData.forEach(function (item) {
                        array.push(item.id);
                    });
                    $.ajax('role/remove?ids=' + array.join(), {
                        type: 'delete',
                        success: function (res) {
                            if (res.code == 200) {
                                layer.msg(res.message);
                                // Table overload 
                                tableReload();
                            }
                        }
                    });
                });
            }
        }

        $('.removeBtn').click(function () {
            removeBatch();
        })

        // newly added 
        var window_index = -1;

        function addOrEdit(id) {
            layer.open({
                type: 1,
                title: id ? ' Role editor ' : ' Role addition ',
                content: $('#dataWindow'),
                btn: [' determine ', ' Cancel '],
                // Click the OK button to the event 
                yes: function (index) {
                    window_index = index
                    $('.submitBtn').click();
                },
                // Click the pop-up layer to hide the event 
                end: function () {
                    window_index = -1;
                    // Empty the form 
                    $('#dataForm')[0].reset();
                }
            });
        }

        $('.addBtn').click(function () {
            addOrEdit();
        });

        // Form submission time 
        form.on('submit(submitBtn)', function (data) {
            // All form fields of the current container , Name value pair form :{name: value}
            var url = 'role/add';
            var method = 'post';
            if (data.field.id) {
                //id Parameter data indicates that the current operation is edit , Otherwise, it is new 
                url = 'role/edit';
                method = 'put';
            }

            $.ajax(url, {
                type: method,
                contentType: 'application/json',
                data: JSON.stringify(data.field),
                success: function (res) {
                    if (res.code = 200) {
                        layer.close(window_index);
                        layer.msg(res.message);
                        tableReload();
                    }
                }
            });
            // Prevent form jump . If you need a form jump , Just remove this paragraph .
            return false;
        });

        // Table overload 
        function tableReload() {
            table.reload('roleTable', {
                where: {
                    roleCode: $('#roleCode').val(),
                    roleName: $('#roleName').val()
                }
            });
        }

    });
</script>
</body>
</html>

5、 ... and 、 System authority module

5.1 Entity class

package com.newcapec.entity;

public class SysPermission {
    

    private Integer id;
    private String name;
    private String type;
    private String url;
    private String percode;
    private Integer parentId;
    private Integer sort;
    private String del;

    public Integer getId() {
    
        return id;
    }

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

    public String getName() {
    
        return name;
    }

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

    public String getType() {
    
        return type;
    }

    public void setType(String type) {
    
        this.type = type;
    }

    public String getUrl() {
    
        return url;
    }

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

    public String getPercode() {
    
        return percode;
    }

    public void setPercode(String percode) {
    
        this.percode = percode;
    }

    public Integer getParentId() {
    
        return parentId;
    }

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

    public Integer getSort() {
    
        return sort;
    }

    public void setSort(Integer sort) {
    
        this.sort = sort;
    }

    public String getDel() {
    
        return del;
    }

    public void setDel(String del) {
    
        this.del = del;
    }

}

5.2 Persistence layer

Dao Interface :

package com.newcapec.dao;

import com.newcapec.entity.SysPermission;
import com.newcapec.utils.BaseDao;

public interface SysPermissionDao extends BaseDao<SysPermission> {
    
}

Mapper file :

<?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.newcapec.dao.SysPermissionDao">

    <insert id="insert" parameterType="com.newcapec.entity.SysPermission" useGeneratedKeys="true" keyProperty="id">
        insert into t_sys_permission(name, type, url, percode, parent_id, sort)
        values(#{name}, #{type}, #{url}, #{percode}, #{parentId}, #{sort})
    </insert>

    <update id="update" parameterType="com.newcapec.entity.SysPermission">
        update t_sys_permission
        <set>
            <if test="name != null">
                name = #{name},
            </if>
            <if test="type != null">
                type = #{type},
            </if>
            <if test="url != null">
                url = #{url},
            </if>
            <if test="percode != null">
                percode = #{percode},
            </if>
            <if test="parentId != null">
                parent_id = #{parentId},
            </if>
            <if test="sort != null">
                sort = #{sort},
            </if>
        </set>
        where id = #{id}
    </update>

    <delete id="delete" parameterType="java.lang.Integer">
        update t_sys_permission set del=1 where id = #{id}
    </delete>

    <delete id="deleteBatch" parameterType="java.lang.Integer">
        update t_sys_permission set del=1 where id in
        <foreach collection="array" open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </delete>

    <resultMap id="BaseResultMap" type="com.newcapec.entity.SysPermission">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="type" property="type"/>
        <result column="url" property="url"/>
        <result column="percode" property="percode"/>
        <result column="parent_id" property="parentId"/>
        <result column="sort" property="sort"/>
    </resultMap>

    <select id="select" parameterType="com.newcapec.entity.SysPermission" resultMap="BaseResultMap">
        select id, name, type, url, percode, parent_id, sort from t_sys_permission
        <where>
            <if test="name != null and name != ''">
                name like concat('%',#{name},'%')
            </if>
            <if test="type != null and type != ''">
                and type = #{type}
            </if>
            and del=0
        </where>
    </select>

    <select id="selectById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
        select id, name, type, url, percode, parent_id, sort from t_sys_permission
        where id = #{id} and del=0
    </select>
</mapper>

5.3 The business layer

Service Interface :

package com.newcapec.service;

import com.newcapec.entity.SysPermission;
import com.newcapec.utils.BaseService;

public interface SysPermissionService extends BaseService<SysPermission> {
    
}

Service Interface implementation class :

package com.newcapec.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.newcapec.constant.CommonConstant;
import com.newcapec.dao.SysPermissionDao;
import com.newcapec.entity.SysPermission;
import com.newcapec.service.SysPermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Service
public class SysPermissionServiceImpl implements SysPermissionService {
    

    @Autowired
    private SysPermissionDao sysPermissionDao;

    @Override
    public void add(SysPermission entity) {
    
        sysPermissionDao.insert(entity);
    }

    @Override
    public void edit(SysPermission entity) {
    
        sysPermissionDao.update(entity);
    }

    @Override
    public void remove(Integer id) {
    
        sysPermissionDao.delete(id);
    }

    @Override
    public void removeBatch(Integer[] ids) {
    
        sysPermissionDao.deleteBatch(ids);
    }

    @Override
    public List<SysPermission> find(SysPermission entity) {
    
        return sysPermissionDao.select(entity);
    }

    @Override
    public Map<String, Object> findPage(Integer pageNum, Integer pageSize, SysPermission entity) {
    
        // Paging service 
        PageHelper.startPage(pageNum, pageSize);
        List<SysPermission> list = sysPermissionDao.select(entity);
        PageInfo<SysPermission> pageInfo = new PageInfo<>(list);
        //1. Current page data ( Data list )2. Total records of this query 
        Map<String, Object> pageMap = new HashMap<>();
        pageMap.put(CommonConstant.PAGE_LIST, list);
        pageMap.put(CommonConstant.PAGE_TOTAL, pageInfo.getTotal());
        return pageMap;
    }

    @Override
    public SysPermission findById(Integer id) {
    
        return sysPermissionDao.selectById(id);
    }

}

5.4 Control layer

package com.newcapec.controller;

import com.newcapec.constant.CommonConstant;
import com.newcapec.entity.SysPermission;
import com.newcapec.service.SysPermissionService;
import com.newcapec.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping("/permission")
public class SysPermissionController {
    

    @Autowired
    private SysPermissionService sysPermissionService;

    /** *  newly added  */
    @PostMapping("/add")
    public Result add(@RequestBody SysPermission sysPermission) {
    
        sysPermissionService.add(sysPermission);
        return Result.success();
    }

    /** *  edit  */
    @PutMapping("/edit")
    public Result edit(@RequestBody SysPermission sysPermission) {
    
        sysPermissionService.edit(sysPermission);
        return Result.success();
    }

    /** *  Delete  */
    @DeleteMapping("/remove/{id}")
    public Result remove(@PathVariable Integer id) {
    
        sysPermissionService.remove(id);
        return Result.success();
    }

    /** *  Batch deletion  */
    @DeleteMapping("/remove")
    public Result removeBatch(Integer[] ids) {
    
        sysPermissionService.removeBatch(ids);
        return Result.success();
    }

    /** *  Single query  */
    @GetMapping("/find/{id}")
    public Result findById(@PathVariable Integer id) {
    
        return Result.success(sysPermissionService.findById(id));
    }

    /** *  Paging query  */
    @GetMapping("/findPage")
    public Result findPage(@RequestParam(value = CommonConstant.PAGE_NUM, required = false, defaultValue = CommonConstant.PAGE_NUM_DEFAULT) Integer pageNum,
                           @RequestParam(value = CommonConstant.PAGE_SIZE, required = false, defaultValue = CommonConstant.PAGE_SIZE_DEFAULT) Integer pageSize,
                           SysPermission sysPermission) {
    
        return Result.success(sysPermissionService.findPage(pageNum, pageSize, sysPermission));
    }

    /** *  Inquire about  */
    @GetMapping("/find")
    public Result find(SysPermission sysPermission) {
    
        return Result.success(sysPermissionService.find(sysPermission));
    }

}

5.5 Foreground page

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
    <link rel="stylesheet" href="static/layui/css/layui.css">
    <style>
        /*layui Data table check box correction */
        .layui-table-view .layui-form-checkbox i {
            margin-top: 5px;
        }
    </style>
</head>
<body>
<div style="padding: 10px">
    <blockquote class="layui-elem-quote">
        <form class="layui-form">
            <div class="layui-inline">
                <input type="text" id="name" name="name" placeholder=" Permission to name " class="layui-input">
            </div>
            <div class="layui-inline">
                <select id="type" name="type">
                    <option value=""> Authority type </option>
                    <option value="1"> Catalog </option>
                    <option value="2"> menu </option>
                    <option value="3"> Button </option>
                </select>
            </div>
            <div class="layui-inline">
                <a class="layui-btn searchBtn"> Search for </a>
                <a class="layui-btn layui-btn-normal addBtn"> add to </a>
                <a class="layui-btn layui-btn-danger removeBtn"> Batch deletion </a>
            </div>
        </form>
    </blockquote>
    <table id="tab" lay-filter="tab"></table>

    <!-- Operations in the table -->
    <script type="text/html" id="permissionBar">
        <a class="layui-btn layui-btn-xs layui-btn-warm" lay-event="edit"> edit </a>
        <a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="remove"> Delete </a>
    </script>

    <!-- Forms -->
    <div id="dataWindow" style="display: none;padding: 10px;">
        <form id="dataForm" class="layui-form" lay-filter="dataForm">
            <input type="text" name="id" style="display: none;">
            <div class="layui-form-item">
                <label class="layui-form-label"> Permission to name </label>
                <div class="layui-input-block">
                    <input type="text" name="name" lay-verify="required" placeholder=" Please enter the permission name " class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label"> Authority type </label>
                <div class="layui-input-block">
                    <select name="type" lay-verify="required">
                        <option value=""> Please select </option>
                        <option value="1"> Catalog </option>
                        <option value="2"> menu </option>
                        <option value="3"> Button </option>
                    </select>
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label"> Access address </label>
                <div class="layui-input-block">
                    <input type="text" name="url" placeholder=" Please enter the access address " class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label"> Authority code </label>
                <div class="layui-input-block">
                    <input type="text" name="percode" placeholder=" Please enter the permission code " class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label"> Parent node </label>
                <div class="layui-input-block">
                    <input type="text" name="parentId" placeholder=" Please enter the parent node " class="layui-input"/>
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label"> According to the order </label>
                <div class="layui-input-block">
                    <input type="text" name="sort" placeholder=" Please enter the display order " class="layui-input">
                </div>
            </div>
            <button class="submitBtn" lay-submit lay-filter="submitBtn" style="display: none;"> Submit... Immediately </button>
        </form>
    </div>
</div>
<script type="text/javascript" src="static/layui/layui.js"></script>
<script type="text/javascript">
    layui.use(['table', 'form', 'layer'], function () {
        var form = layui.form,
            layer = layui.layer,
            table = layui.table,
            dropdown = layui.dropdown,
            tree = layui.tree,
            $ = layui.$;

        // Asynchronous table initialization 
        table.render({
            id: 'permissionTable',
            elem: '#tab',
            // Asynchronous requests 
            method: 'get',
            url: 'permission/findPage',
            // Pagination 
            page: true,
            limit: 10,
            limits: [10, 20, 30, 50],
            // Set the header 
            cols: [[
                {type: 'checkbox', width: 50, fixed: 'left'},
                {field: 'id', title: 'ID', minWidth: 50, fixed: 'left', align: 'center'},
                {field: 'name', title: ' Permission to name ', minWidth: 100, fixed: 'left', align: 'center'},
                {
                    field: 'type', title: ' Authority type ', align: 'center', templet: function (d) {
                        var result = ''
                        switch (d.type) {
                            case '1':
                                result = ' Catalog ';
                                break;
                            case '2':
                                result = ' menu ';
                                break;
                            case '3':
                                result = ' Button ';
                                break;
                        }
                        return result;
                    }
                },
                {field: 'url', title: ' Access address ', align: 'center'},
                {field: 'percode', title: ' Authority code ', align: 'center'},
                {field: 'parentId', title: ' Parent node ', align: 'center'},
                {field: 'sort', title: ' According to the order ', align: 'center'},
                {title: ' operation ', minWidth: 150, fixed: 'right', align: 'center', templet: '#permissionBar'}
            ]],
            //res  It is the data of the background response 
            parseData: function (res) {
                return {
                    // Parse interface state 
                    'code': res.code,
                    // Parse prompt text 
                    'msg': res.message,
                    // Parse data length 
                    'count': res.data.total,
                    // Parse data list 
                    'data': res.data.list
                };
            },
            request: {
                // Parameter name of page number , Default :page
                pageName: 'pageNum',
                // Parameter name of data volume per page , Default :limit
                limitName: 'pageSize'
            },
            response: {
                // Specify the successful status code , Default :0
                statusCode: 200
            }
        });

        // Conditions of the query 
        $('.searchBtn').click(function () {
            tableReload();
        });

        // Line tool Events 
        // notes :tool  Is the toolbar event name ,test  yes  table  Properties of the original container  lay-filter=" Corresponding value "
        table.on('tool(tab)', function (obj) {
            // Get current row data 
            var data = obj.data;
            // get  lay-event  Corresponding value ( It can also be in the header  event  The corresponding value of the parameter )
            var layEvent = obj.event;

            if (layEvent == 'edit') {
                // The echo data 
                form.val("dataForm", data);

                // Click the edit button 
                addOrEdit(data.id);
            } else if (layEvent == 'remove') {
                // Click the delete button 
                remove(data.id);
            }
        });

        // Single delete function 
        function remove(id) {
            layer.confirm(' Are you sure you want to delete ?', function () {
                // Delete by asynchronous request 
                $.ajax('permission/remove/' + id, {
                    type: 'delete',
                    success: function (res) {
                        if (res.code == 200) {
                            layer.msg(res.message);
                            // Table overload 
                            tableReload();
                        }
                    }
                });
            });
        }

        // Batch delete function 
        function removeBatch() {
            // Get the selected data status of the table 
            var checkStatus = table.checkStatus('permissionTable');
            // Get selected data 
            var checkData = checkStatus.data;
            if (checkData.length == 0) {
                layer.msg(' Please select the data to delete ');
            } else {
                layer.confirm(' Are you sure you want to delete ?', function () {
                    var array = [];
                    checkData.forEach(function (item) {
                        array.push(item.id);
                    });
                    $.ajax('permission/remove?ids=' + array.join(), {
                        type: 'delete',
                        success: function (res) {
                            if (res.code == 200) {
                                layer.msg(res.message);
                                // Table overload 
                                tableReload();
                            }
                        }
                    });
                });
            }
        }

        $('.removeBtn').click(function () {
            removeBatch();
        })

        // newly added 
        var window_index = -1;

        function addOrEdit(id) {
            layer.open({
                type: 1,
                title: id ? ' Permission edit ' : ' New permission ',
                content: $('#dataWindow'),
                btn: [' determine ', ' Cancel '],
                // Click the OK button to the event 
                yes: function (index) {
                    window_index = index
                    $('.submitBtn').click();
                },
                // Click the pop-up layer to hide the event 
                end: function () {
                    window_index = -1;
                    // Empty the form 
                    $('#dataForm')[0].reset();
                }
            });
        }

        $('.addBtn').click(function () {
            addOrEdit();
        });

        // Form submission time 
        form.on('submit(submitBtn)', function (data) {
            // All form fields of the current container , Name value pair form :{name: value}
            var url = 'permission/add';
            var method = 'post';
            if (data.field.id) {
                //id Parameter data indicates that the current operation is edit , Otherwise, it is new 
                url = 'permission/edit';
                method = 'put';
            }
            $.ajax(url, {
                type: method,
                contentType: 'application/json',
                data: JSON.stringify(data.field),
                success: function (res) {
                    if (res.code = 200) {
                        layer.close(window_index);
                        layer.msg(res.message);
                        tableReload();
                    }
                }
            });
            // Prevent form jump . If you need a form jump , Just remove this paragraph .
            return false;
        });

        // Table overload 
        function tableReload() {
            table.reload('permissionTable', {
                where: {
                    name: $('#name').val(),
                    type: $('#type').val()
                }
            });
        }

    });
</script>
</body>
</html>

SSM Integrate _ Rights management

One 、 Authority management system analysis

1.1 summary

	 Rights management , Generally, it refers to the security rules or security policies set by the system , Users can access and only access their authorized resources , No less . Authority management appears in almost any system , As long as there's a system with users and passwords .  Many people often “ User authentication ”、“ Password encryption ”、“ System management ” And other concepts are confused with the concept of permission management .
	
	 User authentication , It doesn't belong to authority management at all . User authentication , Is to solve such a problem : The user tells the system “ Who am I ”, The system asks the user how to prove that you are “ who ” Well ? For using user name 、 Password verification system , Then show me your password . When the user name and password match , Then it proves who the current user is ; For systems like fingerprints , Show me your fingerprints ; For hardware Key Wait for the card system , You need to swipe your card .
	
	 Password encryption , It belongs to the field of user identity authentication , It does not belong to the scope of authority management .
	
	 System management , It is generally a module of the system . Moreover, the module generally also contains authority management sub module . therefore , Many people mistakenly think that the authority management system is just a small sub module of the system . Authority management module in system management , Just an operation interface , Let enterprises IT Administrators can set security policies such as roles . There are many permission verification logic behind the system , None of these belong to this module . On the whole , This module is equivalent to providing some data to the authority management module .
	
	 At present, it is mainly through users 、 role 、 Resources are used to allocate permissions . say concretely , Is to give users a role , Roles can access and operate resources in different ranges . By establishing a role system , Separate users and resources , To ensure the implementation of permission allocation .

	 Generally, it refers to the security rules or security policies set by the system , Users can access and only access their authorized resources .

1.2 Examples of scenes

	 Enterprises IT Administrators can generally define roles for the system , Assign roles to users . This is the most common role-based access control . Examples of scenes :
	
	1、 Give Zhang San “ HR Manager ” role ,“ HR Manager ” have “ Query employees ”、“ Add employees ”、“ Modify employees ” and “ Delete employee ” jurisdiction . At this time, Zhang San can enter the system , You can do these operations .
	
	2、 Remove Li Si's “ HR Manager ” role , At this time, Li Si cannot enter the system for these operations .
	
	 For example , Limited to function access . There are some more abundant 、 More detailed permission management . such as :
	
	1、 Because Zhang San is from Beijing Branch “ HR Manager ”, So he can and can only manage the employees of Beijing Branch and the subsidiaries of Beijing Branch ( Haidian subsidiary 、 Chaoyang subsidiary 、 Xicheng subsidiary 、 Dongcheng subsidiary, etc ) The employees' .
	
    2、 Because Wang Wu is a subsidiary of Haidian “ HR Manager ”, So he can and can only manage the employees of Haidian subsidiary .
    
    3、 The authority of the general examiner to review financial data is : The maximum audit limit in the retail industry is ¥50 ten thousand , The maximum limit in the steel industry is ¥1000 ten thousand ; The senior examiner is not subject to this limit .
    
    4、ATM Withdrawal the amount of each withdrawal cannot exceed ¥5000 element , The total withdrawal amount per day cannot exceed ¥20000 element .
    
     These rights management and data ( It can be collectively referred to as resources ) Direct correlation , Also known as data level permission management 、 Fine grained permission management or content permission management .

1.3 classification

From the point of view of control , Permission management can be divided into two categories :

  1. Function level authority management ;
  2. Data level privilege management .

In terms of control direction , You can also divide permission management into two categories :

  1. Get data from the system , For example, to inquire about an order 、 Search for customer information ;
  2. Submit data to the system , For example, to delete an order 、 Modify customer profile .

 Insert picture description here

Two 、 Authority management cases

2.1 Permission involves 5 A watch

	 User table , Role table , Permissions on the table , User role relationship table , Role permission association table .

	 When the user logs in , Verify whether the information in the user table is legal according to the user name and password , If it is legal, get user information , Then according to the user's id Go to the user role relationship table to get the associated roles id aggregate , Then according to the role id Then go to the role permission relationship table to obtain the permissions owned by the role id aggregate , Then basic permissions id Set to the permission table to get the specific menu , Show it to the current login user , Thus, no user can see the unused menu permission .

 Insert picture description here

Table function introduction

  • User table : Record the basic information of users .
-- ----------------------------
--  User table 
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_user`;
CREATE TABLE `t_sys_user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ' Primary key ',
  `username` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ' Login account ',
  `mobile` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' Phone number ',
  `nickname` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ' The user nickname ',
  `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' User mailbox ',
  `userpwd` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' password ',
  `salt` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'newedu' COMMENT ' Encrypting salt ',
  `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT ' state :1 You can use 2 Unavailable ',
  `del` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT ' Whether or not to delete :0 normal 1 Delete ',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ' User information sheet ' ROW_FORMAT = Dynamic;

-- ----------------------------
--  User table data 
-- ----------------------------
INSERT INTO `t_sys_user` VALUES (1, 'admin', '13612345678', ' Administrators ', '[email protected]', '8f32e9f68d6886d095b230b93e7a2c86', 'newedu', '1', '0');
INSERT INTO `t_sys_user` VALUES (2, 'tom', '12345678901', ' Tom ', '[email protected]', '8f32e9f68d6886d095b230b93e7a2c86', 'newedu', '1', '0');
  • Role table : Record the basic information of the role .
-- ----------------------------
--  Role table 
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_role`;
CREATE TABLE `t_sys_role`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `role_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ' Character encoding ',
  `role_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ' Character name ',
  `description` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' describe ',
  `del` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT ' Whether or not to delete :0 normal 1 Delete ',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ' Role information sheet ' ROW_FORMAT = Dynamic;

-- ----------------------------
--  Role table data 
-- ----------------------------
INSERT INTO `t_sys_role` VALUES (1, 'admin', ' Administrators ', ' Administrators ', '0');
INSERT INTO `t_sys_role` VALUES (2, 'user', ' Ordinary users ', ' Ordinary users ', '0');
INSERT INTO `t_sys_role` VALUES (3, 'other', ' other ', ' other ', '0');
  • Permissions on the table : Record basic information about permissions .
-- ----------------------------
--  Permissions on the table 
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_permission`;
CREATE TABLE `t_sys_permission`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ' Permission to name ',
  `type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' Authority type :1 Catalog  2 menu  3 Button ',
  `url` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '#' COMMENT ' Access address ',
  `percode` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' Authority code ',
  `parent_id` int(11) NULL DEFAULT 0 COMMENT ' Parent node ID',
  `sort` int(11) NULL DEFAULT NULL COMMENT ' According to the order ',
  `del` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT ' Whether or not to delete :0 normal 1 Delete ',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ' Permission information table ' ROW_FORMAT = Dynamic;

-- ----------------------------
--  Permission table data 
-- ----------------------------
INSERT INTO `t_sys_permission` VALUES (1, ' System management ', '1', '', 'system', 0, 1, '0');
INSERT INTO `t_sys_permission` VALUES (2, ' User list ', '2', '', 'user', 1, 11, '0');
INSERT INTO `t_sys_permission` VALUES (3, ' User query ', '3', '', 'user:query', 2, 111, '0');
INSERT INTO `t_sys_permission` VALUES (4, ' New users ', '3', '', 'user:add', 2, 112, '0');
INSERT INTO `t_sys_permission` VALUES (5, ' User edit ', '3', '', 'user:edit', 2, 113, '0');
INSERT INTO `t_sys_permission` VALUES (6, ' User deletion ', '3', '', 'user:remove', 2, 114, '0');
INSERT INTO `t_sys_permission` VALUES (7, ' Character list ', '2', '', 'role', 1, 12, '0');
INSERT INTO `t_sys_permission` VALUES (8, ' Role search ', '3', '', 'role:query', 7, 121, '0');
INSERT INTO `t_sys_permission` VALUES (9, ' Role addition ', '3', '', 'role:add', 7, 122, '0');
INSERT INTO `t_sys_permission` VALUES (10, ' Role editor ', '3', '', 'role:edit', 7, 123, '0');
INSERT INTO `t_sys_permission` VALUES (11, ' Character delete ', '3', '', 'role:remove', 7, 124, '0');
INSERT INTO `t_sys_permission` VALUES (12, ' Permission list ', '2', '', 'permission', 1, 13, '0');
INSERT INTO `t_sys_permission` VALUES (13, ' Permission query ', '3', '', 'permission:query', 12, 131, '0');
INSERT INTO `t_sys_permission` VALUES (14, ' New permission ', '3', '', 'permission:add', 12, 132, '0');
INSERT INTO `t_sys_permission` VALUES (15, ' Permission edit ', '3', '', 'permission:edit', 12, 133, '0');
INSERT INTO `t_sys_permission` VALUES (16, ' Permission deletion ', '3', '', 'permission:remove', 12, 134, '0');
  • User role middle table : Record the roles owned by users .
    • A user can have multiple roles , One-to-many relation .
    • A role can be included in multiple users , One-to-many relation .
    • If two tables have a two-way one to many relationship , So they have a many to many relationship , And there must be a relationship description table as an intermediate table .
-- ----------------------------
--  User role middle table 
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_user_role`;
CREATE TABLE `t_sys_user_role`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ' Primary key ',
  `user_id` int(11) NOT NULL COMMENT ' user ID',
  `role_id` int(11) NOT NULL COMMENT ' role ID',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ' User and role association table ' ROW_FORMAT = Dynamic;

-- ----------------------------
--  User role middle table data 
-- ----------------------------
INSERT INTO `t_sys_user_role` VALUES (1, 1, 1);
INSERT INTO `t_sys_user_role` VALUES (2, 1, 2);
INSERT INTO `t_sys_user_role` VALUES (3, 2, 2);
  • Role authority middle table : Record the permissions of the role .
    • A role can have multiple permissions , One-to-many relation .
    • A permission can be contained in multiple roles , One-to-many relation .
-- ----------------------------
--  Role authority middle table 
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_role_permission`;
CREATE TABLE `t_sys_role_permission`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ' Primary key ',
  `role_id` int(11) NOT NULL COMMENT ' role ID',
  `permission_id` int(11) NOT NULL COMMENT ' jurisdiction ID',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ' Role and permission association table ' ROW_FORMAT = Dynamic;

-- ----------------------------
--  Role permission intermediate table data 
-- ----------------------------
INSERT INTO `t_sys_role_permission` VALUES (1, 1, 1);
INSERT INTO `t_sys_role_permission` VALUES (2, 1, 2);
INSERT INTO `t_sys_role_permission` VALUES (3, 1, 3);
INSERT INTO `t_sys_role_permission` VALUES (4, 1, 4);
INSERT INTO `t_sys_role_permission` VALUES (5, 1, 5);
INSERT INTO `t_sys_role_permission` VALUES (6, 1, 6);
INSERT INTO `t_sys_role_permission` VALUES (7, 1, 7);
INSERT INTO `t_sys_role_permission` VALUES (8, 1, 8);
INSERT INTO `t_sys_role_permission` VALUES (9, 1, 9);
INSERT INTO `t_sys_role_permission` VALUES (10, 1, 10);
INSERT INTO `t_sys_role_permission` VALUES (11, 1, 11);
INSERT INTO `t_sys_role_permission` VALUES (12, 1, 12);
INSERT INTO `t_sys_role_permission` VALUES (13, 1, 13);
INSERT INTO `t_sys_role_permission` VALUES (14, 2, 1);
INSERT INTO `t_sys_role_permission` VALUES (15, 2, 2);
INSERT INTO `t_sys_role_permission` VALUES (16, 2, 6);
INSERT INTO `t_sys_role_permission` VALUES (17, 2, 10);

2.2 Display of parent node name in permission data

	 Display the modified name of the parent node of the permission table , The name of the parent authority that can display the current authority data .
	
	 Realize the idea :
		1、 In the permission entity , Add an associated attribute , Attribute types SysPermission, And provide getter and setter Method .
			 notes : Show only the name of the parent permission , Definition String The type is OK .
			
		2、 modify SysPermissionMapper.xml Query for SQL, And pass resultMap mapping .
		
		3、 modify role.jsp Display contents of page data table .

SysPermission.java:

package com.newcapec.entity;

public class SysPermission {
    

    // Other slightly 
    
    /* *  Association attribute  */
    private SysPermission parent;
    
    public SysPermission getParent() {
    
        return parent;
    }

    public void setParent(SysPermission parent) {
    
        this.parent = parent;
    }
}

SysPermissionMapper.xml:

<resultMap id="selectResultMap" type="com.newcapec.entity.SysPermission" extends="BaseResultMap">
    <association property="parent" javaType="com.newcapec.entity.SysPermission">
        <id property="id" column="parent_id"/>
        <result property="name" column="parent_name"/>
    </association>
</resultMap>
<select id="select" parameterType="com.newcapec.entity.SysPermission" resultMap="selectResultMap">
    select a.id, a.name, a.type, a.url, a.percode, a.parent_id, a.sort, b.name parent_name from t_sys_permission a
    left join t_sys_permission b on a.parent_id = b.id
    <where>
        <if test="name != null and name != ''">
            a.name like concat('%',#{name},'%')
        </if>
        <if test="type != null and type != ''">
            and a.type = #{type}
        </if>
        and a.del=0
    </where>
</select>

permission.jsp:

{
    field: 'parent', title: ' Parent node ', align: 'center', templet:function (d){
    
    return d.parent.name ? d.parent.name : ' nothing '
}},

2.3 When adding and editing permission data, query the parent node in association

	 In addition , Edit page add or modify parent node .
	
	 Realize the idea :
		1、 modify permission.jsp page , Add and edit the control type of the parent node in the form , Change from input box to drop-down box .
		
		2、 When adding and modifying , Load all existing nodes , These nodes are the parent nodes by default , Dynamically loaded into the drop-down box .
		
		3、 Modify the operating , After dynamically loading all parent nodes , Then render the form .

permission.jsp:

<div class="layui-form-item">
    <label class="layui-form-label"> Parent node </label>
    <div class="layui-input-block">
        <select id="parentId" name="parentId"></select>
    </div>
</div>

<script type="text/javascript">
    layui.use(['table', 'form', 'layer'], function () {
        // Other slightly 
        // Line tool Events 
        // notes :tool  Is the toolbar event name ,test  yes  table  Properties of the original container  lay-filter=" Corresponding value "
        table.on('tool(tab)', function (obj) {
            // Get current row data 
            var data = obj.data;
            // get  lay-event  Corresponding value ( It can also be in the header  event  The corresponding value of the parameter )
            var layEvent = obj.event;

            if (layEvent == 'edit') {
                // When you click the Modify button , No more immediate data echo . But after loading dynamic data , Display the data 
                //form.val("dataForm", data);

                // Click the edit button 
                addOrEdit(data.id);
            } else if (layEvent == 'remove') {
                // Click the delete button 
                remove(data.id);
            }
        });

        // Add or modify 
        var window_index = -1;

        function addOrEdit(id) {
            layer.open({
                type: 1,
                title: id ? ' Permission edit ' : ' New permission ',
                content: $('#dataWindow'),
                btn: [' determine ', ' Cancel '],
                // Click the OK button to the event 
                yes: function (index) {
                    window_index = index
                    $('.submitBtn').click();
                },
                // Click the pop-up layer to display the subsequent events 
                success: function(){
                    // After the new and edit forms are opened , Load the dynamic form data in the form 
                    loadParent(function(){
                        if(id){
                            $.ajax('permission/find/'+id, {
                                type: 'get',
                                success: function(res){
                                    if(res.code == 200){
                                        form.val('dataForm', res.data);
                                    }
                                }
                            });
                        }
                    });
                },
                // Click the pop-up layer to hide the event 
                end: function () {
                    window_index = -1;
                    // Empty the form 
                    $('#dataForm')[0].reset();
                }
            });
        }

        // Load parent node data ,follow Is the callback function 
        function loadParent(follow){
            $.ajax('permission/find', {
                type: 'get',
                success: function(res){
                    var str = '<option value="0"> Please select </option>';
                    res.data.forEach(function(item){
                        str += '<option value="' + item.id + '">' + (item.parent.name?item.parent.name:' nothing ') + ':' + item.name + '</option>'
                    });
                    $('#parentId').html(str);
                    // to update dataForm In the form select Component rendering 
                    form.render('select', 'dataForm');
                    // How to ensure the execution order of multiple asynchronous requests :  Only after the first asynchronous execution is completed can the second asynchronous execution be executed 
                    /**
                     * 1. Synchronization request 
                     * $.ajax(url1, {
                     *     async: false
                     * })
                     * $.ajax(url2, {
                     *     async: false
                     * })
                     *  Subsequent code 
                     *
                     * 2. Asynchronous request nesting :  Call the second asynchronous request in the callback function of the first asynchronous request 
                     * $.ajax(url1, {
                     *     success: function(){
                     *         $.ajax(url2)
                     *     }
                     * })
                     *
                     * 3.Promise
                     */
                    follow();
                }
            });
        }

    });
</script>

2.4 Associate roles when users add and edit

2.4.1 Background implementation

	 When users add and edit , Roles related to the associated operation user . A user can assign multiple roles .
	
	 Realize the idea :
		1、 stay SysUser Add associated attributes to entity classes , The attribute type is List<Integer> roleIdList, Record the list of role numbers related to the current user , And provide the corresponding getter and setter Method .
		
		2、 stay SysUserDao Add two methods to the interface .
			void insertUserRole(SysUser entity)	 Add user related role information 
			void deleteUserRole(Integer id)	 Delete relevant roles according to users 
		
		3、 stay SysUserMapper.xml The corresponding sql.
		
		4、 modify SysUserServiceImpl in , modify add()、edit() The implementation of the , Add related businesses of associated roles .
			 After adding users , Judge whether the list of relevant role numbers of the current user is empty , If it's not empty , Indicates that you need to add relevant role information .	
			 After modifying the user , Judge whether the role of the current user is empty , If it's not empty , Delete the relevant role number ; Then judge whether the user related roles are empty sets , If there is a role number in the set , Indicates that you need to add role information .( Simply speaking : Modification of user roles , Delete all first , Add new )
		
	 summary :
		 Business when users add :
			1. Determine if the user name is duplicate 
			2. New users 
			3. Judge whether the user has relevant role number information , If there is new relationship data 
		
		 User editing business :
			1. Edit user 
			2. Judge whether the user related role is empty , If not for null, Delete the relevant role number 
			3. Then judge whether the user related roles are empty and empty sets , If there is a role number in the set , Add relationship data 

SysUser.java:

/** *  System user entity class :  Basic functions for user table CURD Implementation of operations  */
public class SysUser {
    
    // Other slightly 
	/* *  Association attribute : Record the list of role numbers related to the current user  */
    private List<Integer> roleIdList;

    public List<Integer> getRoleIdList() {
    
        return roleIdList;
    }

    public void setRoleIdList(List<Integer> roleIdList) {
    
        this.roleIdList = roleIdList;
    }
}

SysUserDao Interface :

public interface SysUserDao extends BaseDao<SysUser> {
    

    /* *  Query according to user name  * 1、 register : Duplicate user name check  * 2、 The user login ( Refinement prompt use , First judge the user name , Then judge the password ) */
    SysUser selectByUsername(String username);

    /* *  Add user related role information  */
    void insertUserRole(SysUser sysUser);

    /* *  Delete relevant roles according to user number  */
    void deleteUserRole(Integer id);
}

SysUserMapper.xml:

<insert id="insertUserRole" parameterType="com.newcapec.entity.SysUser">
    insert into t_sys_user_role(user_id, role_id)
    <foreach collection="roleIdList" open=" values" separator="," item="item">
        (#{id}, #{item})
    </foreach>
</insert>

<delete id="deleteUserRole" parameterType="java.lang.Integer">
    delete from t_sys_user_role where user_id = #{id}
</delete>

SysUserServiceImpl.java:

/** *  Business when users add : * 1. Determine if the user name is duplicate  * 2. New users  * 3. Judge whether the user has relevant role number information , If there is new relationship data  */
@Override
public void add(SysUser entity) {
    
    SysUser sysUser = findByUsername(entity.getUsername());
    // Background verification , Guarantee safety , Prevent third-party tools from registering (PostMan)
    if (sysUser == null) {
    
        entity.setUserpwd(CommonConstant.PASSWORD_DEFAULT);
        sysUserDao.insert(entity);
        // Judge whether the list of relevant roles of the current user is empty , If it's not empty , Relevant role information needs to be added 
        //CollectionUtils yes Spring Provided , A method used to determine whether a set is empty or empty 
        if(!CollectionUtils.isEmpty(entity.getRoleIdList())){
    
            sysUserDao.insertUserRole(entity);
        }
    }
}

/** *  User editing business  * 1. Edit user  * 2. Judge whether the user related role is empty , If not for null, Delete the relevant role number  * 3. Then judge whether the user related roles are empty and empty sets , If there is a role number in the set , Add relationship data  */
@Override
public void edit(SysUser entity) {
    
    SysUser sysUser = findByUsername(entity.getUsername());
    if (sysUser != null) {
    
        sysUserDao.update(entity);
        // Judge whether the role of the current user is empty , If it's not empty , Delete the relevant role number ;
        if(entity.getRoleIdList() != null){
    
            sysUserDao.deleteUserRole(entity.getId());
            // Then judge whether the user related roles are empty sets , If there is a role number in the set , Indicates that you need to add role information .
            if(!CollectionUtils.isEmpty(entity.getRoleIdList())){
    
                sysUserDao.insertUserRole(entity);
            }
        }
    }
}

2.4.2 The front-end implementation

	 In the front page , When adding and modifying users , Show role checkbox .
	
	 Realize the idea :
		1、 stay user.jsp Add and modify the pop-up box content of the page , Add a role related check box , But role data is dynamic , Then check boxes need to be loaded dynamically .
		
		2、 stay user.jsp Query all role data in , Dynamically render character data .
		
		3、 If it's a modification operation , After dynamically rendering the character data , Then do data echo .
		
		4、 When the form submits data asynchronously , Will convert the data into json String to submit , Then the data submitted by the check box will only retain the last value , But what the server needs is an array , Then we need to deal with it manually , Before submitting data , Manually obtain the user's relevant role number and convert it into an array for submission .
		
		5、 If it's a modification operation , Other data is echoed normally , But the user's role data cannot be echoed , Because we are based on id When querying users , There is no associated query role data , Modified according to id Query the user's sql that will do .
		
		6、Layui When the form is echoed , Cannot assign an array to a form control , We need to assign values manually .
	
	 notes :layui Dynamic forms in , Must render refresh .

user.jsp:

<form id="dataForm" class="layui-form" lay-filter="dataForm">
    <div class="layui-form-item">
        <label class="layui-form-label"> role </label>
        <div class="layui-input-block roleIdList">
            <!-- Dynamically load role checkbox -->
        </div>
    </div>
</form>

<script type="text/javascript">
    // Load module 
    layui.use(['table', 'form', 'layer'], function () {
        // Other slightly 
        // Toolbar events 
        // notes :tool  Is the toolbar event name ,test  yes  table  Properties of the original container  lay-filter=" Corresponding value "
        table.on('tool(dataTable)', function (obj) {
            var data = obj.data; // Get current row data 
            var layEvent = obj.event; // get  lay-event  Corresponding value ( It can also be in the header  event  The corresponding value of the parameter )

            if (layEvent === 'remove') { // Delete 
                remove(data.id);
            } else if (layEvent === 'edit') { // edit 
                // No more data echo here , Because you need to load the dynamic character data before echo 

                $("#dataFormUsername").prop('readonly', 'readonly');
                $("#dataFormUsername").attr('lay-verify', '');

                addOrEdit(data.id);
            }
        });

        var window_index = -1; // Default form index value 
        function addOrEdit(id) {
            // Page layer 
            layer.open({
                type: 1,
                title: id ? ' Modify the user ' : ' New users ',
                content: $('#dataWindow'),
                area: ['500px', '500px'], // Wide and high 
                btn: [' determine ', ' Cancel '],
                yes: function (index) {
                    // If you set yes Callback , Manual closing is required 
                    //layer.close(index);
                    window_index = index;

                    // Click the OK button , Submit form data 
                    $("#submitBtn").click();
                },
                // Click the pop-up layer to display the subsequent events 
                success: function(){
                    // After the pop-up layer is displayed , Load all the role list data 
                    loadRole(function(){
                        // If it's a modification operation , Then query the user's data and echo the data 
                        if(id){
                            $.ajax('user/find/'+id, {
                                type: 'get',
                                success: function(res){
                                    if(res.code == 200){
                                        //formTest  namely  class="layui-form"  Attribute of the element  lay-filter=""  Corresponding value 
                                        form.val('dataForm', res.data);
                                        // Manually assign values to user related role information 
                                        $.each($(':checkbox[name="roleIdList"]'), function(){
                                            this.checked = false;
                                            var list = res.data.roleIdList;
                                            if(list && list.length > 0){
                                                for(var i in list){
                                                    if(list[i] == this.value){
                                                        this.checked = true;
                                                    }
                                                }
                                            }
                                        });
                                        // When the user is about to perform editing :
                                        //1. The user name is read-only 
                                        $('#dataFormUsername').prop('readonly', 'readonly');
                                        //2. User name cannot be uniquely verified 
                                        $('#dataFormUsername').attr('lay-verify', '');
                                        form.render('checkbox', 'dataForm');
                                    }
                                }
                            })
                        }
                    });
                },
                end: function () {
                    window_index = -1; // Reset form index defaults 
                    // Reset form 
                    $('#dataForm')[0].reset();

                    $("#dataFormUsername").prop('readonly', '');
                    $("#dataFormUsername").attr('lay-verify', 'required|usernameVerify');
                }
            });
        }

        // Add a form submission event 
        form.on('submit(submitBtn)', function (data) {
            // All form fields of the current container , Name value pair form :{name: value}
            console.log(data.field)
            // Judge the form id Whether the field has a value , If it's worth it , Perform modification operations , Otherwise, execute new .
            var url = 'user/add', method = 'post';
            if (data.field.id) {
                url = 'user/edit';
                method = 'put';
            }
            //console.log(data);
            // Get user related role number information manually 
            var array = [];
            $.each($(':checkbox[name="roleIdList"]:checked'), function(){
                array.push(this.value);
            });
            data.field.roleIdList = array;
            $.ajax(url, {
                type: method,
                contentType: 'application/json',
                data: JSON.stringify(data.field),
                success: function (res) {
                    if (res.code == 200) {
                        // Close page layer 
                        layer.close(window_index);
                        layer.msg(res.message);
                        tableReload();
                    }
                }
            })
            return false; // Prevent form jump . If you need a form jump , Just remove this paragraph .
        });

        // Load all role data 
        function loadRole(follow){
            $.ajax('role/find', {
                type: 'get',
                success: function(res){
                    var str = '';
                    res.data.forEach(function(item){
                        str += '<input type="checkbox" name="roleIdList" title="' + item.roleName + '" lay-skin="primary" value="' + item.id + '">';
                    });
                    $('.roleIdList').html(str);
                    form.render('checkbox', 'dataForm');
                    follow();
                }
            });
        }
    });
</script>

SysUserMapper.xml:

<resultMap id="BaseResultMap" type="com.newcapec.entity.SysUser">
    <id column="id" property="id"/>
    <result column="username" property="username"/>
    <result column="mobile" property="mobile"/>
    <result column="nickname" property="nickname"/>
    <result column="email" property="email"/>
    <result column="userpwd" property="userpwd"/>
    <result column="salt" property="salt"/>
    <result column="status" property="status"/>
</resultMap>

<resultMap id="SelectByIdResultMap" type="com.newcapec.entity.SysUser" extends="BaseResultMap">
    <collection property="roleIdList" ofType="java.lang.Integer">
        <constructor>
            <arg column="role_id"/>
        </constructor>
    </collection>
</resultMap>
<select id="selectById" parameterType="java.lang.Integer" resultMap="SelectByIdResultMap">
    select a.id, a.username, a.mobile, a.nickname, a.email, a.userpwd, a.salt, a.status, b.role_id from t_sys_user a
    left join t_sys_user_role b on a.id = b.user_id
    where a.id = #{id} and a.del=0
</select>

2.5 Associate permissions when adding and editing roles

2.5.1 Background implementation

	 When adding and editing roles , Associated operation role related permissions . A role can be assigned multiple permissions . Overall implementation ideas and 2.4 similar .
	
	 Realize the idea :
		1、 stay SysRole Add associated attributes to entity classes , The attribute type is List<Integer> permissionIdList, Record the list of permission numbers related to the current role , And provide the corresponding getter and setter Method .
		
		2、 stay SysRoleDao Add two methods to the interface .
			void insertRolePermission(SysRole entity)	 Add role related permission information 
			void deleteRolePermission(Integer id)	 Delete relevant permission information according to the role 
		
		3、 stay SysRoleMapper.xml The corresponding sql.
		
		4、 Modified according to id Query the role sql, Query the role information and the list of permission numbers related to the role .
		
		5、 modify SysRoleServiceImpl in , modify add()、edit() The implementation of the , Add related businesses of associated permissions .
			 After adding roles , Judge whether the list of relevant permission numbers of the current role is empty , If it's not empty , Indicates that you need to add relevant permission information .	
			 After modifying the role , Judge whether the permission list of the current role is empty , If it's not empty , Delete the relevant authority number ; Then judge whether the role related permissions are empty sets , If there is a permission number in the set , Indicates that you need to add permission information .( Simply speaking : Modification of role permissions , Delete all first , Add new )

SysRole.java:

public class SysRole {
    

    // Other slightly 
    /* *  Association attribute : Record the list of relevant permission numbers of the current role  */
    private List<Integer> permissionIdList;

    public List<Integer> getPermissionIdList() {
    
        return permissionIdList;
    }

    public void setPermissionIdList(List<Integer> permissionIdList) {
    
        this.permissionIdList = permissionIdList;
    }
}

SysRoleDao Interface :

public interface SysRoleDao extends BaseDao<SysRole> {
    

    /* *  Add role related permission information  */
    void insertRolePermission(SysRole sysRole);

    /* *  Delete relevant permission information according to the root role  */
    void deleteRolePermission(Integer id);
}

SysRoleMapper.xml:

<resultMap id="selectByIdResultMap" type="com.newcapec.entity.SysRole" extends="BaseResultMap">
    <collection property="permissionIdList" ofType="java.lang.Integer">
        <constructor>
            <arg column="permission_id"/>
        </constructor>
    </collection>
</resultMap>
<select id="selectById" parameterType="java.lang.Integer" resultMap="selectByIdResultMap">
    select a.id, a.role_code, a.role_name, a.description, b.permission_id from t_sys_role a
    left join t_sys_role_permission b on a.id = b.role_id
    where a.id = #{id} and a.del=0
</select>


<insert id="insertRolePermission" parameterType="com.newcapec.entity.SysRole">
    insert into t_sys_role_permission(role_id, permission_id)
    <foreach collection="permissionIdList" open=" values" separator="," item="item">
        (#{id}, #{item})
    </foreach>
</insert>

<delete id="deleteRolePermission" parameterType="java.lang.Integer">
    delete from t_sys_role_permission where role_id = #{id}
</delete>

SysRoleServiceImpl.java:

@Override
public void add(SysRole entity) {
    
    sysRoleDao.insert(entity);
    if(!CollectionUtils.isEmpty(entity.getPermissionIdList())){
    
        sysRoleDao.insertRolePermission(entity);
    }
}

@Override
public void edit(SysRole entity) {
    
    sysRoleDao.update(entity);
    if(entity.getPermissionIdList() != null){
    
        sysRoleDao.deleteRolePermission(entity.getId());
        if(!CollectionUtils.isEmpty(entity.getPermissionIdList())){
    
            sysRoleDao.insertRolePermission(entity);
        }
    }
}

2.5.2 The front-end implementation

	 In the front page , When adding and modifying roles , Show the permission tree structure .
		 Be careful : Roles are in the whole system , Just a few , Using the check box is not a problem . But there will be many permissions , If you use the check box , It's not reasonable to .
	
	 Realize the idea :
		1、 stay role.jsp Add and modify the pop-up box content of the page , Add a permission , But the permission data is dynamic .
		
		2、 stay role.jsp Query all permission list data in , Show in a tree structure ( Need to load layui Of tree modular ).
		
		3、 If it's a modification operation , After dynamically rendering the permission tree structure data , Then do data echo .
		
		4、 The data obtained from the background query does not conform to layui tree Data structure of , Then we need to process the data .
			4.1  Convert the background response data into layui in tree The data structure required by the component ,layui tree Components need to id、title、spread、children etc. , But the background response data does not contain these data .
			4.2  Convert data in list structure into data in tree structure .
		
		5、 Render the parsed tree structure data to the specified elements .
		
		6、 When you submit the form , You need to manually add the role related permission number data ( Because the tree structure is not a form control ).
		
		7、 Modify the operating , The data echo of the form will not echo the tree structure , Just call the tree node setChecked that will do .
			 Be careful : because layui The reason for the tree component of , As long as the parent node is selected , Then all child nodes will be checked by default , Then we need data filtering , Only check the button permission .

role.jsp:

<div class="layui-form-item">
    <label class="layui-form-label"> jurisdiction </label>
    <div class="layui-input-block">
        <div id="permissionTree"></div>
    </div>
</div>

<script type="text/javascript" src="static/js/tool.js"></script>
<script type="text/javascript">
    layui.use(['table', 'form', 'layer', 'tree'], function () {
        var form = layui.form,
            layer = layui.layer,
            table = layui.table,
            tree = layui.tree,
            $ = layui.$;

        // Line tool Events 
        // notes :tool  Is the toolbar event name ,test  yes  table  Properties of the original container  lay-filter=" Corresponding value "
        table.on('tool(tab)', function(obj) {
            // Get current row data 
            var data = obj.data;
            // get  lay-event  Corresponding value ( It can also be in the header  event  The corresponding value of the parameter )
            var layEvent = obj.event;

            if(layEvent == 'edit'){
                // Click the edit button 
                addOrEdit(data.id);
            }else if(layEvent == 'remove'){
                // Click the delete button 
                remove(data.id);
            }
        });

        // Add or modify 
        var window_index = -1;
        function addOrEdit(id){
            layer.open({
                type: 1,
                title: id ? ' Role editor ' : ' Role addition ',
                content: $('#dataWindow'),
                btn: [' determine ', ' Cancel '],
                // Click the OK button to the event 
                yes: function(index){
                    window_index = index
                    $('.submitBtn').click();
                },
                // Click the pop-up layer to display the subsequent events 
                success: function(){
                    loadPermission(function(permissions){
                        if(id){
                            $.ajax('role/find/'+id, {
                                type: 'get',
                                success: function(res){
                                    if(res.code == 200){
                                        //formTest  namely  class="layui-form"  Attribute of the element  lay-filter=""  Corresponding value 
                                        form.val('dataForm', res.data);
                                        var array = [];
                                        // Filter the list of permission numbers owned by the current role , Keep only type=3 Permission number of 
                                        res.data.permissionIdList.forEach(function(item){
                                            for(var i in permissions){
                                                if(permissions[i].id == item && permissions[i].type == 3){
                                                    array.push(item);
                                                    break;
                                                }
                                            }
                                        });
                                        tree.setChecked('permissionTree', array);
                                    }
                                }
                            })
                        }
                    });
                },
                // Click the pop-up layer to hide the event 
                end: function(){
                    window_index = -1;
                    // Empty the form 
                    $('#dataForm')[0].reset();
                }
            });
        }

        // Form submit event 
        form.on('submit(submitBtn)', function(data){
            // All form fields of the current container , Name value pair form :{name: value}
            var url = 'role/add';
            var method = 'post';
            if(data.field.id){
                //id Parameter data indicates that the current operation is edit , Otherwise, it is new 
                url = 'role/edit';
                method = 'put';
            }
            // Manually add role related permission number data 
            var array = [];
            var checkData = treeToData(tree.getChecked('permissionTree'));
            checkData.forEach(function(item){
                array.push(item.id);
            });
            data.field.permissionIdList = array;
            $.ajax(url, {
                type: method,
                contentType: 'application/json',
                data: JSON.stringify(data.field),
                success: function(res){
                    if(res.code = 200){
                        layer.close(window_index);
                        layer.msg(res.message);
                        tableReload();
                    }
                }
            });
            // Prevent form jump . If you need a form jump , Just remove this paragraph .
            return false;
        });


        // Load role list data 
        function loadPermission(follow){
            $.ajax('permission/find', {
                type: 'get',
                success: function(res){
                    //1. Convert data to layui in tree Data required by the component 
                    res.data.forEach(function(item){
                        item.title = item.name;
                        item.spread = true;
                    });
                    //2. Convert list data into tree structure data 
                    var treeData = dataToTree(res.data);
                    //3. Tree component initialization 
                    // Tree component data loading 
                    tree.render({
                        id: 'permissionTree',
                        elem: '#permissionTree',
                        showCheckbox: true,
                        showLine: false,
                        data: treeData
                    });
                    follow(res.data);
                }
            });
        }
    });
</script>

2.6 The user login

2.6.1 Background implementation

	1、SysUserDao Has been defined in SysUser selectByUsername(String username) Method , Then we can start from service Start writing .
	
	2、 stay SysUserService Interface UserInfo login(String username,String userpwd);
		 Be careful :UserInfo Entity classes are used to store user login information ,SysUser It is the basic function for user table CURD Operation of the .
		
	3、 stay SysUserServiceImpl Implement the specific login business in the implementation class .
		1. According to the user name ( User ID ), Query relevant records in the database 
		2. Judge whether the queried user is null
		3. If null, Indicates that the user name provided by the current user is incorrect 
		4. If not for null, According to the password provided by the user ( User credentials ) Compare the passwords stored in the database 
		5. If not, the password provided by the user is incorrect 
		6. If it's consistent, return UserInfo object 
	
	4、 Definition LoginController, Login related requests are defined in the controller .

UserInfo Entity class :

package com.newcapec.entity;

import java.util.List;

/** *  User login information object  */
public class UserInfo {
    

    private Integer id;
    private String username;
    private String mobile;
    private String nickname;
    private String email;
    private String userpwd;
    private String salt;
    private String status;

    public Integer getId() {
    
        return id;
    }

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

    public String getUsername() {
    
        return username;
    }

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

    public String getMobile() {
    
        return mobile;
    }

    public void setMobile(String mobile) {
    
        this.mobile = mobile;
    }

    public String getNickname() {
    
        return nickname;
    }

    public void setNickname(String nickname) {
    
        this.nickname = nickname;
    }

    public String getEmail() {
    
        return email;
    }

    public void setEmail(String email) {
    
        this.email = email;
    }

    public String getUserpwd() {
    
        return userpwd;
    }

    public void setUserpwd(String userpwd) {
    
        this.userpwd = userpwd;
    }

    public String getSalt() {
    
        return salt;
    }

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

    public String getStatus() {
    
        return status;
    }

    public void setStatus(String status) {
    
        this.status = status;
    }
}

SysUserService Interface :

public interface SysUserService extends BaseService<SysUser> {
    

    SysUser findByUsername(String username);

    UserInfo login(String username, String userpwd);
}

SysUserServiceImpl Implementation class :

/** *  Sign in  * 1. According to the user name ( User ID ), Query relevant records in the database  * 2. Judge whether the queried user is null * 3. If null, Indicates that the user name provided by the current user is incorrect  * 4. If not for null, According to the password provided by the user ( User credentials ) Compare the passwords stored in the database  * 5. If not, the password provided by the user is incorrect  * 6. If it's consistent, return UserInfo object  */
@Override
public UserInfo login(String username, String userpwd) {
    
    SysUser sysUser = sysUserDao.selectByUsername(username);
    if(sysUser != null){
    
        if(userpwd.equals(sysUser.getUserpwd())){
    
            UserInfo userInfo = new UserInfo();
            //spring A tool class is provided in BeanUtils, Provide attribute value copy function 
            //copyProperties( Source object ,  Target audience )
            // requirement : Property names are consistent 
            BeanUtils.copyProperties(sysUser, userInfo);
            return userInfo;
        }
    }
    return null;
}

LoginController.java:

package com.newcapec.controller;

import com.newcapec.constant.SystemCode;
import com.newcapec.entity.UserInfo;
import com.newcapec.service.SysUserService;
import com.newcapec.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;

@RestController
@RequestMapping("/auth")
public class LoginController {
    

    @Autowired
    private SysUserService sysUserService;

    /** *  Login interface  *  call Service Medium login Method  *  If the return value is null, Indicates that the user name or password is incorrect  *  If the return value is not null * 1. Put user information UserInfo Objects stored in HttpSession in  * 2. Return the result of successful login ( User information can be sent to the front end ) * *  Be careful : *  Login is usually for password security , use post request  */
    @PostMapping("/login")
    public Result login(@RequestBody UserInfo userInfo, HttpSession session) {
    
        UserInfo dbUserInfo = sysUserService.login(userInfo.getUsername(), userInfo.getUserpwd());
        if (dbUserInfo != null) {
    
            session.setAttribute("userInfo", dbUserInfo);
            return Result.success(dbUserInfo);
        }
        return Result.error(SystemCode.USERNAME_ERROR.getCode(), SystemCode.USERNAME_ERROR.getMessage(), null);
    }

    /** *  Login interface  */
    @GetMapping("/logout")
    public Result logout(HttpSession session) {
    
        session.removeAttribute("userInfo");
        session.invalidate();
        return Result.success();
    }

}

2.6.2 The front-end implementation

	 Realize the idea :
		1、 stay views Create under directory login.jsp page , And introduce layui relevant css and js file .
		
		2、 The homepage of the normal background management system , It should be the login page , So modify web.xml Configuration in .
		
		3、 adopt HTML/CSS Write static page effects .
		
		4、 Send asynchronous login request .
			1. If the username and password are correct , Jump to home page .
			2. If the user name or password is incorrect , Then the pop-up box will prompt .
			
		5、 After login , Jump page , Dynamically display the nickname of the login user .
		
		6、 stay index.jsp Page exit system link binding event , When the event triggers , Ask whether you want to exit the system ?  If you click OK , Then send an asynchronous request to log out , Exit and jump to the login page .
		
		 notes : If the front page is not jsp、 Template engine and other dynamic pages , But static pages , Then we can use sessionStoreage To achieve .

login.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title> Background management system </title>
    <link rel="stylesheet" href="static/layui/css/layui.css">
    <style type="text/css">
        body {
            margin: 0;
            padding: 0;
            height: 100vh;
            /* flex Fluid layout  */
            display: flex;
            /*flex-flow: column nowrap;*/
            justify-content: center;
            align-items: center;
            background-image: url(static/images/login_bg.jpg);
        }

        .login-page {
            width: 450px;
            background-color: #ffffff;
            border-radius: 10px;
            padding: 30px 20px;
        }

        .login-header {
            text-align: center;
            font-size: 20px;
            font-weight: bold;
        }
    </style>
</head>
<body>
<div class="login-page">
    <form class="layui-form">
        <div class="layui-form-item">
            <div class="login-header"> please &emsp;&emsp; deng &emsp;&emsp; record </div>
        </div>
        <div class="layui-form-item">
            <input type="text" name="username" lay-verify="required" placeholder=" user name " class="layui-input">
        </div>
        <div class="layui-form-item">
            <input type="password" name="userpwd" lay-verify="required" placeholder=" password " class="layui-input">
        </div>
        <div class="layui-form-item">
            <button class="layui-btn layui-btn-fluid" lay-submit lay-filter="submitBtn"> Sign in </button>
        </div>
    </form>
</div>

<script type="text/javascript" src="static/layui/layui.js"></script>
<script>
    layui.use(['form', 'layer'], function () {
        var form = layui.form,
            layer = layui.layer,
            $ = layui.$;

        // Submit login 
        form.on('submit(submitBtn)', function (data) {
            $.ajax('auth/login', {
                type: 'post',
                contentType: 'application/json',
                data: JSON.stringify(data.field),
                success: function (res) {
                    if (res.code == 200) {
                        // If the front page adopts pure static page , Store the user information returned from the background response in the front-end cache 
                        // sessionStorage.setItem(key, value);  save 
                        // sessionStorage.getItem(key);  take 
                        // sessionStorage.removeItem(key);  Delete 
                        sessionStorage.setItem('userInfo', JSON.stringify(res.data));
                        // Page Jump 
                        location.href = 'page/index';
                    } else {
                        layer.msg(res.message);
                    }
                }
            });
            return false;
        });
    });
</script>
</body>
</html>

index.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title> Background management system </title>
    <!-- introduce Layui The style file -->
    <link rel="stylesheet" href="static/layui/css/layui.css">
</head>
<body>
<!-- introduce layui Classic layout and revision -->
<div class="layui-layout layui-layout-admin">
    <!-- Page header -->
    <div class="layui-header">
        <div class="layui-logo layui-hide-xs layui-bg-black"> Background management system </div>
        <ul class="layui-nav layui-layout-right">
            <li class="layui-nav-item layui-hide layui-show-md-inline-block">
                <a href="javascript:;">
                    <img src="//tva1.sinaimg.cn/crop.0.0.118.118.180/5db11ff4gw1e77d3nqrv8j203b03cweg.jpg"
                         class="layui-nav-img">
                    <!-- Get the nickname of the login user on the dynamic page -->
                    <%--${sessionScope.userInfo==null?' nothing ':sessionScope.userInfo.nickname}--%>
                    <!-- Get the nickname of the login user on the static page -->
                    <span class="user-info"></span>
                </a>
                <dl class="layui-nav-child">
                    <dd><a href=""> Personal information </a></dd>
                    <dd><a href=""> System settings </a></dd>
                    <dd><a href="javascript:void(0);" class="logoutBtn"> Exit the system </a></dd>
                </dl>
            </li>
        </ul>
    </div>

    <div class="layui-side layui-bg-black">
        <div class="layui-side-scroll">
            <!--  Left navigation area ( Compatible layui Existing vertical navigation ) -->
            <ul class="layui-nav layui-nav-tree" lay-filter="test">
                <li class="layui-nav-item layui-nav-itemed">
                    <a class="" href="javascript:;"> System management </a>
                    <dl class="layui-nav-child">
                        <dd><a href="page/sys/user" target="mainFrame"> User list </a></dd>
                        <dd><a href="page/sys/role" target="mainFrame"> Character list </a></dd>
                        <dd><a href="page/sys/permission" target="mainFrame"> Permission list </a></dd>
                    </dl>
                </li>
                <li class="layui-nav-item">
                    <a href="javascript:;"> The business management </a>
                    <dl class="layui-nav-child">
                        <dd><a href="student/find" target="mainFrame"> Student list </a></dd>
                        <dd><a href="javascript:;"> List of employees </a></dd>
                        <dd><a href="javascript:;"> Department list </a></dd>
                    </dl>
                </li>
            </ul>
        </div>
    </div>

    <div class="layui-body">
        <!--  Content subject area  -->
        <iframe name="mainFrame" frameborder="0" style="width:100%;height: 100%" src="page/welcome"></iframe>
    </div>

    <div class="layui-footer">
        <!--  Bottom fixed area  -->
         Bottom fixed area 
    </div>
</div>

<!-- introduce layui.js file -->
<script type="text/javascript" src="static/layui/layui.js"></script>
<script>
    layui.use(['layer', 'element'], function () {
        var element = layui.element,
            layer = layui.layer,
            $ = layui.$;

        // Get the data in the front-end cache 
        var userInfo = JSON.parse(sessionStorage.getItem('userInfo'));
        if(userInfo && userInfo.nickname){
            $('.user-info').html(userInfo.nickname);
        }else {
            $('.user-info').html(' Not logged in ');
        }
        
        $('.logoutBtn').click(function () {
            layer.confirm(' Are you sure you want to exit the system ?', function () {
                $.ajax('auth/logout', {
                    type: 'get',
                    success: function (res) {
                        if (res.code == 200) {
                            // Clear cache 
                            sessionStorage.removeItem('userInfo');
                            location.href = 'page/login';
                        }
                    }
                })
            });
        });
    });
</script>
</body>
</html>

2.6.3 Authentication interceptor

	 Realize the idea :
		1、 Definition SpringMVC Interceptor LoginInterceptor( Realization HandlerInterceptor Interface ), In the interceptor preHandle Method for user identity authentication . The package where the interceptor is located :interceptor.
			
		2、 from session Get user login information in the domain .
			1. If not for null, The release .
			2. If null, The intercept . There are two ways :
				 Mode one : Page Jump . Redirect to the login page through the response object . However, this method has certain limitations , If it is a development mode with front and rear ends separated , It should be the jump of the front-end control page , Instead of deciding the jump of the page in the background .
				 Mode two : Respond to json data , Prompt not logged in .
		
        3、 Configure interceptors , Set interception request and release request .
        
        4、 On the front page , Get the return data of the asynchronous request , If not 200, Then give the corresponding prompt .
        
        5、 On the front page , Determine whether to log in , If for login , Go to the login page .
        	 Mode one : from session Get user login information in the domain , If you are not logged in , Then go to the login page .
        	 Mode two : Get user login information from the front-end cache , If there is no cached data , Then go to the login page .

LoginInterceptor.java:

package com.newcapec.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.newcapec.constant.SystemCode;
import com.newcapec.utils.Result;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

/** *  User authentication ( The user login ) Interceptor  */
public class LoginInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
    
        // obtain HttpSession object 
        HttpSession session = httpServletRequest.getSession();
        // from session Get user login information in the domain 
        Object userInfo = session.getAttribute("userInfo");
        // Judge whether the user login information exists 
        if (userInfo == null) {
    
            // Page Jump 
            //httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/page/login");

            // Set response content type 
            httpServletResponse.setContentType("application/json;charset=utf-8");
            // Respond to users json data , Prompt not logged in 
            Result result = Result.error(SystemCode.NOT_LOGIN.getCode(), SystemCode.NOT_LOGIN.getMessage(), null);
            // Manually convert the custom response format object to json character string : jackson
            ObjectMapper objectMapper = new ObjectMapper();
            String resultStr = objectMapper.writeValueAsString(result);
            httpServletResponse.getWriter().write(resultStr);
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    
    }
}

springmvc.xml:

<!-- Configure interceptors -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <!-- Dynamic page Jump request and static resource mapping request -->
        <mvc:exclude-mapping path="/page/**"/>
        <mvc:exclude-mapping path="/static/**"/>
        <mvc:exclude-mapping path="/auth/login"/>
        <bean class="com.newcapec.interceptor.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

index.jsp:

<script>
    layui.use(['layer', 'element'], function () {
        var element = layui.element,
            layer = layui.layer,
            $ = layui.$;

        // Judge whether the user logs in on the current page 
        /*var obj = '${sessionScope.userInfo}';
        if(!obj){
           location.href = 'page/login';
        }*/

        // Get the data in the front-end cache 
        var userInfo = JSON.parse(sessionStorage.getItem('userInfo'));
        if(!userInfo){
            location.href = 'page/login';
        }else if(userInfo && userInfo.nickname){
            $('.user-info').html(userInfo.nickname);
        }

        $('.logoutBtn').click(function () {
            layer.confirm(' Are you sure you want to exit the system ?', function () {
                $.ajax('auth/logout', {
                    type: 'get',
                    success: function (res) {
                        if (res.code == 200) {
                            // Clear cache 
                            sessionStorage.removeItem('userInfo');
                            location.href = 'page/login';
                        }else if(res.code == 404){
                            layer.msg(res.message);
                        }
                    }
                })
            });
        });
    });
</script>

sys Related pages :

// Judge whether the user logs in on the current page 
var userInfo = sessionStorage.getItem('userInfo');
if(!userInfo){
    
    location.href = 'page/login';
}

2.6.4 Implementation of dynamic menu

	 Realize the idea :
		1、 The permission list data is consistent with the background menu data , Insert the business management directory in the permission 、 Student list / List of employees / Department list menu 、 There is a query button permission under each list .
		
		2、 Configure test data .
			 Configure role permission data :admin The role has all permissions 、user The role has all business management and user query permissions .
			 Configure user role data :admin Users have administrators 、 Ordinary user role 、 Tom has ordinary user roles .
			
		3、 Improve the pages corresponding to the employee menu and department menu , And configure the page Jump path .
			 stay views Create below emp/find.jsp、dept/find.jsp, The content of the page doesn't matter .
			 stay SystemController Configure page Jump path .
		
		4、 Configure the access path of permissions .
		
		5、 According to the user id Query the permissions you have , Then it involves the permission table 、 Role authority middle table 、 User role middle table three table associated query .
			1. stay SysPermissionDao In the definition of List<SysPermission> selectByUserId(@Param("userId") Integer userId, @Param("type") String type) Method , This method is based on the user ID Query the list of permissions owned by the current user .
				 If it's delivered type by 3, Filter button type permissions , Dynamic menu use .
				 If it's delivered type by null, Then query all permission types . Authorization authentication use .
				
			2. stay SysPermissionMapper.xml It defines the corresponding sql.
			3. stay SysPermissionService In the definition of List<SysPermission> findMenu(Integer userId) Method .
			4. stay SysPermissionServiceImpl To achieve specific business .
			5. stay SysPermissionController Define request mapping , from session Get the currently logged in user in the domain , Get the corresponding permission menu .
		
        6、 stay index.jsp The page sends asynchronous requests , Get the permission of the currently logged in user , Dynamically generate menus .

SystemController.java:

/** *  The processor used to realize page Jump  */
@Controller
@RequestMapping("/page")
public class SystemController {
    

    @GetMapping("/stu/add")
    public String stuAdd() {
    
        return "stu/add";
    }

    @GetMapping("/welcome")
    public String welcome() {
    
        return "welcome";
    }

    @GetMapping("/sys/user")
    public String sysUser() {
    
        return "sys/user";
    }

    @GetMapping("/sys/role")
    public String sysRole() {
    
        return "sys/role";
    }

    @GetMapping("/sys/permission")
    public String sysPermission() {
    
        return "sys/permission";
    }

    @GetMapping("/emp")
    public String emp() {
    
        return "emp/find";
    }

    @GetMapping("/dept")
    public String dept() {
    
        return "dept/find";
    }

    @GetMapping("/index")
    public String index() {
    
        return "index";
    }

    @GetMapping("/login")
    public String login() {
    
        return "login";
    }
}

index.jsp:

<li class="layui-nav-item">
    <a href="javascript:;"> The business management </a>
    <dl class="layui-nav-child">
        <dd><a href="student/find" target="mainFrame"> Student list </a></dd>
        <dd><a href="page/emp" target="mainFrame"> List of employees </a></dd>
        <dd><a href="page/dept" target="mainFrame"> Department list </a></dd>
    </dl>
</li>

Access path of permission :

 Insert picture description here

SysPermissionDao.java:

public interface SysPermissionDao extends BaseDao<SysPermission> {
    
    /** *  According to the user ID Query the list of permissions owned by the current user  *  Parameters userId, Users to query id *  Parameters type, The type of menu . *  If it's delivered type by 3, Filter button type permissions , Dynamic menu use  *  If it's delivered type by null, Then query all permission types . Authorization authentication use  */
    List<SysPermission> selectByUserId(@Param("userId") Integer userId, @Param("type") String type);
}

SysPermissionMapper.xml:

<select id="selectByUserId" parameterType="java.util.HashMap" resultMap="BaseResultMap">
    select distinct a.id, a.name, a.type, a.url, a.percode, a.parent_id, a.sort from t_sys_permission a
    join t_sys_role_permission b on a.id = b.permission_id
    join t_sys_user_role c on b.role_id = c.role_id
    <where>
        c.user_id = #{userId} and a.del = 0
        <if test="type != null">
            and a.type != 3
        </if>
    </where>
    order by a.sort
</select>	

SysPermissionService.java:

public interface SysPermissionService extends BaseService<SysPermission> {
    
    List<SysPermission> findMenu(Integer userId);
}

SysPermissionServiceImpl.java:

@Override
public List<SysPermission> findMenu(Integer userId) {
    
    return sysPermissionDao.selectByUserId(userId, "3");
}

SysPermissionController.java:

/** *  Query the menu of the currently logged in user  */
@GetMapping("/findMenu")
public Result findMenu(HttpSession session){
    
    // from session Get the current login user in the domain 
    UserInfo userInfo = (UserInfo) session.getAttribute("userInfo");
    List<SysPermission> menus = sysPermissionService.findMenu(userInfo.getId());
    return Result.success(menus);
}

index.jsp:

<!--  Left navigation area ( Compatible layui Existing vertical navigation ) -->
<ul class="layui-nav layui-nav-tree treeMenu" lay-filter="test">
    <!--  Dynamic rendering of menu data  -->
</ul>

<script type="text/javascript" src="static/js/tool.js"></script>
<script>
    // Initialize the menu list of the current user 
    $.ajax('permission/findMenu', {
        type: 'get',
        success: function(res){
            if(res.code == 200){
                var menus = dataToTree(res.data);
                console.log('===> Menu data :', menus);
                var str = '';
                menus.forEach(function(item){
                    str += '<li class="layui-nav-item layui-nav-itemed">';
                    str += '<a class="" href="javascript:;">' + item.name + '</a>';
                    if(item.children && item.children.length > 0){
                        str += '<dl class="layui-nav-child">';
                        item.children.forEach(function(item2){
                            str += '<dd><a href="' +  item2.url + '" target="mainFrame">' + item2.name + '</a></dd>';
                        });
                        str += '</dl>';
                    }
                    str += '</li>';
                });
                $('.treeMenu').html(str);
                //element.render('nav', 'test');
            }else{
                layer.msg(res.message);
            }
        }
    });
</script>    

2.7 Authority identification

	 Implementation of dynamic menu , It only realizes the menu displayed after the user logs in , The menu with permission is displayed , Menus without permission are not displayed . But if after logging in , Know about other pages url, You can also operate other non permission menus .
	
	 such as tom user , There is no permission to operate roles and permissions , But you can enter the address in the address bar to access .
		http://localhost:8080/ssm/page/sys/permission
		http://localhost:8080/ssm/page/sys/role
		
	 Realize the idea :
		1. stay SysPermissionService In the definition of List<SysPermission> findByUserId(Integer userId) Method , It is used to query all the permission lists of users .
		2. stay SysPermissionServiceImpl To achieve specific business .
		3. stay SysUserServiceImpl Of login In the method , When the user logs in successfully , Query all permissions owned by the current user , And assign it to userInfo object .
		4. Definition PermissionInterceptor Authorization interceptor , Judge a request , Whether the current user has permission to access .
		5. Configure interceptors .
			 Be careful : Be sure to configure it after logging in the interceptor .

SysPermissionService.java:

public interface SysPermissionService extends BaseService<SysPermission> {
    
    List<SysPermission> findMenu(Integer userId);
    
    List<SysPermission> findByUserId(Integer userId);
}

SysPermissionServiceImpl.java:

@Override
public List<SysPermission> findByUserId(Integer userId) {
    
    return sysPermissionDao.selectByUserId(userId, null);
}

SysUserServiceImpl.java:

@Autowired
private SysPermissionService sysPermissionService;

@Override
public UserInfo login(String username, String userpwd) {
    
    SysUser sysUser = sysUserDao.selectByUsername(username);
    if(sysUser != null){
    
        if(userpwd.equals(sysUser.getUserpwd())){
    
            UserInfo userInfo = new UserInfo();
            //spring A tool class is provided in BeanUtils, Provide attribute value copy function 
            //copyProperties( Source object ,  Target audience )
            // requirement : Property names are consistent 
            BeanUtils.copyProperties(sysUser, userInfo);
            // Query all permissions owned by the current user 
            List<SysPermission> permissionList = sysPermissionService.findByUserId(userInfo.getId());
            userInfo.setPermissionList(permissionList);
            return userInfo;
        }
    }
    return null;
}

PermissionInterceptor.java:

package com.newcapec.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.newcapec.constant.SystemCode;
import com.newcapec.entity.SysPermission;
import com.newcapec.entity.UserInfo;
import com.newcapec.utils.Result;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

/** *  User authentication interceptor : Judge a request , Whether the current user has permission to access  *  Through the path url Intercept to authenticate permissions  */
public class PermissionInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
    
        HttpSession session = httpServletRequest.getSession();
        Object obj = session.getAttribute("userInfo");
        // Judge whether the user login information exists 
        if (obj instanceof UserInfo) {
    
            UserInfo userInfo = (UserInfo) obj;
            // Get the permission list of the currently logged in user 
            List<SysPermission> permissionList = userInfo.getPermissionList();
            // Gets the current request path 
            String url = httpServletRequest.getServletPath();
            System.out.println(" The path of this request :" + url);
            // Query the data matching the current request path in the permission list of the currently logged in user 
            // If it is queried, it means that the user has permission to access 
            // If no query is found, the user does not have permission to access 
            for (SysPermission sysPermission : permissionList) {
    
                System.out.println(" Permission path :" + sysPermission.getUrl());
                if (url.contains(sysPermission.getUrl()) && !sysPermission.getUrl().equals("")) {
    
                    return true;
                }
            }

            httpServletResponse.setContentType("application/json;charset=utf-8");
            // Respond to users json data , Prompt not logged in 
            Result result = Result.error(SystemCode.NO_PERMISSION.getCode(), SystemCode.NO_PERMISSION.getMessage(), null);
            // Manually convert the custom response format object to json character string : jackson
            ObjectMapper objectMapper = new ObjectMapper();
            String resultStr = objectMapper.writeValueAsString(result);
            httpServletResponse.getWriter().write(resultStr);
        }
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    
    }
}

springmvc.xml:

<!-- Configure interceptors -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <!-- Dynamic page Jump request and static resource mapping request -->
        <mvc:exclude-mapping path="/page/**"/>
        <mvc:exclude-mapping path="/static/**"/>
        <mvc:exclude-mapping path="/auth/login"/>
        <bean class="com.newcapec.interceptor.LoginInterceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/page/login"/>
        <mvc:exclude-mapping path="/page/index"/>
        <mvc:exclude-mapping path="/page/welcome"/>
        <mvc:exclude-mapping path="/static/**"/>
        <mvc:exclude-mapping path="/auth/**"/>
        <mvc:exclude-mapping path="/permission/findMenu"/>
        <bean class="com.newcapec.interceptor.PermissionInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>
原网站

版权声明
本文为[I'm Bo Li Bo]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/188/202207070637092448.html