Spring mvc +Mybstis 整合 集成cache+shiro+通用mapper

Spring mvc+Mybatis的整合

  • pom文件的配置
  • applicationContext.xml配置
  • 通用mapper与分页插件配置
  • cache配置
  • spring-mvc.xml的配置
  • applicationContext-shiro.xml配置
  • properties文件
  • 集成
  • 测试

一.项目的集成,各种配置文件整理

  1. pom文件的配置  废话不多说 贴代码
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.mark.mession</groupId>
      <artifactId>xfMession</artifactId>
      <packaging>war</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>xfMession Maven Webapp</name>
      <url>http://maven.apache.org</url>
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--  MyBatis Generator  -->
        <!--  Java接口和实体类  -->
        <targetJavaProject>${basedir}/src/main/java</targetJavaProject>
        <targetMapperPackage>com.marks.framework.dao</targetMapperPackage>
        <targetModelPackage>com.marks.framework.entity</targetModelPackage>
        <!--  XML生成路径  -->
        <targetResourcesProject>${basedir}/src/main/resources</targetResourcesProject>
        <targetXMLPackage>mapper</targetXMLPackage>
        <!--  编译jdk版本  -->
        <jdk.version>1.8</jdk.version>
        <!--  依赖版本  -->
        <slf4j.version>1.6.6</slf4j.version>
        <log4j.version>1.2.12</log4j.version>
        <mybatis.version>3.3.1</mybatis.version>
        <mapper.version>3.3.6</mapper.version>
        <pagehelper.version>4.1.4</pagehelper.version>
        <mysql.version>5.1.29</mysql.version>
        <shiro.version>1.2.3</shiro.version>
        <aspectj.version>1.6.12</aspectj.version>
        <spring.version>4.1.2.RELEASE</spring.version>
        <mybatis.spring.version>1.2.4</mybatis.spring.version>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
        </dependency>
        <!-- log start -->
        <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>${log4j.version}</version>
        </dependency>
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>${slf4j.version}</version>
        </dependency>
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>${slf4j.version}</version>
          <exclusions>
            <exclusion>
              <artifactId>log4j</artifactId>
              <groupId>log4j</groupId>
            </exclusion>
          </exclusions>
        </dependency>
        <!-- log end -->
    
        <!--web-->
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
          <version>2.5</version>
          <scope>provided</scope>
        </dependency>
        <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>jsp-api</artifactId>
          <version>2.1</version>
          <scope>provided</scope>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
        </dependency>
        <dependency>
          <groupId>javax.ws.rs</groupId>
          <artifactId>javax.ws.rs-api</artifactId>
          <version>2.0</version>
        </dependency>
        <dependency>
          <groupId>javax.websocket</groupId>
          <artifactId>javax.websocket-api</artifactId>
          <version>1.0</version>
        </dependency>
        <dependency>
          <groupId>javax.annotation</groupId>
          <artifactId>javax.annotation-api</artifactId>
          <version>1.2</version>
        </dependency>
        <dependency>
          <groupId>javax.transaction</groupId>
          <artifactId>javax.transaction-api</artifactId>
          <version>1.2</version>
        </dependency>
    
        <!--Spring-->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>commons-logging</artifactId>
                    <groupId>commons-logging</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-orm</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-oxm</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-test</artifactId>
        </dependency>
    
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context-support</artifactId>
          <version>${spring.version}</version>
        </dependency>
    
    
    
        <!-- shiro -->
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-spring</artifactId>
          <version>${shiro.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-ehcache</artifactId>
          <version>${shiro.version}</version>
          <exclusions>
            <exclusion>
              <artifactId>ehcache-core</artifactId>
              <groupId>net.sf.ehcache</groupId>
            </exclusion>
          </exclusions>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-core</artifactId>
          <version>${shiro.version}</version>
          <exclusions>
            <exclusion>
              <artifactId>slf4j-api</artifactId>
              <groupId>org.slf4j</groupId>
            </exclusion>
          </exclusions>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-web</artifactId>
          <version>${shiro.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-quartz</artifactId>
          <version>${shiro.version}</version>
        </dependency>
    
        <!-- aspectjweaver -->
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>${aspectj.version}</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjrt</artifactId>
          <version>${aspectj.version}</version>
        </dependency>
    
    
        <!--spring-oxm依赖-->
        <dependency>
          <groupId>org.codehaus.castor</groupId>
          <artifactId>castor-xml</artifactId>
          <version>1.3.3</version>
        </dependency>
        <!--spring-json依赖-->
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>2.4.2</version>
        </dependency>
        <dependency>
          <groupId>com.fasterxml.jackson.dataformat</groupId>
          <artifactId>jackson-dataformat-xml</artifactId>
          <version>2.4.2</version>
        </dependency>
        <!--spring-aop依赖-->
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.8.8</version>
        </dependency>
    
        <!--上传文件-->
        <dependency>
          <groupId>commons-fileupload</groupId>
          <artifactId>commons-fileupload</artifactId>
          <version>1.3.1</version>
        </dependency>
    
        <!--mysql-->
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>${mysql.version}</version>
        </dependency>
        <!--druid-->
        <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.0.11</version>
        </dependency>
    
        <!--Mybatis-->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis</artifactId>
          <version>${mybatis.version}</version>
        </dependency>
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis-spring</artifactId>
          <version>${mybatis.spring.version}</version>
        </dependency>
        <!-- Mybatis Generator -->
        <dependency>
          <groupId>org.mybatis.generator</groupId>
          <artifactId>mybatis-generator-core</artifactId>
          <version>1.3.2</version>
          <scope>compile</scope>
          <optional>true</optional>
        </dependency>
        <!--分页插件-->
        <dependency>
          <groupId>com.github.pagehelper</groupId>
          <artifactId>pagehelper</artifactId>
          <version>${pagehelper.version}</version>
        </dependency>
        <!--通用Mapper-->
        <dependency>
          <groupId>tk.mybatis</groupId>
          <artifactId>mapper</artifactId>
          <version>${mapper.version}</version>
        </dependency>
    
        <dependency>
          <groupId>net.sf.ehcache</groupId>
          <artifactId>ehcache</artifactId>
          <version>2.10.1</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
    
    
        <dependency>
          <groupId>com.googlecode.ehcache-spring-annotations</groupId>
          <artifactId>ehcache-spring-annotations</artifactId>
          <version>1.2.0</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
    
    
      </dependencies>
      <dependencyManagement>
        <dependencies>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-framework-bom</artifactId>
            <version>${spring.version}</version>
            <type>pom</type>
            <scope>import</scope>
          </dependency>
        </dependencies>
      </dependencyManagement>
      <repositories>
        <repository>
          <id>nexus</id>
          <name>local private nexus</name>
          <url>http://maven.oschina.net/content/groups/public/</url>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </repository>
        <repository>
          <id>sonatype-nexus-releases</id>
          <name>Sonatype Nexus Releases</name>
          <url>http://oss.sonatype.org/content/repositories/releases</url>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </repository>
        <repository>
          <id>sonatype-nexus-snapshots</id>
          <name>Sonatype Nexus Snapshots</name>
          <url>http://oss.sonatype.org/content/repositories/snapshots</url>
          <releases>
            <enabled>false</enabled>
          </releases>
          <snapshots>
            <enabled>true</enabled>
          </snapshots>
        </repository>
      </repositories>
      <build>
        <resources>
          <resource>
            <directory>${basedir}/src/main/java</directory>
            <includes>
              <include>**/*.xml</include>
            </includes>
          </resource>
          <resource>
            <directory>${basedir}/src/main/resources</directory>
          </resource>
        </resources>
        <plugins>
          <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <source>${jdk.version}</source>
              <target>${jdk.version}</target>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.2</version>
            <configuration>
              <configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
              <overwrite>true</overwrite>
              <verbose>true</verbose>
            </configuration>
            <dependencies>
              <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
              </dependency>
              <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper</artifactId>
                <version>${mapper.version}</version>
              </dependency>
            </dependencies>
          </plugin>
        </plugins>
      </build>
    </project>

    2.applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
           xmlns:cache="http://www.springframework.org/schema/cache"
           xsi:schemaLocation="
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/cache
        http://www.springframework.org/schema/cache/spring-cache.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--spring的注解扫描 这里需要注意 有的时候报创建bean失败可能是这里扫描不到你所使用的注解标记的bean-->
        <context:component-scan base-package="com.marks.framework.*"/>
    
        <context:property-placeholder location="classpath:config/jdbc.properties"/>
    
    
        <!-- Cache配置 -->
        <cache:annotation-driven cache-manager="cacheManager"/>
        <bean id="ehCacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
              p:configLocation="classpath:ehcache.xml"/>
        <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
              p:cacheManager-ref="ehCacheManagerFactory"/>
    
        <!--配置alibaba druid  即DataSource-->
    
        <!--对于druid的介绍可以参考 http://blog.csdn.net/qq892618896/article/details/52021642  -->
    
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
            <!-- 基本属性 url、user、password -->
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
    
            <!-- 配置初始化大小、最小、最大 -->
            <property name="initialSize" value="${ds.initialSize}"/>
            <property name="minIdle" value="${ds.minIdle}"/>
            <property name="maxActive" value="${ds.maxActive}"/>
    
            <!-- 配置获取连接等待超时的时间 -->
            <property name="maxWait" value="${ds.maxWait}"/>
    
            <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
            <property name="timeBetweenEvictionRunsMillis" value="${ds.timeBetweenEvictionRunsMillis}"/>
    
            <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
            <property name="minEvictableIdleTimeMillis" value="${ds.minEvictableIdleTimeMillis}"/>
    
            <property name="validationQuery" value="SELECT 'x'"/>
            <property name="testWhileIdle" value="true"/>
            <property name="testOnBorrow" value="false"/>
            <property name="testOnReturn" value="false"/>
    
            <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
            <property name="poolPreparedStatements" value="false"/>
            <property name="maxPoolPreparedStatementPerConnectionSize" value="20"/>
    
            <!-- 配置监控统计拦截的filters -->
            <property name="filters" value="stat,log4j"/>
    
        </bean>
    
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="mapperLocations">
                <array>
                    <value>classpath:mapper/*.xml</value>
                </array>
            </property>
            <property name="typeAliasesPackage" value="com.marks.framework.entity"/>
            <!--分页插件的介绍请参考  https://github.com/pagehelper/Mybatis-PageHelper-->
            <property name="plugins">
                <array>
                    <bean class="com.github.pagehelper.PageHelper">
                        <!-- 这里的几个配置主要演示如何使用,如果不理解,一定要去掉下面的配置 -->
                        <property name="properties">
                            <value>
                                dialect=mysql
                                reasonable=true
                                supportMethodsArguments=true
                                params=count=countSql
                                autoRuntimeDialect=true
                            </value>
                        </property>
                    </bean>
                </array>
            </property>
        </bean>
        <!--详细参数请参考 http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/2.Integration.md  -->
        <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.marks.framework.dao"/>
            <!--默认mappers不配置会自动扫描mapper这个通用的-->
        </bean>
    
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        </bean>
    
        <!-- 对dataSource 数据源进行事务管理 -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
              p:dataSource-ref="dataSource"/>
    
        <!-- 事务管理 通知 -->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <!-- 对insert,update,delete 开头的方法进行事务管理,只要有异常就回滚 -->
                <tx:method name="insert*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
                <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
                <tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
                <!-- select,count开头的方法,开启只读,提高数据库访问性能 -->
                <tx:method name="select*" read-only="true"/>
                <tx:method name="count*" read-only="true"/>
                <!-- 对其他方法 使用默认的事务管理 -->
                <tx:method name="*"/>
            </tx:attributes>
        </tx:advice>
    
        <!-- 事务 aop 配置 -->
        <aop:config>
            <aop:pointcut id="serviceMethods" expression="execution(* com.marks.framework.service..*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
        </aop:config>
    
        <!-- 配置使Spring采用CGLIB代理 -->
        <aop:aspectj-autoproxy proxy-target-class="true"/>
    
        <!-- 启用对事务注解的支持 -->
        <tx:annotation-driven transaction-manager="transactionManager"/>
    
    </beans>

    3.spring-mvc.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.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">
        
        <context:component-scan base-package="com.marks.framework.controller"></context:component-scan>
    
        <!--RequestMappingHandlerAdapter-->
        <mvc:annotation-driven>
            <mvc:message-converters>
                <ref bean="stringHttpMessageConverter"/>
                <ref bean="marshallingHttpMessageConverter"/>
                <ref bean="mappingJackson2HttpMessageConverter"/>
            </mvc:message-converters>
        </mvc:annotation-driven>
    
        <bean id="stringHttpMessageConverter"
              class="org.springframework.http.converter.StringHttpMessageConverter"/>
    
        <bean id="marshallingHttpMessageConverter"
              class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
            <property name="marshaller" ref="castorMarshaller"/>
            <property name="unmarshaller" ref="castorMarshaller"/>
        </bean>
    
        <bean id="mappingJackson2HttpMessageConverter"
              class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>application/json;charset=UTF-8</value>
                    <value>application/xml;charset=UTF-8</value>
                    <value>text/html;charset=UTF-8</value>
                    <value>text/plain;charset=UTF-8</value>
                    <value>text/xml;charset=UTF-8</value>
                </list>
            </property>
        </bean>
    
        <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
    
        <!--信息转化结束-->
    
        <bean id="contentNegotiationManagerFactoryBean"
              class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
            <property name="defaultContentType" value="text/html"/>
            <property name="ignoreAcceptHeader" value="true"/>
            <property name="favorPathExtension" value="true"/>
            <property name="favorParameter" value="false"/>
            <property name="mediaTypes">
                <map>
                    <entry key="atom" value="application/atom+xml"/>
                    <entry key="html" value="text/html"/>
                    <entry key="json" value="application/json"/>
                </map>
            </property>
        </bean>
    
        <!--内容协商-->
        <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
            <property name="contentNegotiationManager">
                <bean class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
                    <property name="defaultContentType" value="text/html"/>
                    <property name="mediaTypes">
                        <map>
                            <entry key="json" value="application/json"/>
                            <entry key="xml" value="application/xml"/>
                            <entry key="html" value="text/html"/>
                        </map>
                    </property>
                </bean>
            </property>
            <property name="viewResolvers">
                <list>
                    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                        <property name="prefix" value="/WEB-INF/jsp/"/>
                        <property name="suffix" value=".jsp"/>
                    </bean>
                </list>
            </property>
            <property name="defaultViews">
                <list>
                    <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
                    <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
                        <property name="marshaller" ref="castorMarshaller"/>
                    </bean>
                </list>
            </property>
        </bean>
    
        <!-- 配置springMVC处理上传文件的信息 -->
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="defaultEncoding" value="utf-8"/>
            <property name="maxUploadSize" value="10485760000"/>
            <property name="maxInMemorySize" value="40960"/>
        </bean>
    
        <!-- 启用shrio授权注解拦截方式 -->
        <aop:config proxy-target-class="true"></aop:config>
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
            <property name="securityManager" ref="securityManager"/>
        </bean>
    
    </beans>

    4.applicationContext-shiro.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <description>apache shiro配置</description>
    
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager"/>
            <property name="loginUrl" value="/rest/page/login"/>
            <property name="successUrl" value="/rest/index"/>
            <property name="unauthorizedUrl" value="/rest/page/401"/>
            <property name="filterChainDefinitions">
                <value>
                    <!-- 静态资源允许访问 -->
                    /static/** = anon
                    /assets/** = anon
                    <!-- 登录页允许访问 -->
                    /rest/user/login = anon
                    /rest/test2 = anon
                    /rest/page/select = anon
                    <!-- 其他资源需要认证 -->
                    /** = authc
                </value>
            </property>
        </bean>
    
        <!-- 缓存管理器 使用Ehcache实现 -->
        <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
            <property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>
        </bean>
    
        <!-- 会话DAO -->
        <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO"/>
    
        <!-- 会话管理器 -->
        <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
            <property name="sessionDAO" ref="sessionDAO"/>
        </bean>
    
        <!-- 安全管理器 -->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realms">
                <list>
                    <ref bean="securityRealm"/>
                </list>
            </property>
             <!--cacheManager,集合spring缓存工厂 -->
             <!--<property name="cacheManager" ref="shiroEhcacheManager" />-->
             <!--<property name="sessionManager" ref="sessionManager" />-->
        </bean>
    
        <!-- Shiro生命周期处理器 -->
        <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    
    </beans>

    6.jdbc.properties

    ##JDBC Global Setting
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/tagmaps?useUnicode=true&characterEncoding=utf-8
    jdbc.username=root
    jdbc.password=root
    
    ##DataSource Global Setting
    
    #配置初始化大小、最小、最大
    ds.initialSize=1
    ds.minIdle=1
    ds.maxActive=20
    
    #配置获取连接等待超时的时间
    ds.maxWait=60000
    
    #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    ds.timeBetweenEvictionRunsMillis=60000
    
    #配置一个连接在池中最小生存的时间,单位是毫秒
    ds.minEvictableIdleTimeMillis=300000
    
    # generator.xm连接配置
    mapper.plugin = tk.mybatis.mapper.generator.MapperPlugin
    mapper.Mapper = tk.mybatis.mapper.common.Mapper

    7.log4j.properties

    # DEBUG,INFO,WARN,ERROR,FATAL
    LOG_LEVEL=info
    
    log4j.rootLogger=${LOG_LEVEL},CONSOLE,FILE,E
    
    log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
    log4j.appender.CONSOLE.Encoding=utf-8
    log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
    #log4j.appender.CONSOLE.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss} %C{8}@(%F:%L):%m%n 
    log4j.appender.CONSOLE.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss} %C{1}@(%F:%L):%m%n
    
    log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender
    log4j.appender.FILE.File=/Users/apple/Desktop/logs/mylogs.log
    log4j.appender.FILE.Encoding=utf-8
    log4j.appender.FILE.DatePattern='.'yyyy-MM-dd
    log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
    #log4j.appender.FILE.layout=org.apache.log4j.HTMLLayout
    log4j.appender.FILE.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH\:mm\:ss} %C{8}@(%F\:%L)\:%m%n
    
    log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.E.File =/Users/apple/Desktop/logs/error.log
    log4j.appender.E.Append = true
    log4j.appender.E.Threshold = ERROR
    log4j.appender.E.layout = org.apache.log4j.PatternLayout
    log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

    8.ehcache.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache updateCheck="false" name="txswx-ehcache">
        <diskStore path="java.io.tmpdir"/>
        <!-- DefaultCache setting. -->
        <defaultCache maxEntriesLocalHeap="10000" eternal="true" timeToIdleSeconds="300" timeToLiveSeconds="600"
                      overflowToDisk="true" maxEntriesLocalDisk="100000"/>
        <cache name="testCache" eternal="false" maxElementsInMemory="100"
               overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
               timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU" />
    </ehcache>

    9.ehcache-shiro.xml

    <ehcache updateCheck="false" name="shiroCache">
    
        <defaultCache
                maxElementsInMemory="10000"
                eternal="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                overflowToDisk="false"
                diskPersistent="false"
                diskExpiryThreadIntervalSeconds="120"
                />
    </ehcache>

    10.generator.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    
    <!DOCTYPE generatorConfiguration
            PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
            "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    
    <generatorConfiguration>
      <properties resource="config/jdbc.properties"/>
    
      <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>
        
        <plugin type="${mapper.plugin}">
          <property name="mappers" value="${mapper.Mapper}"/>
        </plugin>
    
        <jdbcConnection driverClass="${jdbc.driver}"
                        connectionURL="${jdbc.url}"
                        userId="${jdbc.username}"
                        password="${jdbc.password}">
        </jdbcConnection>
    
        <javaModelGenerator targetPackage="${targetModelPackage}" targetProject="${targetJavaProject}"/>
    
        <sqlMapGenerator targetPackage="${targetXMLPackage}"  targetProject="${targetResourcesProject}"/>
    
        <javaClientGenerator targetPackage="${targetMapperPackage}" targetProject="${targetJavaProject}" type="XMLMAPPER" />
    
        <table tableName="%" >
          <generatedKey column="id" sqlStatement="Mysql" identity="true"/>
        </table>
      </context>
    </generatorConfiguration>

    二.集成开发

    1.开发工具采用的是idea,数据库mysql 这里推荐navicat与mamp两款。

   

       三.测试

    废话完了,那么就得来点实际的,接下来演示项目的缓存与shiro的用法部分吧。

1.首先是cache。

controller

package com.marks.framework.controller;

import com.github.pagehelper.PageInfo;
import com.marks.framework.service.TagMapService;
import com.marks.framework.service.TestTagService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

/**
 * Created  16/9/28 下午6:02
 *
 * @memo
 */
@Controller
public class TestApi {

    Logger logger = Logger.getLogger(TestApi.class);
    
    @Autowired
    private TagMapService tagMapService;

    @Autowired
    private TestTagService testTagService;

    @ResponseBody
    @RequestMapping("/test1")
    public List showTest() {
        long start = System.currentTimeMillis();
        List list = tagMapService.selectAll();
        logger.error("所用的时间为:"+(System.currentTimeMillis()-start));
        return list;
    }

    @ResponseBody
    @RequestMapping("/test2")
    public PageInfo showTest2() {

        return testTagService.selectPageInfo(1,10);
    }

}

service

package com.marks.framework.service;

import com.marks.framework.dao.MapTagMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Created 16/9/28 下午5:59
 *
 * @memo
 */
@Service
public class TagMapService {

    @Autowired
    private MapTagMapper mapTagMapper;

    public List selectAll() {
        List list = mapTagMapper.selectAll();
        return list;
    }
}

不使用缓存注解  测试查询 结果为:

2016-09-29 10:03:00  [ http-nio-8033-exec-1:12176 ] - [ ERROR ]  所用的时间为:223
2016-09-29 10:06:13  [ http-nio-8033-exec-3:204667 ] - [ ERROR ]  所用的时间为:69
2016-09-29 10:06:36  [ http-nio-8033-exec-2:228363 ] - [ ERROR ]  所用的时间为:39
2016-09-29 10:07:02  [ http-nio-8033-exec-4:253452 ] - [ ERROR ]  所用的时间为:26
2016-09-29 10:07:36  [ http-nio-8033-exec-5:287906 ] - [ ERROR ]  所用的时间为:19
2016-09-29 10:08:06  [ http-nio-8033-exec-6:318311 ] - [ ERROR ]  所用的时间为:22
2016-09-29 10:08:30  [ http-nio-8033-exec-7:342038 ] - [ ERROR ]  所用的时间为:23

在service层增加一个注解

ackage com.marks.framework.service;

import com.marks.framework.dao.MapTagMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Created  16/9/28 下午5:59
 *
 * @memo
 */
@Service
public class TagMapService {

    @Autowired
    private MapTagMapper mapTagMapper;
    //这个testCache即是在ehcache.xml里面配置的
    @Cacheable("testCache")
    public List selectAll() {
        List list = mapTagMapper.selectAll();
        return list;
    }
}

使用注解后测试结果为:

[ERROR] 2016-09-29 10:15:26 TestApi@(TestApi.java:35):所用的时间为:219
[ERROR] 2016-09-29 10:15:33 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:15:37 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:15:42 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:15:49 TestApi@(TestApi.java:35):所用的时间为:0

新增一个插入数据  刷新缓存

service

package com.marks.framework.service;

import com.marks.framework.dao.MapTagMapper;
import com.marks.framework.entity.MapTag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Created 16/9/28 下午5:59
 *
 * @memo
 */
@Service
public class TagMapService {

    @Autowired
    private MapTagMapper mapTagMapper;

    @Cacheable("testCache")
    public List selectAll() {
        List list = mapTagMapper.selectAll();
        return list;
    }

    @CacheEvict("testCache")
    public int insertTag() {

        MapTag tag = new MapTag();
        tag.setName("test1");
        return mapTagMapper.insertSelective(tag);
    }



}

controller

package com.marks.framework.controller;

import com.github.pagehelper.PageInfo;
import com.marks.framework.service.TagMapService;
import com.marks.framework.service.TestTagService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

/**
 * Created  16/9/28 下午6:02
 *
 * @memo
 */
@Controller
public class TestApi {

    Logger logger = Logger.getLogger(TestApi.class);

    @Autowired
    private TagMapService tagMapService;

    @Autowired
    private TestTagService testTagService;

    @ResponseBody
    @RequestMapping("/test1")
    public List showTest() {
        long start = System.currentTimeMillis();
        List list = tagMapService.selectAll();
        logger.error("所用的时间为:"+(System.currentTimeMillis()-start));
        return list;
    }

    @ResponseBody
    @RequestMapping("/test2")
    public PageInfo showTest2() {

        return testTagService.selectPageInfo(1,10);
    }

    @ResponseBody
    @RequestMapping("/test3")
    public int showTest3() {
        logger.error("执行了一个插入数据的操作");
        return  tagMapService.insertTag();
    }

}

结果为:

[ERROR] 2016-09-29 10:31:27 TestApi@(TestApi.java:35):所用的时间为:235
[ERROR] 2016-09-29 10:31:39 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:31:46 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:31:56 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:31:59 TestApi@(TestApi.java:49):执行了一个插入数据的操作
[ERROR] 2016-09-29 10:32:05 TestApi@(TestApi.java:35):所用的时间为:82
[ERROR] 2016-09-29 10:32:12 TestApi@(TestApi.java:35):所用的时间为:1
[ERROR] 2016-09-29 10:32:22 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:32:34 TestApi@(TestApi.java:35):所用的时间为:0

2.测试分页

1.service

package com.marks.framework.service;

import com.github.pagehelper.PageInfo;
import com.marks.framework.entity.MapTag;

/**
 * Created  16/9/28 下午6:11
 *
 * @memo
 */
public interface TestTagService extends IService<MapTag> {

    PageInfo selectPageInfo(int page, int limit);

}
package com.marks.framework.service.imp;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.marks.framework.entity.MapTag;
import com.marks.framework.service.TestTagService;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Created  16/9/28 下午6:13
 *
 * @memo
 */
@Service
public class TestTagServiceImp extends BaseService<MapTag> implements TestTagService{

    @Override
    public PageInfo selectPageInfo(int page, int limit) {
        PageHelper.startPage(page,limit);
        List list = mapper.selectAll();
        return  new PageInfo(list);
    }
}

IService


package com.marks.framework.service;

import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 通用接口
 */
@Service
public interface IService<T> {

    T selectByKey(Object key);

    int save(T entity);

    int delete(Object key);

    int updateAll(T entity);

    int updateNotNull(T entity);

    List<T> selectByExample(Object example);

    //TODO 其他...
}

baseService

package com.marks.framework.service.imp;

import com.marks.framework.service.IService;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.common.Mapper;

import java.util.List;

/**
 * Created by liuzh on 2014/12/11.
 */
public abstract class BaseService<T> implements IService<T> {

    @Autowired
    protected Mapper<T> mapper;

    public Mapper<T> getMapper() {
        return mapper;
    }

    @Override
    public T selectByKey(Object key) {
        return mapper.selectByPrimaryKey(key);
    }

    public int save(T entity) {
        return mapper.insert(entity);
    }

    public int delete(Object key) {
        return mapper.deleteByPrimaryKey(key);
    }

    public int updateAll(T entity) {
        return mapper.updateByPrimaryKey(entity);
    }

    public int updateNotNull(T entity) {
        return mapper.updateByPrimaryKeySelective(entity);
    }

    public List<T> selectByExample(Object example) {
        return mapper.selectByExample(example);
    }

    //TODO 其他...
}

controller 之前的代码贴过 就不贴了  看之前的

结果:

{
    "pageNum": 1,
    "pageSize": 10,
    "size": 10,
    "orderBy": null,
    "startRow": 1,
    "endRow": 10,
    "total": 2859,
    "pages": 286,
    "list": [
        {
            "id": 143,
            "name": "宁河分线1#",
            "longitude": "120.195322",
            "latitude": "30.355647",
            "city": null,
            "state": "1",
            "img": "0",
            "memo": "",
            "address": null,
            "isMove": 0,
            "createTime": 1463381982000
            
        },
        {
            "id": 144,
            "name": "田安一站",
            "longitude": "120.195378",
            "latitude": "30.35531",
            "city": null,
            "state": "1",
            "img": "1",
            "memo": "田园河畔居4幢地下室",
            "address": null,
            "isMove": 0,
            "createTime": 1463382127000
            
        },
        {
            "id": 145,
            "name": "宁河站",
            "longitude": "120.194731",
            "latitude": "30.355662",
            "city": null,
            "state": "1",
            "img": "0",
            "memo": "半山路新时代幼儿园旁(宁河弄附近)",
            "address": null,
            "isMove": 0,
            "createTime": 1463382727000
           
        },
        {
            "id": 147,
            "name": "园野站",
            "longitude": "120.194533",
            "latitude": "30.355455",
            "city": null,
            "state": "1",
            "img": "0",
            "memo": "半山路公交终点站旁(公共自行车停放点旁/路口垃圾箱后面)",
            "address": null,
            "isMove": 0,
            "createTime": 1463383631000
            
        },
        {
            "id": 148,
            "name": "田畔站",
            "longitude": "120.195005",
            "latitude": "30.355204",
            "city": null,
            "state": "1",
            "img": "0",
            "memo": "半山公交总站东南角房子内 拱墅半山供电营业厅旁)",
            "address": null,
            "isMove": 0,
            "createTime": 1463383743000
            
        },
        {
            "id": 149,
            "name": "田安二站",
            "longitude": "120.195472",
            "latitude": "30.354803",
            "city": null,
            "state": "1",
            "img": "0",
            "memo": "田园河畔居7-8幢之间",
            "address": null,
            "isMove": 0,
            "createTime": 1463383872000
            
        },
        {
            "id": 150,
            "name": "玻宿二站",
            "longitude": "120.195388",
            "latitude": "30.356453",
            "city": null,
            "state": "1",
            "img": "0",
            "memo": "半山宁河弄1幢旁",
            "address": null,
            "isMove": 0,
            "createTime": 1463384069000
            
        },
        {
            "id": 151,
            "name": "明园一、二站",
            "longitude": "120.193717",
            "latitude": "30.356389",
            "city": null,
            "state": "1",
            "img": "0",
            "memo": "明园路小区旁",
            "address": null,
            "isMove": 0,
            "createTime": 1463384177000
            
        },
        {
            "id": 152,
            "name": "山安站",
            "longitude": "120.192122",
            "latitude": "30.354577",
            "city": null,
            "state": "1",
            "img": "0",
            "memo": "半山路87号城北大厦南面半山家苑6幢3号",
            "address": null,
            "isMove": 0,
            "createTime": 1463384379000
            
        },
        {
            "id": 153,
            "name": "钢宿站",
            "longitude": "120.191182",
            "latitude": "30.355051",
            "city": null,
            "state": "1",
            "img": "0",
            "memo": "半山路行钢南苑16幢东面的公共厕所后面",
            "address": null,
            "isMove": 0,
            "createTime": 1463384489000
            
        }
    ],
    "firstPage": 1,
    "prePage": 0,
    "nextPage": 2,
    "lastPage": 8,
    "isFirstPage": true,
    "isLastPage": false,
    "hasPreviousPage": false,
    "hasNextPage": true,
    "navigatePages": 8,
    "navigatepageNums": [
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8
    ]
}

具体的参数请参考  https://github.com/pagehelper/Mybatis-PageHelper

3.测试shiro

package com.marks.framework.security;

import org.apache.log4j.Logger;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;

/**
 * 
 *配置文件的组件bean
 * 
 * 
 **/
@Component(value = "securityRealm")
public class SecurityRealm extends AuthorizingRealm {

    Logger logger = Logger.getLogger(SecurityRealm.class);

    /**
     * 权限检查
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        String username = String.valueOf(principals.getPrimaryPrincipal());
        logger.error("doGetAuthorizationInfo==" + username);

        authorizationInfo.addRole("admin");
        authorizationInfo.addStringPermission("user:create");
        authorizationInfo.addStringPermission("add");

        return authorizationInfo;
    }

    /**
     * 登录验证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = String.valueOf(token.getPrincipal());
        String password = new String((char[]) token.getCredentials());
        logger.error("doGetAuthenticationInfo:" + "username=" + username + " password:" + password);
        if (!username.equals("admin") && !password.equals("123456")) {
            throw new AuthenticationException("用户名或密码错误.");
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, password, getName());
        return authenticationInfo;
    }

}

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>我是登录的界面</title>
</head>
<body>
    <span>请先登录</span>

    <form  action="/rest/user/login" method="post">

        <input  type="text" name="username" required/>
        <input type="password" name="password" required/>
        <input type="submit" value="on click"/>
    </form>


</body>
</html>

main.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<head>
    <title>I am main</title>
</head>
<body>
    <span>欢迎来到首页,<shiro:principal/></span>


    <table>

        <tr><td><shiro:authenticated>用户已经登录显示此内容</shiro:authenticated></td></tr>
        <tr><td><shiro:hasRole name="manager">manager角色登录显示此内容</shiro:hasRole></td></tr>
        <tr><td><shiro:hasRole name="admin">admin角色登录显示此内容</shiro:hasRole></td></tr>
        <tr><td><shiro:hasRole name="normal">normal角色登录显示此内容</shiro:hasRole></td></tr>

        <tr><td><shiro:hasAnyRoles name="manager,admin">**manager or admin 角色用户登录显示此内容**</shiro:hasAnyRoles></td></tr>
        <tr><td> <shiro:principal/>-显示当前登录用户名</td></tr>
        <tr> <td><shiro:hasPermission name="add">add权限用户显示此内容</shiro:hasPermission></td></tr>
        <tr><td><shiro:hasPermission name="user:query">query权限用户显示此内容<shiro:principal/></shiro:hasPermission></td></tr>
        <tr><td> <shiro:hasPermission name="user:create">user:create权限用户显示此内容<shiro:principal/></shiro:hasPermission></td></tr>
        <tr><td><shiro:lacksPermission name="user:del"> 不具有user:del权限的用户显示此内容 </shiro:lacksPermission></td></tr>


    </table>


</body>
</html>

测试:

图1.

111056_7dYX_2661827.png

图2

111154_2iKm_2661827.png

图3

111443_c9bd_2661827.png

图4

图5111639_UElb_2661827.png

111710_gVEr_2661827.png

 

总结:

在整合的时候有些地方只是考虑到简单的整合,所以要运用到正真开发的项目还需要自己按照需求进行修改。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/swiftloop/blog/753136

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值