zoukankan      html  css  js  c++  java
  • Struts+Spring+Hibernate整合入门详解

    Java 5.0

    Struts 2.0.9

    Spring 2.0.6

    Hibernate 3.2.4

                                                 作者:  Liu Liu 转载请注明出处

    基本概念和典型实用例子。

    一、基本概念

          Struts:作为基于 MVC 模式的 Web 应用最经典框架,两个项目Struts webwork已经集成,成为现在的Struts2。目前的最新版本是2.0.92007-7)。

          Spring 是一个轻型的容器,利用它可以使用一个外部 XML 配置文件方便地将对象连接在一起。每个对象都可以通过显示一个 JavaBean 属性收到一个到依赖对象的引用,留给您的简单任务就只是在一个 XML 配置文件中把它们连接好。

          Hibernate 是一个纯 Java 的对象关系映射和持久性框架,它允许您用 XML 配置文件把普通Java 对象映射到关系数据库表。使用 Hibernate 能够节约大量项目开发时间,因为整个 JDBC 层都由这个框架管理。这意味着您的应用程序的数据访问层位于 Hibernate 之上,完全是从底层数据模型中抽象出来的。

          三种技术到目前已经比较成熟,而且他们都是免费的!让我们对三者集成进行一个初览(简单而不专业):

          我们用Struts实现从Web(网页,MVC中的View)到后台系统的映射(WebàAction),然后由Spring管理这些Action,把它们作为Bean和其他对象一起处理。这些Bean之间处理业务逻辑、数据、系统状态等,且它们被Spring统一管理,为了区分,就算大概包括MVCMC部分吧。然后需要持久化的数据由SpringHibernate之间的接口交由Hibernate处理(这个属于持久层)。

          必须基础:只要Java基础,一点HTML知识、XML基础就可以了。本文的目的就是从零开始建立第一个Struts+Spring+Hibernate应用。即使它是最简单的,我们也希望初学者能够从中理解一些思想,其中也包括系统架构的设计思想。

     

    二、环境搭建

          我们坚持免费才是硬道理,开源才是好事情,所以我们全部使用开源免费的工具和软件。如果使用MyEclipse,其中的工具将有助于简化下面演示的工程开发,但本文不用。

          所需软件包如下表:

    序号

    下载地址和文件(包)名

    说明

    1

    JDK5.0

    http://java.sun.com/javase/downloads/index.jsp

    JDK5.0

    2

    Eclipse WTP

    Eclipse IDE for Java EE Developers

    下载All in One,这样不用自己下载其他插件

    包含网站开发的Eclipsev3.3,下载All in One

    3

    HibernateSynchronizer-3.1.9

    https://sourceforge.net/project/showfiles.php?group_id=99370

    帮助开发Hibernate应用的Eclipse插件

    4

    Hibernate3

    http://sourceforge.net/project/showfiles.php?group_id=40712 à hibernate3所指示的包

    Hibernate支持包

    5

    Spring

    http://sourceforge.net/project/showfiles.php?group_id=73357

     

    spring-framework-2.0.6-with-dependencies.zip

    6

    SpringIDE(可选)

    http://springide.org/updatesite/ 包名如
    springide_updatesite_2.0.1_v200707300600.zip

    7

    Struts

    http://struts.apache.org/download.cgi

     

    为了较全的例子和文档,建议下载
    struts-2.0.9-all.zip否则只下载lib:struts-2.0.9-lib.zip

    8

    Tomcat

    http://tomcat.apache.org

    建议下载v5.5以上版本,应用服务器(支持JSP等)Apache项目之一

    9

    MySQL

     

    Hibernate演示需要

             

     

          1、下载了eclipse以后安装。在所安装的目录下有两个子目录pluginsfeatures,这是两个放eclipse插件的目录,即可以通过拷贝需要的文件到这些目录里面,从而给eclipse添加新的功能。

          2、将第36的包解压,将其中的plugins目录直接复制到eclipse安装目录下,选择“全部”替换。

          3、运行eclipse,选择一个空目录作为工作区(WorkSpace),启动以后可以看到Welcome.html的欢迎界面。现在建立新工程FileàNewàProject,在打开的New Project窗口中选择WebàDynamic Web Project。输入Project name,在Target Runtime一项选择新建(New),选择你所安装的Apache Tomcat,在弹出窗口输入相关信息(Tomcat安装目录等)。

          新建工程流程如下图。

    工程结构如下:

    其中我们要写的Java代码在Java Resource: src(以后直接称src)下,网站根目录内容在WebContent下,类所在根目录是WEB-INF/classesEclipse会自动将build/classes里面已经编译的类同步过去。

    WEB-INF下的lib目录添加如下所列的jar包。 

    1)这些包在下载解压后SpringStrutsHibernatelib目录或者dist/module目录下面(如果不在,可以到网上google一把。列表中mysql-*.jar包是MySQL数据库的JDBC Driver)。也可以把所有libdist下的jar包拷贝过来(可以在系统复制这些jar包,然后到Eclipse里面选中WEB-INF里面的lib包,然后粘帖就可以了)。但要注意全拷贝可能会存在冲突,如struts*plugin.jar等包不能引入,否则不能运行。

    (2)这些Jar包是:

    antlr-2.7.2.jar

    cglib-nodep-2.1_3.jar

    commons-beanutils-1.6.jar

    commons-chain-1.1.jar

    commons-collections-2.1.1.jar

    commons-dbcp.jar

    commons-digester.jar

    commons-logging-1.0.4.jar

    commons-logging-api-1.1.jar

    commons-pool.jar

    commons-validator-1.3.0.jar

    dom4j-1.6.1.jar

    el-api.jar

    el-ri.jar

    freemarker-2.3.8.jar

    hibernate3.jar

    jsf-api.jar

    jta.jar

    mysql-connector-java-3.0.14-production-bin.jar

    ognl-2.6.11.jar

    oro-2.0.8.jar

    spring-hibernate3.jar

    spring.jar

    struts-config.xml

    struts-core-1.3.5.jar

    struts2-codebehind-plugin-2.0.9.jar

    struts2-config-browser-plugin-2.0.9.jar

    struts2-core-2.0.9.jar

    struts2-jasperreports-plugin-2.0.9.jar

    struts2-jfreechart-plugin-2.0.9.jar

    struts2-jsf-plugin-2.0.9.jar

    struts2-pell-multipart-plugin-2.0.9.jar

    struts2-plexus-plugin-2.0.9.jar

    struts2-sitegraph-plugin-2.0.9.jar

    struts2-sitemesh-plugin-2.0.9.jar

    struts2-spring-plugin-2.0.9.jar

    struts2-struts1-plugin-2.0.9.jar

    struts2-tiles-plugin-2.0.9.jar

    tiles-api-2.0.4.jar

    tiles-core-2.0.4.jar

    tiles-jsp-2.0.4.jar

    xwork-2.0.4.jar

    三、开始工作

    WebContent下建立index.jsp,建立方式如图。

    index.jsp的内容如表,我们暂时不分析。

    <%@ page contentType="text/html; charset=UTF-8" %>

    <html>

      <head> <title>Example by Doer Liu@UTStarcom sz </title></head>

      <body>

        This is my JSP page. <br>

        <form name="userInfoForm" action="login.do" method="post">

        用户名:

        <input name="username" type="text" />

        密码:

        <input name="password" type="password">

        <input name="sub" type="submit" value="增加" />

        <input name="res" type="reset" value="重置" />

      </form>

      </body>

    </html>

     

    此时就可以运行该工程,忙了这么久,看看效果吧。

    运行方式:右键点击index.jsp,选择Run/Debug AsàRun on Server,在弹出窗口中默认我们使用的Tomcat Server,点击finish完成。可以看到eclipse中内嵌的浏览器显示我们的网页。其中表单的输入在我们的工程中将得到输入数据(用户名和密码),这些数据会传给我们将要建立的Action处理。

     

    现在来看看如何建立我们的Action。在src下新建一个package(包)名为action用于保存响应Web请求的Action类。在action包下新建ActionLoginActionaction.LoginAction)如下,注意类的继承关系。

    package action;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

     

    import org.apache.struts.action.ActionForm;

    import org.apache.struts.action.ActionForward;

    import org.apache.struts.action.ActionMapping;

    import org.apache.struts.validator.DynaValidatorForm;

    import org.springframework.web.struts.ActionSupport;

     

    //我们继承spring提供的Action衍生类org.springframework.web.struts.ActionSupport

    public class LoginAction extends ActionSupport{

     

        public ActionForward execute(

                 ActionMapping mapping,

                 ActionForm form,

                 HttpServletRequest request,

                 HttpServletResponse response) {

           return mapping.findForward("success");

          

        }

    }

     

    但是现在index.jsp的内容怎么和LoginAction的数据匹配呢,我们看到LoginActionexecute方法有一个属性ActionForm,于是我们建立一个类forms.UserInfoForm如下,继承ActionForm

    package forms;

    import org.apache.struts.action.ActionForm;

    public class UserInfoForm extends ActionForm {

        private String username;

        private String password;

       

        public String getUsername() { return username; }

        public void setUsername(String username)

        { this.username = username; }

     

        public String getPassword() { return password; }

        public void setPassword(String password)

        { this.password = password; }

    }

     

     

    有了两个头,又有了保持内容的类,现在看看我们如何用struts把他们联系起来吧。

    现在需要在WEB-INF下建立文件struts-config.xml。其中form-beans定义了表单是如何映射的,这里用我们刚刚定义的forms.UserInfoForm。

    <?xml version=”1.0” encoding="ISO-8859-1"?>

    <!DOCTYPE struts-config PUBLIC   "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"         "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

     

    <struts-config>

        <form-beans>

           <form-bean name="userInfoForm" type="forms.UserInfoForm"/>

        </form-beans>

       

        <action-mappings>

           <action attribute="userInfoForm" path="/login"input="/index.jsp"type="org.springframework.web.struts.DelegatingActionProxy"

                  name="userInfoForm" scope="session" validate="false">

               <forward name="success" path="/success.html"/>

           </action>

        </action-mappings>

    </struts-config>

     

    <action-mappings>中定义了我们的Action。它的属性attribute指出Action的内容输入是我们自定义的ActionFormpathAction赋予一个路径,input指明只接受index.jsp的输入,<forward标签定义了当Action返回"success"的时候,将定向到/success.html这个网页。 最重要的是type,它定义了这个处理这个请求的Action类,本来应该是我们自定义的LoginAction,但我们却用了spring的一个Action,为什么?因为我们要用Spring管理我们自定义的Action。看,strutsSpring在这里就开始连接起来了。

     

    但还有两个问题,StrutsSpring又是如何知道对方的存在,如何沟通呢?Spring如何知道把控制权交给我们自定义的LoginAction呢?

    我们先来解决第一个问题,web.xmlTomcat这些应用服务器管理的,因此我们在这里将strutsSpring配置联系起来。这是整个web.xml。请看注释。

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

    <web-app version="2.5" id="WebApp"

        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_2_5.xsd">

     

    <display-name> Struts2+Spring2+Hibernate3 simple example by Doer Liu@UTstarcom</display-name>

     <!-- filter就理解为一些对网页请求的过滤吧 -->

     <!-- encodingFilter是为了处理国际化,交由Spring处理,设置为UTF-8 -->

     <filter>

     <filter-name>encodingFilter</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>

     <!-- struts 是struts的filter,这个定义就将可以将请求交给struts过滤一番了 -->

     <filter>

     <filter-name>struts</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>

     </filter>

     

    <!-- 那么哪些请求交给struts过滤呢,这里包括 /struts2spring2hib3bydoer下和根目录/下的所有请求-->

     <filter-mapping>

     <filter-name>struts</filter-name>

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

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

     </filter-mapping>

     

     <!-- 定义一个监听器,处理整个WebContext,简单的理解为整个网站的上下文环境监听器吧这个属于Spring-->

     <listener>

      <listener-class>

       org.springframework.web.context.ContextLoaderListener

      </listener-class>

     </listener>

     

    <!-- servlet定义一个servlet为struts的ActionServlet -->

        <servlet>

           <servlet-name>doertest</servlet-name>

           <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

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

        </servlet>

     

    <!-- servlet-mapping将servlet和请求对应起来,这里是所有*.do的请求交由上面定义的doertest处理 -->

        <servlet-mapping>

           <servlet-name>doertest</servlet-name>

           <url-pattern>*.do</url-pattern>

        </servlet-mapping>

     

    <!-- 定义默认返回页,如输入http://127.0.0.1/那么根目录下的index.html或者其他文件就被请求 -->

        <welcome-file-list>

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

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

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

           <welcome-file>default.html</welcome-file>

           <welcome-file>default.htm</welcome-file>

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

        </welcome-file-list>

    </web-app>

     

     

    通过web.xml两者联系上了。现在它们各自还需要一些配置。

    Struts在我们的例子里比较简单,在build/class下面(最终会被eclipse同步到网站的WEB-INF/classes下面)建立struts.xml

    <!DOCTYPE struts PUBLIC

            "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

            "http://struts.apache.org/dtds/struts-2.0.dtd">

     

    <struts>

        <include file="struts-default.xml" />

    </struts>

    Spring的默认配置文件是WEB-INF/applicationContext.xml,目前其内容很简单,我们只是把strutsBean放进来,如下:

    映射的规则:beanname属性必须等于struts-config.xml里面定义的actionpath属性,class就是这个bean的类action.LoginAction

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

    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd"> 

     

    <beans>

      <!-- Action Bean , 对应的部分 struts-config.xml form-bean and action-mappings -->

      <bean name="/login" class="action.LoginAction " singleton="false">

      

      </property>

      </bean>

     

    </beans>

     

    现在在WebContent下面建立success时重定向的目标success.html,方法和index.jsp类似,但选择THML类型,随便输入内容以便测试。这时候strutsSpring就简单的连接起来了。先停掉刚才运行起来的Tomcat,重新启动,运行index.jsp,点击网页中的按钮<添加>,看看有什么效果。

    现在,然我们简略描述一下数据和请求的流程。

    点击<添加>index.jsp的这个表单发送的请求是login.do(<form name="userInfoForm" action="login.do" method="post">),请求被传给后台,生成了doertest(处理*.do的请求)集合的一个servlet,然后传到path/loginaction,被Springorg.springframework.web.struts.DelegatingActionProxy处理,该类找到name是/login的Bean,转交处理权,等待结果。这个Bean就是我们的action.LoginAction。我们的execute中返回一个forward是"success"对应的网页,就是success.html。所以……,你已经看到了,struts和spring已经联系起来了。OK!

     

    下面我们需要把hibernate整合进来了,本来考虑到例子的简单性,打算用更简单的类,但既然用三者整合,就是要有良好的设计。我们需要以下几个层次的设计:表现层,业务层,持久层。表现层就是网页;表现层和业务层之间的接口就是网页和action的接口,由struts处理了;业务层包括业务逻辑和事务管理等,由Spring管理,我们只是建立具体处理对象;业务层和持久层之间由数据访问对象DAO处理,持久层交给hibernate处理。贯穿这些层的是领域对象(domain object),即表示现实世界的对象(base object),如订单对象,人物信息对象等等。现在看看我们需要的剩余设计结构。

    业务层:放进包service

    数据访问对象放进包dao

    持久层:hibernate

    领域对象:放进包bo

    既然领域对象是最基本的对象,我们就得首先建立,本例中,可以借助HibernateSynchronizer生成:

    首先在mysql中创建表

    CREATE TABLE `userinfo` (                                                                                                                                                    

                `id` int(11) primary key auto_increment,                                                                                                                                      

                `username` varchar(20) default NULL,                                                                                                                                        

                `Password` varchar(20) default NULL                                                                                                                                      

              )

    Eclipse中,建立hibernatemap文件:右键点击WEB-INF(或其他目录都可,后面会提到如何使用该文件),选择newàother,在弹出窗口中选择Hibernate Mapping File。在弹出窗口输入url,用户名和密码后点击Refresh,可以看到你选择的数据库的表,选中userinfo表。输入包bo,用来保存从数据库提取的领域对象。在Properties中将Id generator改为native

    HibernateSynchronizer将在WEB-INF下生成Uerinfo.hbm.xml文件。

    右键点击该文件,选择Hibernate SynchronizeràSynchronize Files。将自动生成bo.base.BaseUserinfobo.Userinfo类。这两个就是领域对象。工具正好啊!

     

    现在bo包里面的对象自动生成了。

    下面建立dao包中对象dao.UserinfoDAO

    package dao;

    import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

    import bo.Userinfo;

    //从HibernateDaoSupport继承,从而可以使用getHibernateTemplate().save保存数据。

    public class UserinfoDAO extends HibernateDaoSupport {

     

        public void save(Userinfo userinfo) {

           System.out.println("saved!");

           getHibernateTemplate().save(userinfo);

        }

     

    }

     

    再建立service包中的业务对象,service.UserinfoService

    package service;

    import dao.UserinfoDAO;

    import bo.Userinfo;

    package service;

    public class LoginService {

        private UserinfoDAO userinfoDAO;

     

        public UserinfoDAO getUserinfoDAO() {

           System.out.println("shit");

           return userinfoDAO;

        }

     

        public void setUserinfoDAO(UserinfoDAO userinfoDAO) {

           System.out.println("LoginService:setAdminDAO");

           this.userinfoDAO = userinfoDAO;

        }

     

        public void saveinfo(Userinfo userinfo) {

             //进行相关业务处理,比如validate之类的。

           userinfoDAO.save(userinfo);

        }

    }

     

    好了,所有我们应该建立的对象都生成了,现在把hibernate整合进来再进行一些后续处理。

    首先,在applicationContext.xml文件中加入必需的Bean定义,成为如下内容,注意其中注释。

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

    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd"> 

     

    <beans>

      <!-- Action Bean , 对应的部分 struts-config.xml form-bean and action-mappings -->

      <bean name="/login" class="action.LoginAction" singleton="false">

      <!-- property是该bean的属性,如下面的property,在类LoginAction 中必有字段定义LoginService loginService;和getLoginService()以及setLoginService方法-->

      <property name="loginService">

        <ref bean="loginService" />

      </property>

     

      </bean>

     

     <!-- 定义DBCP的数据库连接属性,该数据源会被hibernate使用,DBCP是连接池开源包,其中的url,username,password需要替换成你的数据库访问属性 -->

     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

      <property name="driverClassName">

       <value>com.mysql.jdbc.Driver</value>

      </property>

      <property name="url">

       <value>jdbc:mysql://localhost/mysql</value>

      </property>

      <property name="username">

       <value>root</value>

      </property>

      <property name="password">

       <value>doerliu</value>

      </property>

     </bean>

     

     <!-- 配置sessionFactory, 为Hibernate配置属性  -->

     <bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

      <property name="dataSource">

       <ref local="dataSource" />

      </property>

      <property name="mappingResources">

       <list>

        <!—Hibernate的map 文件在这里配置了,注意文件的相对位置。 -->

        <value>../Userinfo.hbm.xml</value>

       </list>

      </property>

      <property name="hibernateProperties">

       <props>

        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>

        <prop key="hibernate.show_sql">true</prop>

       </props>

      </property>

     </bean>

     

     <!-- 业务层的事务管理由该bean管理-->

     <bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager">

      <property name="sessionFactory">

       <ref local="sessionFactory" />

      </property>

     </bean>

     

     <!-- 事务处理环境(代理)配置,为业务处理LoginService定义一个事务处理*****-->

     <bean id="userDAOProxy"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

      <property name="transactionManager">

       <ref bean="transactionManager" />

      </property>

      <property name="target">

       <ref local="loginService" />

      </property>

      <property name="transactionAttributes">

       <props>

        <prop key="save*">PROPAGATION_REQUIRED</prop>

        <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>

        <prop key="is*">PROPAGATION_REQUIRED,readOnly</prop>

       </props>

      </property>

     </bean>

     

     <!-- 业务处理Bean定义 -->

     <bean id="loginService" class="service.LoginService">

      <property name="userinfoDAO">

       <ref bean="userinfoDAO" />

      </property>

     </bean>

     

     <!-- 数据访问对象的Bean -->

     <bean id="userinfoDAO" class="dao.UserinfoDAO">

      <property name="sessionFactory"><ref local="sessionFactory"/></property>

     </bean>

     

    </beans>

     

    最后,LoginAction可以处理请求并和业务层进行交流了。因此需要增加实质性内容:

    package action;

     

    /* @sample for training.

     * @author doer.liu@utstarcom

     * @date 2007-7-30

     */

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

     

    import org.apache.struts.action.ActionForm;

    import org.apache.struts.action.ActionForward;

    import org.apache.struts.action.ActionMapping;

    import org.springframework.web.struts.ActionSupport;

     

    import bo.Userinfo;

     

    import forms.UserInfoForm;

     

    import service.LoginService;

     

    //我们继承spring提供的Action衍生类org.springframework.web.struts.ActionSupport

    public class LoginAction extends ActionSupport {

     

          LoginService loginService;

     

          public ActionForward execute(ActionMapping mapping, ActionForm form,

                     HttpServletRequest request, HttpServletResponse response) {

               UserInfoForm userInfoForm = (UserInfoForm) form;

               String username = userInfoForm.getUsername();

               String password = userInfoForm.getPassword();

               Userinfo userinfo = new Userinfo();

               userinfo.setUsername(username);

               userinfo.setPassword(password);

               loginService.saveinfo(userinfo);// 保存前台的数据,插入数据库

     

               return mapping.findForward("success"); //返回页。

     

          }

     

          public LoginService getLoginService() {

               return loginService;

          }

     

          public void setLoginService(LoginService loginService) {

               System.out.println("setLoginService=" + loginService);

               this.loginService = loginService;

          }

    }

     

    Ok!整个流程到此就走通了。运行看看吧。还有什么说的呢,动手开始吧,在此基础上不断修改测试,再参考相关文档,一切都将越来越简单!——有问题,看日志!

        附件是导出的WAR文件,其中lib已被清空,只要加入文中列出的lib文件即可运行(可以将WAR导入eclipse,或者将war文件放到Tomcat的webaspps下)http://dl2.csdn.net/down4/20070806/06111224839.war

          当然这个例子为了清晰起见,在各种模式,java编程习惯上是不合适的,比如应该面向接口编程,而不是统统拿类,拿对象来处理。应该定义如ILoginService, ILoginDAO等接口,使得系统更灵活,更易移植。当然为了说明,我们这样做是可以原谅的,但工作中切记不要只图简单!否则还不如不用这种高级优秀的构架,因为你一用就把它破坏殆尽了。

  • 相关阅读:
    饿了么P7级前端工程师进入大厂的面试经验
    前端程序员面试的坑,简历写上这一条信息会被虐死!
    这次来分享前端的九条bug吧
    移动端开发必会出现的问题和解决方案
    创建一个dynamics 365 CRM online plugin (八)
    创建一个dynamics 365 CRM online plugin (七)
    创建一个dynamics 365 CRM online plugin (六)
    创建一个dynamics 365 CRM online plugin (五)
    使用User Primary Email作为GUID的问题
    怎样Debug Dynamics 365 CRM Plugin
  • 原文地址:https://www.cnblogs.com/whtydn/p/4972246.html
Copyright © 2011-2022 走看看