zoukankan      html  css  js  c++  java
  • Spring+MyBatis+SpringMVC整合

    Spring+SpringMVC+MyBatis

    《一》MyBatis配置文件xml

    MyBatis框架依赖的jar包:下载地址:https://github.com/mybatis/mybatis-3/releases

       

    1.头信息

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

    1.配置标签

    <configuration>

        ……………………………

    </ configuration >

    3.配置properties属性

    [这个可以整合到Spring的配置文件中]  properties元素的配置:(两种方式)

       

    a:通过指定外部配置文件的方式

    b:直接配置yBatisXML文件

       

    4.配置settings设置标签

    <settings> 

            <!-- 这个配置使全局的映射器启用或禁用缓存 --> 

            <setting name="cacheEnabled" value="true" /> 

            <!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载 --> 

            <setting name="lazyLoadingEnabled" value="true" /> 

            <!-- 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载 --> 

            <setting name="aggressiveLazyLoading" value="true" /> 

            <!-- 允许或不允许多种结果集从一个单独的语句中返回(需要适合的驱动) --> 

            <setting name="multipleResultSetsEnabled" value="true" /> 

            <!-- 使用列标签代替列名。不同的驱动在这方便表现不同。参考驱动文档或充分测试两种方法来决定所使用的驱动 --> 

            <setting name="useColumnLabel" value="true" /> 

            <!-- 允许JDBC支持生成的键。需要适合的驱动。如果设置为true则这个设置强制生成的键被使用,尽管一些驱动拒绝兼容但仍然有效(比如Derby --> 

            <setting name="useGeneratedKeys" value="true" /> 

            <!-- 指定MyBatis如何自动映射列到字段/属性。PARTIAL只会自动映射简单,没有嵌套的结果。FULL会自动映射任意复杂的结果(嵌套的或其他情况) --> 

            <setting name="autoMappingBehavior" value="PARTIAL" /> 

            <!-- 配置默认的执行器。SIMPLE执行器没有什么特别之处。REUSE执行器重用预处理语句。BATCH执行器重用语句和批量更新 --> 

            <setting name="defaultExecutorType" value="SIMPLE" /> 

            <!-- 设置超时时间,它决定驱动等待一个数据库响应的时间 --> 

            <setting name="defaultStatementTimeout" value="25000" /> 

        </settings>  

       

    5.配置typeAlisases别名标签

    [这个可以整合到Spring的配置文件中] 定义类的别名,一般用类名做别名

    <typeAliases> 

          <typeAlias alias="pageAccessURL" type="com.lgm.mybatis.model.PageAccessURL" /> 

    </typeAliases>

       

    6.配置typeHandlers类型处理器

       

    7.配置objectFactory对象工厂

       

    8.配置plugins插件

       

    9.配置environments配置环境

       

    <environments  default="development"> 

         <!-- 环境配置1,每个SqlSessionFactory对应一个环境 --> 

         <environment  id="development1"> 

                <!-- 事务配置 type= JDBCMANAGED 1.JDBC:这个配置直接简单使用了JDBC的提交和回滚设置。它依赖于从数据源得到的连接来管理事务范围。  

                    2.MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让容器来管理事务的整个生命周期(比如SpringJEE应用服务器的上下文)。  

                    默认情况下它会关闭连接。然而一些容器并不希望这样,因此如果你需要从连接中停止它,将closeConnection属性设置为false --> 

            <transactionManager type="JDBC" /> 

            <!-- <transactionManager type="MANAGED">  

                        <property name="closeConnection" value="false"/>  

                     </transactionManager> --> 

                <!-- 数据源类型:type = UNPOOLEDPOOLEDJNDI 1.UNPOOLED:这个数据源的实现是每次被请求时简单打开和关闭连接。它有一点慢,这是对简单应用程序的一个很好的选择,因为它不需要及时的可用连接。  

                    不同的数据库对这个的表现也是不一样的,所以对某些数据库来说配置数据源并不重要,这个配置也是闲置的 2.POOLED:这是JDBC连接对象的数据源连接池的实现,用来避免创建新的连接实例时必要的初始连接和认证时间。  

                    这是一种当前Web应用程序用来快速响应请求很流行的方法。 3.JNDI:这个数据源的实现是为了使用如Spring或应用服务器这类的容器,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文的引用 -->  

                 <dataSource type="UNPOOLED"> 

                    <property name="driver" value="com.mysql.jdbc.Driver" /> 

                    <property name="url" value="jdbc:mysql://localhost:3306/appdb" /> 

                    <property name="username" value="root" /> 

                    <property name="password" value="123456" /> 

                    <!-- 默认连接事务隔离级别

    <property name="defaultTransactionIsolationLevel" value="" /> --> 

                 </dataSource>   

           </environment> 

    </environments>

       

    10.配置mappers映射文件

    <!-- 映射文件,存放sql语句的xml配置文件的路径 --> 

        <mappers> 

            <mapper resource="com/lgm/mybatis/config/pageAccessURL.xml" /> 

    </mappers>

       

       

    《二》SpringMyBatis的整合

       

    编写Spring配置文件:applicationContext-mybatis.xml

    需要的jar包:mybatis-spring-1.2.0.jar

       

    0.配置文件头信息

       

    详见文档……

       

    1.加载properties文件,可以配置一些数据库的连接参数和线程池的初始化参数,加载properties文件的方法主要有两种,详细见资料。

       

    reaources目录下编写配置文件内容:

    ====================================

    driver=com.mysql.jdbc.Driver

    url=jdbc:mysql://10.221.10.111:8080/db_zsl

    username=demao

    password=demao

    #定义初始连接数

    initialSize=0

    #定义最大连接数

    maxActive=20

    #定义最大空闲

    maxIdle=20

    #定义最小空闲

    minIdle=1

    #定义最长等待时间

    maxWait=60000

    =====================================

    加载配置文件:

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

      <property name="locations">

        <array><value>classpath:database.properties</value></array>

      </property>

    </bean>

       

    2.配置数据源

    dbcpc3p0,Proxool,他们都实现了连接池的功能

    使用到的jar包:commons-dbcp-1.4.jar,commons-pool-1.6.jar

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">

        <property name="driverClassName" value="${driver}"/>

        <property name="url" value="${url}"/>

        <property name="username" value="${user}"/>

    <property name="password" value="${password}"/>

    <property name="initialSize" value="${initialSize}"/>

       <property name="maxActive" value="${maxActive}"/>

       <property name="maxIdle" value="${maxIdle}"/>

       <property name="minIdle" value="${minIdle}"/>

       

    </bean>

       

       

    3.配置sqlSessionFactory

    SqlSessionFactoryBean提供了很多丰富的属性来整合MyBatis的各种元素和属性,SqlSessionFactoryBean来替代SqlSessionFactoryBuilder来创建SqlSession

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

        //配置数据源引用

    <property name="dataSource" ref="dataSource"></property>

    //引入mybatisxml文件

    <property name="configLocation" value="classpath:mybatis-config.xml"></property>

    //将指定包下的类的类名作为该类的别名

    <property name="typeAliasesPackage" value="com.del.pojo"></property>

    //指定mapper映射文件的位置

        <property name="mapperLocations">

         <list>

           <value>classpath:com/del/dao/UserMapper.xml</value>

         </list>

        </property>

    </bean>

       

       

    4.配置MapperScannerConfigurer批量产生接口映射器实现类1,实现类中已经注入sqlSessionFactory,getsession自动递归扫描指定包下的Mapper接口,并将他们直接动态注册为MapperFactoryBean, 接口名称作为Bean组件的名称,首字母小写。并且会注入SqlSessionFactory,若有多个SqlSessionFactory,则必须显示地指定具体用哪个SqlSessionFactory,因此可以拿到sqlsessionTemplate的实例。

       

    <property name="SqlSessionFactoryBeanName" value="SqlSessionFactoryBean "></property>

    使用MapperScannerConfigurer@Autowired注解和@Resource注解能够配合使用,自动创建映射器实现,并注入给业务组件,能很大程度减少DAO组件的业务组件的编码工作。最后通过SpringgetBean()方法直接拿到DAO和业务层的实例,直接使用。

       

    ===============================补充==================================

       

    补充1 MapperFactoryBean数据映射器实现

    为什么需要映射器实现类? (也就是手动编写映射器存在的问题)

    1SqlSession.selectList()等方法需要采用字符串指定映射项,易写错

    2SqlSession.getMapper()方法需要在每次调用的时候都实现一次接口.

    由此诞生注入映射器,在容器中始终存在一个映射器接口的实现类xxxImpl,这样就将可以用XXXImpl.接口方法() 的方式操作sql语句,取代了SqlSession.selectList()的方式

       

    采用MapperFactoryBean数据映射器实现Mapper映射,

    根据Mmapper接口获取Mapper对象,它封装了原有的SqlSession.getMapper()功能的实现MapperFactoryBeanSqlSessionDaoSupport的子类[接口名称和里面的方法名称一定要和映射文件的id对应]     配置方法:

    这里注入sqlSessionFactory属性,以便于获得sqlSessionTemplate实例,

       

    补充2sqlSessionTemplate

    A:配置sqlSessionTemplate以获得sqlSession,

    通过传入一个SqlSessionFactory构造得到SqlSessionTemplate实例,因为没有set()不能设置注入)

    B:另一种获取SqlSession的方法(继承它的基类SqlSessionDaoSupport)

    通过set()方法注入Factory,同过getSqlSession()方法得SqlSession

    =============================补充结束==============================

    引入注解支持

    xmlns:context="http://www.springframework.org/schema/context"

       

    xsi:schemaLocation="

    http://www.springframework.org/schema/context    http://www.springframework.org/schema/context/spring-context-3.2.xsd "

       

    开启注解支持,扫描基准包自动批量注册为Bean组件,添加命名空间,模板实例地址,扫描service层包,这样的配置基本上把我们全部的DAOService扫描进来了,很强大

    <context:component-scan base-package="com.del.service,com.del.dao"/>

       

    (有的时候版本低,扫描不能开启注解,则应该用下面这句配置开启注解支持)

    <context:annotation-config/>

       

    //配置MapperScannerConfigurer批量产生映射器实现类

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

        <property name="basePackage" value="com.del.dao"></property>

    </bean>

       

       

       

    5.配置事务管理器

       

    A:通过配置xml声明事务

    1:导入txaop命名空间

    2:定义事务管理器,并为其注入数据源Bean

    3:通过<tx:advice>配置事务增强,绑定事务管理并针对不同的方法定义 事务规则。

    4:配置切面,将事务增强与方法切入点组合。

    xmlns:aop="http://www.springframework.org/schema/aop"   xmlns:tx="http://www.springframework.org/schema/tx"

       

    <!-- 事务管理器 -->

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

       <property name="dataSource" ref="dataSource"/>

    </bean> 

    <!—配置增强 -->

    <tx:advice id="txAdvice" transaction-manager="txManager">

           定义很多事务规则

           <tx:attributes>

    规则1

              <tx:method name="find*" read-only="true" propagation="SUPPORTS" timeout="1000" isolation="SERIALIZABLE" />

    规则2

              <tx:method name="*" propagation="REQUIRED"/>

           </tx:attributes>     

    </tx:advice>

    <!-- 配置切面 -->

    <!--配置切面-->里面的切点表达式里面切中的所有方法中筛选符合<!--配置增强-->里面的name属性要求的方法

    <aop:config>

        <aop:pointcut expression="execution(* cn.smbms.service..*.*(..))" id="myPoint"/>

    引用增强*                             引用切点

        <aop:advisor advice-ref="txAdvice" pointcut-ref="myPoint"/>

    </aop:config>

       

    --------------补充-----------------

    Propagation:事务的传播机制

    REQUIRED(默认值):如果存在一个事务则加入到一个事务,如果不存在事

                       务,则开启一个事务,能够满足大多数事务的需求,

    REQUIRES_NEW/MANDATORY/NESTED

    SUPPORTS:        如果存在事务方法当中,则加入事务。如果不存在事务,则以非事务方式运

                     行。适用于查询的方法。

    NOT_SUPPORTED/NEVER

    -----------------------------

    isolation:事务的隔离等级

     1. DEFAULT 这是TransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.

     2. READ_UNCOMMITTED 这是事务最低的隔离级别,充许令外一个事务可以看到这个事务未提交的数据。

          这种隔离级别会产生脏读,不可重复读和幻像读。

     3. READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据

     4. REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。

          它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)

     5. SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。

          除了防止脏读,不可重复读外,还避免了幻像读。

    ---------------------------

    <tx里面加事务属性:

    timeout:设置事务的最长运行时间s。一般默认是-1,永不超时。

    Read-only:设置事务是否为只读,默认值是false,可以提高性能

    rollback-for:设定能够触发回滚的异常类型

        Spring默认值在抛出runtimeException时才标识事务回滚

        可以通过完全限定类名指定需要回滚事务的异常。多个类名用逗号隔开

    no-rollback-for:指定不触发回滚的异常类型。

        Spring默认checked Exception不会触发事务回滚

    可以通过完全限定类名指定不需要回滚事务的异常。多个类名逗号隔开

    --------------------补充结束--------------------

       

    B:使用注解实现事务处理

    xmlns:aop="http://www.springframework.org/schema/aop"   xmlns:tx="http://www.springframework.org/schema/tx"

    <!-- 事务管理器 -->

        <bean id="txManager"

                 class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

                 <property name="dataSource" ref="dataSource"></property>

        </bean>

    <tx:annotation-driven transaction-manager="txManager"/>

       

       

    6.配置log4j

       

    详见文档…….

       

       

       

       

    《三》SpringSpringMVC的整合

       

    A: 配置web.xml文件

       

    1:头信息

    <?xml version="1.0" encoding="UTF-8"?>

    <web-app version="3.0"

        xmlns="http://java.sun.com/xml/ns/javaee"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    //配置显示名称

    <display-name>SSMEBUY</display-name>

    //配置欢迎页

    <welcome-file-list>

        <welcome-file>index.jsp</welcome-file>

      </welcome-file-list>

       

    2:加载Spring配置文件

       

    <context-param>

         <param-name>contextConfigLocation</param-name>

         <param-value>classpath:applicationContext-mybatis.xml</param-value>

     </context-param>

       

    3:字符编码的filter过滤器

    spring mvc3.2及以上版本增加了对请求的异步处理,是在servlet3的基础上进行封装的。

    声明version="3.0",声明web-app_3_0.xsd

    servlet或者filter设置启用异步支持:<async-supported>true</async-supported>,修改WEB应用的web.xml

       

    <filter>

           <filter-name>encodingFilter</filter-name>     <filter-class>org.springframework.web.filter.CharacterEncodingFilter             </filter-class>

            //servlet或者filter设置启用异步支持

           <async-supported>true</async-supported>

           <init-param>

    //encoding用来设置编码格式

               <param-name>encoding</param-name>

               <param-value>UTF-8</param-value>

           </init-param>

           <init-param> 

    //forceEncoding用来设置是否理会 request.getCharacterEncoding()方法,

    //设置为true则强制覆盖之前的编码格式。 

                <param-name>forceEncoding</param-name>  

                <param-value>true</param-value>  

           </init-param>  

    </filter>

       

       

    <filter-mapping>

           <filter-name>encodingFilter</filter-name>

           <url-pattern>/*</url-pattern>

    </filter-mapping>

       

       

       

       

    4:容器启动监听器,去初始化容器

    web容器的入口是被WEB容器所控制的,所以无法在main方法中同过调用创建classpath.xml application context对象来启动spring 容器。所以spring容器提供了一个监听类叫做contextLoaderListen,这个监听实现了servletListener接口,可以在外部容器启动的时候去初始容器,当然,前提是我们必须在web.xml文件中先配置此监听,配置如下:

       

    <listener>    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

    </listener>

       

    5:防止Spring内存溢出监听器

    <listener>

    <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>

    </listener>

    6log4j监听器

       

     

    7:前端核心控制器DispatcherServlet

    它的作用:调用springmvc配置文件的映射,将不同的请求分配给不同的控制器controler!

    要点:其中param-name的命名,要与springmvc的配置文件的名称一致

       

    <servlet>

         <servlet-name>dispatcherServlet</servlet-name>     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

         <init-param>

            //wenb项目去哪个位置加载springmvc的配置文件

            <param-name>contextConfigLocation</param-name>

            <param-value>classpath:springmvc-servlet.xml</param-value>

         </init-param>

         //设置1表示启动时就加载该servlet

         <load-on-startup>1</load-on-startup>

    </servlet>

       

    <servlet-mapping>

          <servlet-name>dispatcherServlet</servlet-name>

          <url-pattern>/</url-pattern>

    </servlet-mapping>

       

    B: 配置springmvc.xml文件

    1:配置头信息

    <?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:mvc="http://www.springframework.org/schema/mvc"

        xmlns:p="http://www.springframework.org/schema/p"

        xmlns:context="http://www.springframework.org/schema/context"

        xsi:schemaLocation="

            http://www.springframework.org/schema/beans

            http://www.springframework.org/schema/beans/spring-beans.xsd

            http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context.xsd

            http://www.springframework.org/schema/mvc

            http://www.springframework.org/schema/mvc/spring-mvc.xsd">

       

     

    2:利用SpringMVC的注解批量配置处理器映射

       

    <context:component-scan base-package="com.del.service,com.del.controller"/>

    自动扫描cn.smbms.controller包下的javaBean,使添加了标注的处理器Bean组件生效,此时的javaBean不再需要继承AbstractController,

     

    <mvc:annotation-driven/>

    作用:自动批量注册处理器映射,小写驼峰命名,注册完成之后,再通过DefaultAnnotationHandlerMappingAnnotationMethodHandlerAdapter这两个Bean的实例完成对注解的支持.@Controller表示处理器,用@RequestMapping()表示请求映射.

    --------------------重点-----------------------------

    dataBinder

    DefaultAnnotationHandlerMapping:作用:映射器

    用来解析Spring MVC里面的annotation对应的Controller,也就是通过这个类,给annotation设置映射关系,如@RequestMapping等

    AnnotationMethodHandlerAdapter:作用:适配器

    对Annotation设置的方法进行处理,再返回给!

     

    还会自动注册FormarttingConversionServiceFactoryBean(此实例为spring类型转换核心接口ConversionService的默认注册实例)来通过格式化注解,解决日期的格式转换问题

     

    HttpMessageConverter接口

    @ResponseBody这个注解就是使用消息转换机制,最终通过json的转换器转换成json数据的。

    HttpMessageConverter接口就是Spring提供的http消息转换接口。

     

       

    ============================补充=======================================

    配置处理器映射所用的接口HandlerMapping:

    1:第一个是实现类Spring默认的处理器映射,意思是查找与请求URL同名的处理器Bean,这个映射器是不需要配置就可以生效的:

    2:第二个实现类是通过注解的方式来进行URL和处理器Bean组件的映射

       

    SpringMVC是如何配置处理器映射的呢?

       

    1:默认用BeanNameUrlHandlerMapping配置处理器映射,表示:(如果请求的路劲是"/index.html",则分配到后面class所指定的处理器去处理)

    <bean name="/index.html" class="cn.smbms.controller.IndexController"/>

       

    2:A:创建一个控制器:同过继承AbstractController,重写handlerRequestInternal方法,将IndexController这样的javaBean变成一个能处理前端请求的控制器

       

    B: 配置视图层的Bean组件

       

       

    当我们需要controller返回一个mapjson对象时,可以设定<mvc:annotation-driven />

    同时设定<mvc:message-converters> 标签,设定字符集和json处理类,如下代码:

    ============================补充结束===================================

       

    3:配置视图解析器

    配置单视图解析器作用:将返回的逻辑视图名和前缀,后缀,进行拼接成新的viewurl,prefix属性和suffix属性其实是InternalResourceViewResolver的父类的属性.

       

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

     <property name="prefix" value="WEB-INF/jsp"></property>

     <property name="suffix" value=".jsp"></property>

    </bean>

       

    4:配置多视图解析器

    1:根据请求的MIME类型决定视图解析器

    2:同样的内容数据可以通过不同的view(html,json,xml,xls)进行前台的展现

       

    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">

            <property name="favorParameter" value="true"/>

            <property name="defaultContentType" value="text/html"/>

            <property name="mediaTypes">

                <map>

                    <entry key="html" value="text/html;charset=UTF-8"/>

                    <entry key="json" value="application/json;charset=UTF-8"/>

                    <entry key="xml" value="application/xml;charset=UTF-8"/>

                </map>

            </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>

    </bean>

       

       

    5:配置文件上传CommonsMultipartResolver

       

    <!-- 配置MultipartResolver,用于上传文件,使用springCommonsMultipartResolver --> 

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

             <property name="maxUploadSize" value="5000000"/>

             <property name="defaultEncoding" value="UTF-8"/>

     </bean>

       

       

    6:配置全局异常处理SimpleMappingExceptionResolver

    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">

            <property name="exceptionMappings">

                <props>

                    <prop key="java.lang.RuntimeException">error</prop>

                </props>

            </property>

    </bean>

       

       

    7.配置静态资源(3种方法)

    1:上面提到过如果在配置前端控制器时拦截了所有的请求,不做特殊处理就会导致部分静态资源无法使用。如果是这种情况就可以使用下面的配置来访问静态资源文件。

    <mvc:resources mapping="/images/**" location="/images/" />

    <mvc:resources mapping="/css/**" location="/css/" /> 

    <mvc:resources mapping="/js/**" location="/js/" />

    <mvc:resources mapping="/imgdata/**" location="/imgdata/" />

    2

  • 相关阅读:
    Cross-Site Scripting XSS 跨站攻击全攻略 分类: 系统架构 2015-07-08 12:25 21人阅读 评论(2) 收藏
    WAS集群:记一次Node Agent不活动问题解决过程
    Oracle RAC集群资料收集
    Linux使用 tar命令-g参数进行增量+差异备份、还原文件
    WAS7.0安装补丁升级程序无法替换文件 java/docs/autorun.inf解决办法
    Java程序员面试失败的5大原因
    Lemon OA第4篇:常用功能
    Lemon OA第3篇:核心功能
    Lemon OA第2篇:功能解析方法
    Activiti5小试牛刀demo流程
  • 原文地址:https://www.cnblogs.com/domi22/p/8048133.html
Copyright © 2011-2022 走看看