分类目录归档:程序生活

Program Life – Web

【转】使用Maven搭建Struts2+Spring3+Hibernate4的整合开发环境

做 了三年多的JavaEE开发了,在平时的JavaEE开发中,为了能够用最快的速度开发项目,一般都会选择使用 Struts2,SpringMVC,Spring,Hibernate,MyBatis这些开源框架来开发项目,而这些框架一般不是单独使用的,经常是 Struts2+Spring3+Hibernate、SpringMVC+Spring+Hibernate、 SpringMVC+Spring+Mybatis这几种组合中的一种,也就是多个框架配合起来使用。今天来总结一下如何使用Maven搭建 Struts2+Spring3+Hibernate4的整合开发环境。

一、建立Maven工程

第一步:

 

第二步:

 

第三步:

 

创建好的项目如下图所示:

 

第四步:

 

注意:这里的JDK要选择默认的,这样别人在使用的时候,如何JDk不一致的话也不会出错,如下图所示:

 

第五步:

创建Maven标准目录

src/main/java

    src/main/resources

    src/test/java

    src/test/resources

 

第六步:

发布项目:Maven install

清除编译过的项目:Maven clean

 

Maven install命令执行结果如下:

 

OK,Maven工程创建成功!

二、搭建Spring3开发环境

2.1、下载Spring3需要的jar包

1.spring-core

    2.spring-context

    3.spring-jdbc

    4.spring-beans

    5.spring-web

    6.spring-expression

    7.spring-orm

在pom.xml中编写Spring3需要的包,maven会自动下载这些包以及相关的依赖jar包。

复制代码
 1 <!-- spring3 -->
 2         <dependency>
 3             <groupId>org.springframework</groupId>
 4             <artifactId>spring-core</artifactId>
 5             <version>3.1.2.RELEASE</version>
 6         </dependency>
 7         <dependency>
 8             <groupId>org.springframework</groupId>
 9             <artifactId>spring-context</artifactId>
10             <version>3.1.2.RELEASE</version>
11         </dependency>
12         <dependency>
13             <groupId>org.springframework</groupId>
14             <artifactId>spring-jdbc</artifactId>
15             <version>3.1.2.RELEASE</version>
16         </dependency>
17         <dependency>
18             <groupId>org.springframework</groupId>
19             <artifactId>spring-beans</artifactId>
20             <version>3.1.2.RELEASE</version>
21         </dependency>
22         <dependency>
23             <groupId>org.springframework</groupId>
24             <artifactId>spring-web</artifactId>
25             <version>3.1.2.RELEASE</version>
26         </dependency>
27         <dependency>
28             <groupId>org.springframework</groupId>
29             <artifactId>spring-expression</artifactId>
30             <version>3.1.2.RELEASE</version>
31         </dependency>
32         <dependency>
33             <groupId>org.springframework</groupId>
34             <artifactId>spring-orm</artifactId>
35             <version>3.1.2.RELEASE</version>
36         </dependency>
复制代码

2.2、编写Spring配置文件

在src/main/resources目录下创建一个spring.xml文件,如下图所示:

 

spring.xml文件的内容如下:

按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

在src/main/resources目录下创建一个config.properties文件,如下图所示:

 

config.properties文件主要是用来编写一些系统的配置信息,例如数据库连接信息,config.properties文件中的内容暂时先不编写,等整合到Hibernate时再编写具体的数据库连接信息。

2.3、编写单元测试

首先,在src/main/java中创建me.gacl.service包,在包中编写一个 UserServiceI 接口,如下图所示:

 

代码如下:

复制代码
 1 package me.gacl.service;
 2 
 3 /**
 4  * 测试
 5  * @author gacl
 6  *
 7  */
 8 public interface UserServiceI {
 9 
10     /**
11      * 测试方法
12      */
13     void test();
14 }
复制代码

然后,在src/main/java中创建me.gacl.service.impl包,在包中编写UserServiceImpl实现类,如下图所示:

 

代码如下:

复制代码
 1 package me.gacl.service.impl;
 2 
 3 import org.springframework.stereotype.Service;
 4 
 5 import me.gacl.service.UserServiceI;
 6 //使用Spring提供的@Service注解将UserServiceImpl标注为一个Service
 7 @Service("userService")
 8 public class UserServiceImpl implements UserServiceI {
 9 
10     @Override
11     public void test() {
12         System.out.println("Hello World!");
13     }
14 
15 }
复制代码

进行单元测试时需要使用到Junit,所以需要在pom.xml文件中添加Junit的jar包描述,如下:

复制代码
1         <!-- Junit -->
2         <dependency>
3             <groupId>junit</groupId>
4             <artifactId>junit</artifactId>
5             <version>4.12</version>
6             <scope>test</scope>
7         </dependency>
复制代码

<scope>test</scope>这里的test表示测试时编译src/main/test文件夹中的文件,等发布的时候不编译。 最后,在src/main/test中创建me.gacl.test包,在包中编写 TestSpring类,如下图所示:

 

代码如下:

复制代码
 1 package me.gacl.test;
 2 
 3 import me.gacl.service.UserServiceI;
 4 
 5 import org.junit.Test;
 6 import org.springframework.context.ApplicationContext;
 7 import org.springframework.context.support.ClassPathXmlApplicationContext;
 8 
 9 public class TestSpring {
10 
11     @Test
12     public void test(){
13         //通过spring.xml配置文件创建Spring的应用程序上下文环境
14         ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring.xml");
15         //从Spring的IOC容器中获取bean对象
16         UserServiceI userService = (UserServiceI) ac.getBean("userService");
17         //执行测试方法
18         userService.test();
19     }
20 }
复制代码

JUnit Test运行,结果如图所示:

 

2.4、在web.xml中配置Spring监听器

复制代码
1 <!-- Spring监听器 -->
2     <listener>
3         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
4     </listener>
5     <!-- Spring配置文件位置 -->
6     <context-param>
7         <param-name>contextConfigLocation</param-name>
8         <param-value>classpath:spring.xml</param-value>
9     </context-param>
复制代码

在tomcat服务器中进行测试,先执行【Maven install】命令发布项目,然后将SSHE项目部署到tomcat服务器,最后启动tomcat服务器

 

tomcat服务器启动的过程中没有出现报错,输入地址:http://localhost:8080/SSHE/ 能够正常进行访问,就说明Spring3的开发环境搭建成功,如下图所示:

 

测试通过,Spring3开发环境搭建成功!

三、搭建Struts2开发环境并整合Spring3

3.1、下载Struts2需要的jar包

1.strtus2-core

2.struts2-spring-plugin(struts2和Spring整合时需要使用到的插件)

3.struts2-convention-plugin(使用了这个插件之后,就可以采用注解的方式配置Struts的Action,免去了在struts.xml中的繁琐配置项)

4.struts2-config-browser-plugin(config-browser-plugin插件不是必须的,但是使用了这个插件之后,就可以很方便的浏览项目中的所有action及其与 jsp view的映射)

在pom.xml文件中编写Struts2所需要的jar包,Maven会自动下载这些包

复制代码
 1 <!-- Struts2的核心包 -->
 2         <dependency>
 3             <groupId>org.apache.struts</groupId>
 4             <artifactId>struts2-core</artifactId>
 5             <version>2.3.16</version>
 6             <!--
 7             这里的 exclusions 是排除包,因为 Struts2中有javassist,Hibernate中也有javassist,
 8             所以如果要整合Hibernate,一定要排除掉Struts2中的javassist,否则就冲突了。
 9             <exclusions>
10                 <exclusion>
11                     <groupId>javassist</groupId>
12                     <artifactId>javassist</artifactId>
13                 </exclusion>
14             </exclusions> 
15             -->
16         </dependency>
17         <!-- convention-plugin插件,使用了这个插件之后,就可以采用注解的方式配置Action -->
18         <dependency>
19             <groupId>org.apache.struts</groupId>
20             <artifactId>struts2-convention-plugin</artifactId>
21             <version>2.3.20</version>
22         </dependency>
23         <!--config-browser-plugin插件,使用了这个插件之后,就可以很方便的浏览项目中的所有action及其与 jsp view的映射 -->
24         <dependency>
25             <groupId>org.apache.struts</groupId>
26             <artifactId>struts2-config-browser-plugin</artifactId>
27             <version>2.3.20</version>
28         </dependency>
29         <!-- Struts2和Spring整合插件 -->
30         <dependency>
31             <groupId>org.apache.struts</groupId>
32             <artifactId>struts2-spring-plugin</artifactId>
33             <version>2.3.4.1</version>
34         </dependency>
复制代码

 

3.2、编写Struts.xml配置文件

在src/main/resources目录下创建一个struts.xml文件,如下图所示:

 

struts.xml文件中的内容如下:

按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

3.3、在web.xml中配置Struts2的过滤器

复制代码
 1 <!-- Struts2的核心过滤器配置 -->
 2     <filter>
 3         <filter-name>struts2</filter-name>
 4         <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
 5     </filter>
 6     <!-- Struts2过滤器拦截所有的.action请求 -->
 7     <filter-mapping>
 8         <filter-name>struts2</filter-name>
 9         <url-pattern>*.action</url-pattern>
10     </filter-mapping>
复制代码

 3.4、编写测试

首先,在src/main/java中创建me.gacl.action包,在包中编写一个 TestAction类,如下图所示:

 

代码如下:

复制代码
 1 package me.gacl.action;
 2 
 3 import me.gacl.service.UserServiceI;
 4 
 5 import org.apache.struts2.convention.annotation.Action;
 6 import org.apache.struts2.convention.annotation.Namespace;
 7 import org.apache.struts2.convention.annotation.ParentPackage;
 8 import org.springframework.beans.factory.annotation.Autowired;
 9 
10 @ParentPackage("basePackage")
11 @Action(value="strust2Test")//使用convention-plugin插件提供的@Action注解将一个普通java类标注为一个可以处理用户请求的Action,Action的名字为struts2Test
12 @Namespace("/")//使用convention-plugin插件提供的@Namespace注解为这个Action指定一个命名空间
13 public class TestAction {
14     
15     /**
16      * 注入userService
17      */
18     @Autowired
19     private UserServiceI userService;
20 
21     /**
22      * http://localhost:8080/SSHE/strust2Test!test.action
23      * MethodName: test
24      * Description: 
25      * @author xudp
26      */
27     public void test(){
28         System.out.println("进入TestAction");
29         userService.test();
30     }
31 }
复制代码

这里使用@Autowired注解将userService注入到UserAction中。

测试Struts2的开发环境是否搭建成功,先执行【Maven install】操作,然后部署到tomcat服务器,最后启动tomcat服务器运行,

输入访问地址:http://localhost:8080/SSHE/strust2Test!test.action,访问结果如下:

 

测试通过,Struts2的开发环境搭建并整合Spring成功!这里提一下遇到的问题,我执行完Maven install命令之后,重新发布到tomcat服务器运行,第一次运行时出现了找不到action的404错误,后来就先执行Maven clean,然后clean一下项目,再执行Maven install命令重新编译项目,然后再发布到tomcat服务器中运行,这次就可以正常访问到action了,使用Maven总是会遇到一些奇怪的问 题,好在凭借着一些平时积累的解决问题的经验把问题解决了。

四、搭建Hibernate4开发环境并整合Spring3

4.1、下载Hibernate4需要的jar包

1.hibernate-core

在pom.xml文件中编写Hibernate4所需要的jar包,Maven会自动下载这些包。

复制代码
1 <!-- hibernate4 -->
2         <dependency>
3             <groupId>org.hibernate</groupId>
4             <artifactId>hibernate-core</artifactId>
5             <version>4.1.7.Final</version>
6         </dependency>
复制代码

 

 

  注意:一定要排除掉Struts2中的javassist,否则就冲突了。

4.2、添加数据库驱动jar包

我们知道,Hibernate是用于和数据库交互的,应用系统所有的CRUD操作都要通过Hibernate来完成。既然要连接数据库,那么就要使用到 相关的数据库驱动,所以需要加入数据库驱动的jar包,根据自身项目使用的数据库在pom.xml文件中编写相应的数据库驱动jar:

MySQL数据库驱动jar:

按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

SQLServer数据库驱动jar:

复制代码
1 <!-- SQLServer数据库驱动包 -->
2         <dependency>
3             <groupId>net.sourceforge.jtds</groupId>
4             <artifactId>jtds</artifactId>
5             <version>1.3.1</version>
6         </dependency>
复制代码

这里要说一下使用Maven管理Oracle JDBC驱动的问题了,正常情况下,Maven在下载 oracle数据库驱动时会出错,如下图所示:

 

这是由于Oracle授权问题,Maven3不提供Oracle JDBC driver,为了在Maven项目中应用Oracle JDBC driver,必须手动添加到本地仓库。

解决办法:先从网上下载Oracle的驱动包,然后通过Maven命令放到本地库中去:

安装命令:

mvn install:install-file -Dfile={Path/to/your/ojdbc.jar} -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0.1.0 -Dpackaging=jar

例如把位于F:\oracle驱动\ojdbc6.jar添加到本地仓库中

执行命令:

mvn install:install-file -Dfile=F:/oracle驱动/ojdbc6.jar -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0.1.0 -Dpackaging=jar

如下图所示:

然后在pom.xml文件中编写ojdbc6.jar包的<dependency>信息,如下所示:

复制代码
1 <!--Oracle数据库驱动包,针对Oracle11.2的ojdbc6.jar -->
2         <dependency>  
3              <groupId>com.oracle</groupId>  
4              <artifactId>ojdbc6</artifactId>  
5              <version>11.2.0.1.0</version>  
6         </dependency>
复制代码

由于我们已经将ojdbc6.jar包加入到本地仓库中了,因此这次可以正常使用针对Oracle数据库的驱动包了。如下图所示:

 

4.3、添加数据库连接池jar包

在平时开发中,我们一般都会使用数据库连接池,应用系统初始化时,由数据库连接池向数据库申请一定数量的数据库连接,然后放到一个连接池中,当需要操作 数据库时,就从数据库连接池中取出一个数据库连接,通过从连接池中获取到的数据库连接对象连接上数据库,然后进行CRUD操作,关于数据库连接池的选择, 常用的有DBCP,C3P0和Druid,这里我们使用Druid作为我们的数据库连接池。这三种连接池各自有各自的特点,自己熟悉哪个就用哪个,萝卜白 菜,各有所爱。

在pom.xml文件中编写Druid的jar包,Maven会自动下载,如下:

复制代码
1 <!--Druid连接池包 -->
2         <dependency>
3             <groupId>com.alibaba</groupId>
4             <artifactId>druid</artifactId>
5             <version>1.0.12</version>
6         </dependency>
复制代码

 4.4、添加aspectjweaver包

使用Spring的aop时需要使用到aspectjweaver包,所以需要添加aspectjweaver包,在pom.xml文件中添加aspectjweaver的jar包,Maven会自动下载,如下:

复制代码
1 <!--aspectjweaver包 -->
2         <dependency>
3             <groupId>org.aspectj</groupId>
4             <artifactId>aspectjweaver</artifactId>
5             <version>1.8.5</version>
6         </dependency>
复制代码

4.5、编写连接数据库的配置信息

之前我们在src/main/resources目录下创建了一个config.properties文件,里面的内容是空的,现在我们就在这个config.properties文件中编写连接数据库需要使用到的相关信息,如下所示:

复制代码
 1 #hibernate.dialect=org.hibernate.dialect.OracleDialect
 2 #driverClassName=oracle.jdbc.driver.OracleDriver
 3 #validationQuery=SELECT 1 FROM DUAL
 4 #jdbc_url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
 5 #jdbc_username=gacl
 6 #jdbc_password=xdp
 7 
 8 hibernate.dialect=org.hibernate.dialect.MySQLDialect
 9 driverClassName=com.mysql.jdbc.Driver
10 validationQuery=SELECT 1
11 jdbc_url=jdbc:mysql://localhost:3306/sshe?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
12 jdbc_username=root
13 jdbc_password=XDP
14 
15 #hibernate.dialect=org.hibernate.dialect.SQLServerDialect
16 #driverClassName=net.sourceforge.jtds.jdbc.Driver
17 #validationQuery=SELECT 1
18 #jdbc_url=jdbc:jtds:sqlserver://127.0.0.1:1433/sshe
19 #jdbc_username=sa
20 #jdbc_password=123456
21 
22 #jndiName=java:comp/env/dataSourceName
23 
24 hibernate.hbm2ddl.auto=update
25 hibernate.show_sql=true
26 hibernate.format_sql=true
复制代码

4.6、编写Hibernate与Spring整合的配置文件

在src/main/resources目录下新建一个spring-hibernate.xml文件,如下图所示:

 

spring-hibernate.xml文件的内容如下:

复制代码
  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
  3 http://www.springframework.org/schema/beans 
  4 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
  5 http://www.springframework.org/schema/tx 
  6 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
  7 http://www.springframework.org/schema/aop 
  8 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
  9 ">
 10 
 11     <!-- JNDI方式配置数据源 -->
 12     <!-- 
 13     <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
 14          <property name="jndiName" value="${jndiName}"></property> 
 15     </bean> 
 16     -->
 17 
 18     <!-- 配置数据源 -->
 19     <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
 20         <property name="url" value="${jdbc_url}" />
 21         <property name="username" value="${jdbc_username}" />
 22         <property name="password" value="${jdbc_password}" />
 23 
 24         <!-- 初始化连接大小 -->
 25         <property name="initialSize" value="0" />
 26         <!-- 连接池最大使用连接数量 -->
 27         <property name="maxActive" value="20" />
 28         <!-- 连接池最大空闲 -->
 29         <property name="maxIdle" value="20" />
 30         <!-- 连接池最小空闲 -->
 31         <property name="minIdle" value="0" />
 32         <!-- 获取连接最大等待时间 -->
 33         <property name="maxWait" value="60000" />
 34 
 35         <!-- <property name="poolPreparedStatements" value="true" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="33" /> -->
 36 
 37         <property name="validationQuery" value="${validationQuery}" />
 38         <property name="testOnBorrow" value="false" />
 39         <property name="testOnReturn" value="false" />
 40         <property name="testWhileIdle" value="true" />
 41 
 42         <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
 43         <property name="timeBetweenEvictionRunsMillis" value="60000" />
 44         <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
 45         <property name="minEvictableIdleTimeMillis" value="25200000" />
 46 
 47         <!-- 打开removeAbandoned功能 -->
 48         <property name="removeAbandoned" value="true" />
 49         <!-- 1800秒,也就是30分钟 -->
 50         <property name="removeAbandonedTimeout" value="1800" />
 51         <!-- 关闭abanded连接时输出错误日志 -->
 52         <property name="logAbandoned" value="true" />
 53 
 54         <!-- 监控数据库 -->
 55         <!-- <property name="filters" value="stat" /> -->
 56         <property name="filters" value="mergeStat" />
 57     </bean>
 58 
 59     <!-- 配置hibernate session工厂 -->
 60     <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
 61         <property name="dataSource" ref="dataSource" />
 62         <property name="hibernateProperties">
 63             <props>
 64                 <!-- web项目启动时是否更新表结构 -->
 65                 <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
 66                 <!-- 系统使用的数据库方言,也就是使用的数据库类型 -->
 67                 <prop key="hibernate.dialect">${hibernate.dialect}</prop>
 68                 <!-- 是否打印Hibernate生成的SQL到控制台 -->
 69                 <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
 70                 <!-- 是否格式化打印出来的SQL -->
 71                 <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
 72             </props>
 73         </property>
 74 
 75         <!-- 自动扫描注解方式配置的hibernate类文件 -->
 76         <property name="packagesToScan">
 77             <list>
 78                 <value>me.gacl.model</value>
 79             </list>
 80         </property>
 81 
 82         <!-- 自动扫描hbm方式配置的hibernate文件和.hbm文件 -->
 83         <!-- 
 84         <property name="mappingDirectoryLocations">
 85             <list>
 86                 <value>classpath:me/gacl/model/hbm</value>
 87             </list>
 88         </property>
 89          -->
 90     </bean>
 91 
 92     <!-- 配置事务管理器 -->
 93     <bean name="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
 94         <property name="sessionFactory" ref="sessionFactory"></property>
 95     </bean>
 96 
 97     <!-- 注解方式配置事物 -->
 98     <!-- <tx:annotation-driven transaction-manager="transactionManager" /> -->
 99 
100     <!-- 拦截器方式配置事物 -->
101     <tx:advice id="transactionAdvice" transaction-manager="transactionManager">
102         <tx:attributes>
103             <!-- 以如下关键字开头的方法使用事物 -->
104             <tx:method name="add*" />
105             <tx:method name="save*" />
106             <tx:method name="update*" />
107             <tx:method name="modify*" />
108             <tx:method name="edit*" />
109             <tx:method name="delete*" />
110             <tx:method name="remove*" />
111             <tx:method name="repair" />
112             <tx:method name="deleteAndRepair" />
113             <!-- 以如下关键字开头的方法不使用事物 -->
114             <tx:method name="get*" propagation="SUPPORTS" />
115             <tx:method name="find*" propagation="SUPPORTS" />
116             <tx:method name="load*" propagation="SUPPORTS" />
117             <tx:method name="search*" propagation="SUPPORTS" />
118             <tx:method name="datagrid*" propagation="SUPPORTS" />
119             <!-- 其他方法不使用事物 -->
120             <tx:method name="*" propagation="SUPPORTS" />
121         </tx:attributes>
122     </tx:advice>
123     <!-- 切面,将事物用在哪些对象上 -->
124     <aop:config>
125         <aop:pointcut id="transactionPointcut" expression="execution(* me.gacl.service..*Impl.*(..))" />
126         <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
127     </aop:config>
128     
129 </beans>
复制代码

4.7、编写单元测试代码

1、在MySQL中创建sshe数据库

SQL脚本:

CREATE DATABASE SSHE;

2、在src/main/java中创建me.gac.model包,在包中编写一个 User类,如下图所示:

 

代码如下:

复制代码
 1 package me.gacl.model;
 2 
 3 import java.util.Date;
 4 
 5 import javax.persistence.Column;
 6 import javax.persistence.Entity;
 7 import javax.persistence.Id;
 8 import javax.persistence.Table;
 9 import javax.persistence.Temporal;
10 import javax.persistence.TemporalType;
11 
12 @Entity
13 @Table(name = "T_USER", schema = "SSHE")
14 public class User implements java.io.Serializable {
15 
16     // Fields
17     private String id;
18     private String name;
19     private String pwd;
20     private Date createdatetime;
21     private Date modifydatetime;
22 
23     // Constructors
24 
25     /** default constructor */
26     public User() {
27     }
28 
29     /** minimal constructor */
30     public User(String id, String name, String pwd) {
31         this.id = id;
32         this.name = name;
33         this.pwd = pwd;
34     }
35 
36     /** full constructor */
37     public User(String id, String name, String pwd, Date createdatetime, Date modifydatetime) {
38         this.id = id;
39         this.name = name;
40         this.pwd = pwd;
41         this.createdatetime = createdatetime;
42         this.modifydatetime = modifydatetime;
43     }
44 
45     // Property accessors
46     @Id
47     @Column(name = "ID", unique = true, nullable = false, length = 36)
48     public String getId() {
49         return this.id;
50     }
51 
52     public void setId(String id) {
53         this.id = id;
54     }
55 
56     @Column(name = "NAME",nullable = false, length = 100)
57     public String getName() {
58         return this.name;
59     }
60 
61     public void setName(String name) {
62         this.name = name;
63     }
64 
65     @Column(name = "PWD", nullable = false, length = 32)
66     public String getPwd() {
67         return this.pwd;
68     }
69 
70     public void setPwd(String pwd) {
71         this.pwd = pwd;
72     }
73 
74     @Temporal(TemporalType.TIMESTAMP)
75     @Column(name = "CREATEDATETIME", length = 7)
76     public Date getCreatedatetime() {
77         return this.createdatetime;
78     }
79 
80     public void setCreatedatetime(Date createdatetime) {
81         this.createdatetime = createdatetime;
82     }
83 
84     @Temporal(TemporalType.TIMESTAMP)
85     @Column(name = "MODIFYDATETIME", length = 7)
86     public Date getModifydatetime() {
87         return this.modifydatetime;
88     }
89 
90     public void setModifydatetime(Date modifydatetime) {
91         this.modifydatetime = modifydatetime;
92     }
93 }
复制代码

3、在src/main/java中创建me.gacl.dao包,在包中编写一个 UserDaoI接口,如下图所示:

 

代码如下:

复制代码
 1 package me.gacl.dao;
 2 
 3 import java.io.Serializable;
 4 
 5 import me.gacl.model.User;
 6 
 7 public interface UserDaoI {
 8 
 9     /**
10      * 保存用户
11      * @param user
12      * @return
13      */
14     Serializable save(User user); 
15 }
复制代码

在src/main/java中创建me.gacl.dao.impl包,在包中编写 UserDaoImpl实现类,如下图所示:

 

代码如下:

复制代码
 1 package me.gacl.dao.impl;
 2 
 3 import java.io.Serializable;
 4 
 5 import org.hibernate.SessionFactory;
 6 import org.springframework.beans.factory.annotation.Autowired;
 7 import org.springframework.stereotype.Repository;
 8 
 9 import me.gacl.dao.UserDaoI;
10 import me.gacl.model.User;
11 
12 @Repository("userDao")
13 public class UserDaoImpl implements UserDaoI {
14     
15     /**
16      * 使用@Autowired注解将sessionFactory注入到UserDaoImpl中
17      */
18     @Autowired
19     private SessionFactory sessionFactory;
20     
21     @Override
22     public Serializable save(User user) {
23         return sessionFactory.getCurrentSession().save(user);
24     }
25 }
复制代码

这里使用@Repository(“userDao”)注解完成dao注入, 使用@Autowired注解将sessionFactory注入到UserDaoImpl中。

4、在之前创建好的UserServiceI接口中添加一个save方法的定义,如下:

复制代码
 1 package me.gacl.service;
 2 
 3 import java.io.Serializable;
 4 import me.gacl.model.User;
 5 
 6 /**
 7  * 测试
 8  * @author gacl
 9  *
10  */
11 public interface UserServiceI {
12 
13     /**
14      * 测试方法
15      */
16     void test();
17     
18     /**
19      * 保存用户
20      * @param user
21      * @return
22      */
23     Serializable save(User user); 
24 }
复制代码

5、在UserServiceImpl类中实现save方法,如下:

复制代码
 1 package me.gacl.service.impl;
 2 
 3 import java.io.Serializable;
 4 
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.stereotype.Service;
 7 
 8 import me.gacl.dao.UserDaoI;
 9 import me.gacl.model.User;
10 import me.gacl.service.UserServiceI;
11 //使用Spring提供的@Service注解将UserServiceImpl标注为一个Service
12 @Service("userService")
13 public class UserServiceImpl implements UserServiceI {
14 
15     /**
16      * 注入userDao
17      */
18     @Autowired
19     private UserDaoI userDao;
20     
21     @Override
22     public void test() {
23         System.out.println("Hello World!");
24     }
25 
26     @Override
27     public Serializable save(User user) {
28         return userDao.save(user);
29     }
30 }
复制代码

6、在src/main/test下的me.gacl.test包中编写 TestHibernate类,代码如下:

复制代码
 1 package me.gacl.test;
 2 
 3 import java.util.Date;
 4 import java.util.UUID;
 5 
 6 import me.gacl.model.User;
 7 import me.gacl.service.UserServiceI;
 8 
 9 import org.junit.Before;
10 import org.junit.Test;
11 import org.springframework.context.ApplicationContext;
12 import org.springframework.context.support.ClassPathXmlApplicationContext;
13 
14 public class TestHibernate {
15 
16     private UserServiceI userService;
17     
18     /**
19      * 这个before方法在所有的测试方法之前执行,并且只执行一次
20      * 所有做Junit单元测试时一些初始化工作可以在这个方法里面进行
21      * 比如在before方法里面初始化ApplicationContext和userService
22      */
23     @Before
24     public void before(){
25         ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring.xml","spring-hibernate.xml"});
26         userService = (UserServiceI) ac.getBean("userService");
27     }
28     
29     @Test
30     public void testSaveMethod(){
31         //ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring.xml","spring-hibernate.xml"});
32         //UserServiceI userService = (UserServiceI) ac.getBean("userService");
33         User user = new User();
34         user.setId(UUID.randomUUID().toString().replaceAll("-", ""));
35         user.setName("孤傲苍狼");
36         user.setPwd("123");
37         user.setCreatedatetime(new Date()); 
38         userService.save(user);
39     }
40 }
复制代码

执行Junit单元测试,如下所示:

测试通过,再看看sshe数据库,如下图所示:

 

Hibernate在执行过程中,先帮我们在sshe数据库中创建一张t_user表,t_user的表结构根据User实体类中的属性定义来创建的,然后再将数据插入到t_user表中,如下图所示:

 

到此,Hibernate4开发环境的搭建并且与Spring整合的工作算是全部完成并且测试通过了。

五、三大框架综合测试

经过前面的四大步骤,我们已经成功地搭建好基于struts2+hibernate4+spring3这三大框架的整合开发环境,下面我们来综合测试一下三大框架配合使用进行开发的效果。

5.1、完善web.xml文件中的配置

复制代码
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
 5     http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
 6     <display-name></display-name>
 7     <welcome-file-list>
 8         <welcome-file>index.jsp</welcome-file>
 9     </welcome-file-list>
10 
11     <!-- Spring监听器 -->
12     <listener>
13         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
14     </listener>
15     <!-- Spring配置文件位置 -->
16     <context-param>
17         <param-name>contextConfigLocation</param-name>
18         <param-value>classpath:spring.xml,classpath:spring-hibernate.xml</param-value>
19     </context-param>
20     
21     <!-- 防止spring内存溢出监听器 -->
22     <listener>
23         <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
24     </listener>
25     
26     <!-- openSessionInView配置 -->
27     <filter>
28         <filter-name>openSessionInViewFilter</filter-name>
29         <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
30         <init-param>
31             <param-name>singleSession</param-name>
32             <param-value>true</param-value>
33         </init-param>
34     </filter>
35     <filter-mapping>
36         <filter-name>openSessionInViewFilter</filter-name>
37         <url-pattern>*.action</url-pattern>
38     </filter-mapping>
39     
40     <!-- Struts2的核心过滤器配置 -->
41     <filter>
42         <filter-name>struts2</filter-name>
43         <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
44     </filter>
45     <!-- Struts2过滤器拦截所有的.action请求 -->
46     <filter-mapping>
47         <filter-name>struts2</filter-name>
48         <url-pattern>*.action</url-pattern>
49     </filter-mapping>
50     
51     <!-- druid监控页面,使用${pageContext.request.contextPath}/druid/index.html访问 -->
52     <servlet>
53         <servlet-name>druidStatView</servlet-name>
54         <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
55     </servlet>
56     <servlet-mapping>
57         <servlet-name>druidStatView</servlet-name>
58         <url-pattern>/druid/*</url-pattern>
59     </servlet-mapping>
60 </web-app>
复制代码

5.2、编写测试代码

在TestAction类中添加一个saveUser方法,如下:

复制代码
 1 package me.gacl.action;
 2 
 3 import java.util.Date;
 4 import java.util.UUID;
 5 
 6 import me.gacl.model.User;
 7 import me.gacl.service.UserServiceI;
 8 
 9 import org.apache.struts2.convention.annotation.Action;
10 import org.apache.struts2.convention.annotation.Namespace;
11 import org.apache.struts2.convention.annotation.ParentPackage;
12 import org.springframework.beans.factory.annotation.Autowired;
13 
14 @ParentPackage("basePackage")
15 @Action(value="strust2Test")//使用convention-plugin插件提供的@Action注解将一个普通java类标注为一个可以处理用户请求的Action
16 @Namespace("/")//使用convention-plugin插件提供的@Namespace注解为这个Action指定一个命名空间
17 public class TestAction {
18     
19     /**
20      * 注入userService
21      */
22     @Autowired
23     private UserServiceI userService;
24 
25     /**
26      * http://localhost:8080/SSHE/strust2Test!test.action
27      * MethodName: test
28      * Description: 
29      * @author xudp
30      */
31     public void test(){
32         System.out.println("进入TestAction");
33         userService.test();
34     }
35     
36     /**
37      * http://localhost:8080/SSHE/strust2Test!saveUser.action
38      */
39     public void saveUser(){
40         User user = new User();
41         user.setId(UUID.randomUUID().toString().replaceAll("-", ""));
42         user.setName("xdp孤傲苍狼");
43         user.setPwd("123456");
44         user.setCreatedatetime(new Date()); 
45         userService.save(user);
46     }
47 }
复制代码

执行【Maven install】操作,重新编译和发布项目,在执行【Maven install】操作之前,需要修改TestSpring这个测试类中的test方法的代码,如下:

复制代码
 1 package me.gacl.test;
 2 
 3 import me.gacl.service.UserServiceI;
 4 
 5 import org.junit.Test;
 6 import org.springframework.context.ApplicationContext;
 7 import org.springframework.context.support.ClassPathXmlApplicationContext;
 8 
 9 public class TestSpring {
10 
11     @Test
12     public void test(){
13         //通过spring.xml配置文件创建Spring的应用程序上下文环境
14         //ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring.xml");
15         /**
16          *因为已经整合了Hibernate,UserServiceImpl类中使用到了userDao,
17          *userDao是由spring创建并且注入给UserServiceImpl类的,而userDao中又使用到了sessionFactory对象
18          *而创建sessionFactory对象时需要使用到spring-hibernate.xml这个配置文件中的配置项信息,
19          *所以创建Spring的应用程序上下文环境时,需要同时使用spring.xml和spring-hibernate.xml这两个配置文件
20          *否则在执行Maven install命令时,因为maven会先执行test方法中的代码,而代码执行到
21          *UserServiceI userService = (UserServiceI) ac.getBean("userService");
22          *这一行时就会因为userDao中使用到sessionFactory对象无法正常创建的而出错,这样执行Maven install命令编译项目时就会失败!
23          *
24          */
25         ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring.xml","spring-hibernate.xml"});
26         //从Spring的IOC容器中获取bean对象
27         UserServiceI userService = (UserServiceI) ac.getBean("userService");
28         //执行测试方法
29         userService.test();
30     }
31 }
复制代码

每次执行【Maven install】命令时都会执行Junit单元测试中的代码有时候感觉挺累赘的,有时候往往就是因为一些单元测试中的代码导致【Maven install】命令编译项目失败!

将编译好的项目部署到tomcat服务器中运行,输入地址:http://localhost:8080/SSHE/strust2Test!saveUser.action进行访问,如下所示:

 

访问action的过程中没有出现错误,并且后台也没有报错并且打印出了Hibernate执行插入操作时的SQL语句,如下所示:

 

这说明三大框架整合开发的测试通过了。以上就是使用使用Maven搭建Struts2+Spring3+Hibernate4的整合开发环境的全部内容。

maven配置strtus2+hibernate时javassist包冲突的问题

 

用maven的话,strtus2包会自动下载javassist组件包,但是hibernate也会自动下载javassist组件包,这两个jar包有冲突,需要排除掉struts2自动下载的那个,方法就是在struts2的依赖里面排除掉javassist。

<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-core</artifactId>
    <version>${struts2-version}</version>
    <exclusions>
        <exclusion>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
        </exclusion>
    </exclusions>
</dependency>

JetBrain 系列注册码(WebStorm 、PhpStorm 等)

webStorm :

UserName:William
===== LICENSE BEGIN =====
45550-12042010
00001SzFN0n1bPII7FnAxnt0DDOPJA
INauvJkeVJBuE5bqLEznccE4tet6tr
RiyoMxDK8oDY93tx!ipPyGmqYYeWxS
===== LICENSE END =====
UserName:Microsoft
===== LICENSE BEGIN =====
44827-12042010
00001xZTATXBeJGHI0CFFRIdOKjhQ7
eiwIjgK7qohmwGSZRUK!lINYbpNQKk
5AtC16jzcy6KWlkBBjTZXwL8fnebTM
===== LICENSE END =====
UserName:ChinaRed
===== LICENSE BEGIN =====
41806-12042010
000006gMpIpRoMPJdqqPfxIYyr5UPx
fTuYnZxklVYrNOZUHL6YnHTAUM4zqe
qNrt8QzsZERfO”XiHa802ejK9GtcSj
===== LICENSE END =====

rubyMine :
UserName:William
===== LICENSE BEGIN =====
73770-12042010
00000LsPnluU7HZh4TgJoxNDbnCr!T
0yDfranplDJF4ESFHxfhN6dMBEogxt
S!qZH7LvIjab”9qbXrSfL9NitEBODm
===== LICENSE END =====
UserName:Microsoft
===== LICENSE BEGIN =====
05071-12042010
00001DGDB7Ih6YT6ApG0Uh4wxMwJqf
UjDDJvi5mX0yJS!72q8ZrLhKQfusV”
NVSB9iV!lO1tRbt265″z0vZJBwpl!9
===== LICENSE END =====
UserName:ChinaRed
===== LICENSE BEGIN =====
26405-12042010
00001cYtAkKGNyQA7Er6A9e4oS2Y”I
fK”d”APYe591kwLAHVZ7ieFmfoTKTS
90BTaTdrTg36JEivKlxfVaDszIkWuM
===== LICENSE END =====

phpStorm :
UserName:William
===== LICENSE BEGIN =====
56731-12042010
00001F”L73xP5zfOyL58″Vg0hu”R8S
!aPyCtkqgqc5fEvdQLlLs5a9gzvAcu
!2Gb!gp9kfKoAp1e81dVuhM”a8OJ4v
===== LICENSE END =====
UserName:Microsoft
===== LICENSE BEGIN =====
06656-12042010
00002NFsdQw64GSoAeS1!oxQRM!H8k
Rh3soGkXar1UJa27G0Gx3uz4FEq6Fb
CW09ado0neq”3gqd3lZ8KnE303G”MP
===== LICENSE END =====
UserName:ChinaRed
===== LICENSE BEGIN =====
83865-12042010
00001jJvs5lu13QqsSxk1XXwwpiGL1
4GGM”RKB0xBaYtK6Uh4NVG26″TBhTA
HNKvcsV38NwMho1Wdy75KY61SwSdVQ
===== LICENSE END =====

pyCharm :
UserName:William
===== LICENSE BEGIN =====
43064-12042010
00002qm1!PHwV!dC19Cvu04E6IXZJ9
GN”RaF03!bwPE”x3RZbg7ctJld7yZl
XkVf40g3JJGG4Ibbbg4″HQPwWJWSFU
===== LICENSE END =====
UserName:Microsoft
===== LICENSE BEGIN =====
77380-12042010
000017q0LbsOLEIcYF3VRZszWAYE”K
CYfpWmqrUTJy”ROE03pXMWLZ6Z9jbh
cccsmd3P32vdo!L4tnEkp1jrOuySvx
===== LICENSE END =====
UserName:ChinaRed
===== LICENSE BEGIN =====
42852-12042010
00000zw1KaqXWsbN7MiExhdvN!PIjf
ZDCOi0vxBEGX9QDUYIyvr0768OloCU
FUZ4Evyh4lNEFKRDEVnKye9W2DYxPp
===== LICENSE END =====

前端JS框架一览

KIssy
开发公司:阿里巴巴。
框架介绍:KISSY是一款跨终端、模块化、高性能、使用简单的 JavaScript 框架。除了完备的工具集合如 DOM、Event、Ajax、Anim 等,它还提供了经典的面向对象、动态加载、性能优化解决方案。作为一款全终端支持的 JavaScript 框架,KISSY 为移动终端做了大量适配和优化,让你的程序在全终端均能流畅运行。
了解:阿里巴巴公司在2008年时开发,当时考虑到公共开源框架如jquery和YUI2有比较多的冗余API进而自助开发的js框架。其主要基于YUI2,糅合了jquery风格的API,支持模块化异步加载。目前框架分为核心core、外层API,同时提供了供mobile使用的轻量级核心库。性能、稳定性、便利性尚无太多业界反应,有听说过不少关于兼容性问题。

er
开发公司:百度。
框架介绍:ER 是一个富浏览器端web应用的框架,适用于并能很方便地构建一个整站式的AJAX web应用。
了解:主要是从设计模式上延伸出js框架,主要思想是MVC的实现,数据加载和绑定机制。

JX
开发公司:腾讯(WEB QQ)
框架介绍:一个类似 Google Closure Library 的 Web 前端开发框架,服役于 WebQQ 等大规模的 WebApp
核心底层 – 纯Js底层功能封装/代码组织/无缝接入其它js库 – [完成]
基础扩展 – 跨浏览器封装/工具函数/设计模式相关 – [完成]
UI 基础控件 – 按钮/面板/窗口/树形列表/Tab/lightbox/widgets…
实时动画系统 – 实时定时器/关键帧动画/加速度公式/物理引擎/声音控制器…
游戏引擎 – 角色控制/地图系统/游戏异步通讯系统/寻路算法/键盘控制/人工智能/…
了解:业界已经有很多优秀的局部框架,比如JSON、Mini Selector Engine、SWFObject等等,作为一个综合性的Web前端框架直接做兼容即可,没有再写一遍的必要了,所以JX框架针对出色的局部框架做了良好的兼容工作。

seajs
开发者:前淘宝UED,现支付宝前端工程师玉伯
框架介绍:简单友好的模块定义规范:SeaJS 遵循CMD规范,可以像Node.js一般书写模块代码。自然直观的代码组织方式:依赖的自动加载、配置的简洁清晰,可以让我们更多地享受编码的乐趣。(类似require.js的思想)
了解:使用sea.js的公司有不少,如:朋友网、腾讯微博、支付宝、有道云笔记、爱奇艺、淘宝网等。seajs遵循CMD规范,而requirejs遵循AMD规范。

jquery
Query使用户能更方便地处理HTML(标准通用标记语言下的一个应用)、events、实现动画效果,并且方便地为网站提供AJAX交互。jQuery还有一个比较大的优势是,它的文档说明很全,而且各种应用也说得很详细,同时还有许多成熟的插件可供选择。jQuery能够使用户的html页面保持代码和html内容分离,也就是说,不用再在html里面插入一堆js来调用命令了,只需定义id即可。

zepto
Zepto是一个专为移动端新浏览器打造的一个5-10k的js库,同时也是一个精简化的jquery核心库。 知道jquery开发就知道zepto的使用。

requirejs
RequireJS会让你以不同于往常的方式去写JavaScript。你将不再使用script标签在HTML中引入JS文件,以及不用通过script标签顺序去管理依赖关系。遵循AMD规范。jquery、dojo等框架也都使用了requirejs来加载模块。

EJS
EJS是一个JavaScript模板库,用来从JSON数据中生成HTML字符串。与最初的JavaScript相比较,一些不太了解你的代码的人可以更容易地通过EJS模板代码看得懂你的代码。

coffee
CoffeeScript is a little language that compiles into JavaScript. Underneath that awkward Java-esque patina, JavaScript has always had a gorgeous heart. CoffeeScript is an attempt to expose the good parts of JavaScript in a simple way.

spinejs
Spine 可让你使用 MVC 的框架思路来开发Web应用。
文档太少,单纯MVC模式可以简单的实现,其本身也是要借助EJS来实现MVC。

blackbone
Backbone 为复杂Javascript应用程序提供模型(models)、集合(collections)、视图(views)的结构。其中模型用于绑定键值数据和自定义事件;集合附有可枚举函数的丰富API; 视图可以声明事件处理函数,并通过RESTful JSON接口连接到应用程序。
1. 将数据和界面很好的分离开来。
2. 将事件的绑定很好的剥离出来,便于管理和迭代。
3. 使得Javascript程序的模块化更加清晰、明了。

extjs/Sencha
Sencha Touch 是全球领先的应用程序开发框架,其设计旨在充分
利用HTML5、CSS3 和Javascript 来实现最高级别的功能、灵活性和优化。Sencha Touch 是针对下一代具有触摸屏设备的跨平台框架。

实现微信浏览器内打开App Store链接

微信浏览器是不支持打开App Store 页面的,不知道微信为什么这么做。比如你页面写 <a href=”http://itunes.apple.com/us/app/id399608199″>download</a> ,在微信浏览器点击链接是没有反应的,但是如果是其他的链接地址,比如百度那就没有问题

 

后来我发现如果你在微信官方后台编辑图文,把原文链接写为:http://itunes.apple.com/us/app/id399608199 ,那就可以打开了,发现微信页面的“查看原文”是一个function,如下

[code lang=”js”]
function viewSource() {
var redirectUrl = sourceurl.indexOf(‘://’) < 0 ? ‘http://’ + sourceurl: sourceurl;
//redirectUrl = http://itunes.apple.com/us/app/id399608199
redirectUrl = ‘http://’ + location.host + ‘/mp/redirect?url=’ + encodeURIComponent(sourceurl);
//此处是关键,redirectUrl = http://mp.weixin.qq.com/mp/redirect?url=http%3A%2F%2Fitunes.apple.com%2Fus%2Fapp%2Fid399608199%23rd
var opt = {
url: ‘/mp/advertisement_report’ + location.search + ‘&report_type=3&action_type=0&url=’ + encodeURIComponent(sourceurl) + ‘&uin=’ + uin + ‘&key=’ + key + ‘&__biz=’ + biz + ‘&r=’ + Math.random(),
type: ‘GET’,
async: !1
};
return tid ? opt.success = function(res) {
try {
res = eval(‘(‘ + res + ‘)’);
} catch(e) {
res = {};
}
res && res.ret == 0 ? location.href = redirectUrl: viewSource();
}: (opt.timeout = 2000, opt.complete = function() {
location.href = redirectUrl;
}),
ajax(opt),
!1;
}
[/code]

真正的url是:http://mp.weixin.qq.com/mp/redirect?url=http%3A%2F%2Fitunes.apple.com%2Fus%2Fapp%2Fid399608199%23rd

看来微信允许打开mp.weixin.qq.com这个host下的网页,然后用js再打开真正的页面。

现在简单了,将页面的代码写为:<a href=”http://mp.weixin.qq.com/mp/redirect?url=http%3A%2F%2Fitunes.apple.com%2Fus%2Fapp%2Fid399608199%23rd”>download</a>,在微信浏览器内可以打开app store的地址了。

通过In house方式发布ipa(就是通过safari浏览器直接安装)

1.首先要将你的项目进行打包

点击查看原图

 

2.在弹出的窗口中选择Distribute..

点击查看原图

 

3.然后选择打包的方式

点击查看原图

 

4.然后系统会要求对你的应用进行签名,选择一个证书开始签名(工程大的话这个步骤要很久)

点击查看原图

 

5.最后选择保存打包后的ipa路径,手别太快,如果已经点保存的同学要从头来过了,关键就是这一步一定要选择底部的Save for Enterpirse Distribution复选框

点击查看原图

 

6.选中Save for Enterpirse Distribution复选框后会下拉出对话窗口,这里只要填写必填字段就行了

Application URL:填写你要通过web发布的ipa文件的URL下载地址

比如:http://www.wanggq.cn/test/test.ipa

Title比较无所谓,正常点的话就填你的项目名称

比如:test

点击查看原图

 

7.最后点save,打包的过程就算完成了,到你选择的保存路径下看看,应该会生成两个文件一个ipa和一个plist文件,比如项目名称叫test,那么目录下应该有test.ipa和test.pist两个文件

 

8.将ipa和plist文件一起上传到你的web服务器,放在你在上一步填写的Application URL对应的目录中,在本例中你应该放在web服务器的/test目录下.

 

9.在打算通过web发布你的应用之前先要做个网页,不然用户没有页面显示的话也不知道点哪下载(其实直接把生成的plist文件通过指定协议的url地址直接告诉客户就能下载了,不过通用的方式还是做个web页面),以下是个简单的下载页面的

[code]
<pre><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=320, height=460, user-scalable=no,
initial-scale=1.0" />
<title>Install Dev App</title>
</head>

<br/><br/><br/>
<body>
<div align="center">
<a href="itms-services://?action=download-manifest&url=http://www.wanggq.cn/test/test.plist" style="color:orange; font-size:24px">
Install the test App</a>
</div>
<p />

</body>
<br />
<br />

</html>
[/code]

注意:其中的链接地址可以自己修改成你的plist文件存放的位置,但一定是itms-services://?action=download- manifest打头再加上plist文件的url地址的格式,itms-services:这个是特殊的http协议,目前只有safari浏览器支持 (只要是支持这个协议的浏览器应该都能下载安装吧)

显示的效果如图:

点击查看原图

 

10.点击之后系统就会自动开始下载安装ipa了

iOS 开发者企业计划 – In-House证书

http://www.apple.com.cn/developer/support/ios/enterprise.html

什么人应该申请 iOS 开发者企业计划?

如开发者希望在 iPhone 或者 iPod touch 上创建专有的内用应用程序,且其公司雇员不下 500 人,则应申请 iOS 开发者企业计划。在注册企业计划时,开发者需要向苹果公司提供 D-U-N-S 号码。

没有 D-U-N-S 号码的企业能否注册 iOS 开发者企业计划?

注册 iOS 开发者企业计划需要 D-U-N-S 号码。只有先从 Dun & Bradstreet 取得 D-U-N-S 号码才能注册该计划。

注册 iOS 开发者企业计划之后,我能否在 App Store 发布应用程序?

只 有以个人或公司名义注册 iOS 开发者计划才能在 App Store 发布应用程序。如果您注册了 iOS 开发者企业计划,则只能通过 Ad Hoc 发布将应用程序发布给组织的会员或员工使用。 如果您的公司已注册企业计划而又希望通过 App Store 向客户发布应用程序,则需以个人或者公司名义注册加入 iOS 开发者计划

我是一名开发人员,希望为我的客户创建机构内部使用的应用程序。我能否加入 iOS 开发者企业计划以达成这一构想?

不行。因为 iOS Developer Enterprise 应用于开发和发布机构内部使用的私有应用程序,而且程序仅能供给您公司(注册企业计划的公司)的雇员使用。

http://blog.csdn.net/kmyhy/article/details/6418280

企业版IDP,即iOS Development Enterprise Program。注意是$299/Year那种,并不是$99/Year的那种。

这种方式的IDP其最大的好处在于:可以发布“In House”应用。

这种应用使用一种叫做“In House Distribution Provisioning Profile”的文件进行发布,不能发布到Apple Shop进行销售,也不需要经过Apple的评审。你可以把“In House”应用通过任何方式发布给你的企业员工、用户及其他你认可的任何人,尤其适合于企业应用的开发。

网上关于个人版/公司版IDP申请流程,以及将应用发布到苹果商店的介绍有很多,但关于企业版IDP以及In House应用的讨论非常之少(尤其国内)。下面,笔者将对这两方面的问题进行一个全面细致的介绍。

1、申请Apple ID

这个步骤就不说了。

2、申请邓白氏编码

邓氏编码是美国联邦政府推荐使用的企业机构编码。可以看成是美国版的“组织机构代码”,只不过已经得到了联合国、澳大利亚政府、欧盟及美国政府的承认,成为了全球企业标准。

苹果公司需要邓氏编码才能申请IDP企业版。这倒不是对国内企业的歧视,而是出于的美国商业习惯。在美国所有的采购合同和商业合同中,都会要求供应商提供一个DUNS(邓氏编码),否则对方可能不会跟你签合同。因为所有的美国企业都使用D&B公司的数据库,这样才能保证所有企业编码不会重复。

申请邓氏编码在D&B公司的网站即可:

http://www.dunsregistered.com/

中文网站“华夏邓白氏”:

http://dnbregistered.com.cn/

在网站上提交注册申请后,等待1-2天,对方人员会跟你联系(Email)。

原来以为申请会很麻烦(交流上),但实际上是由华夏邓白氏的中籍文员跟你联系的。

邓白氏注册服务有几个版本,收费情况也不一样。笔者一开始收到的邮件是“实地核实”的版本,报价15200/2年。

后来经与北京苹果联系,只需要购买最基本的“标准版”即可,报价8600元/2年, 有网友说2000-3000元/年,现在看来是不可能了 ,在这个物价飞涨的年代:-(。

联系时一定要强调是购买标准版服务(最便宜),否则你可能会花冤枉钱。

收到邮件后,把申请表、协议打印出来,填好并加盖公章,然后加上企业营业执照副本、扫描为电子的,发给对方邮箱。

其实还有一个就是汇款水单(小票),需要发送给对方。这一步其实可以省略。笔者申请时并没有email汇款水单 ,只要对方确认汇款到帐即可。

大约5-7天后,对方发来第2封邮件,告诉你贵公司的编码。此外还可以在网站上安装一个邓白氏电子标识——在网页上嵌入指定脚本,则会在页面上显示一个D&B图标,点击图标自动链接到D&B的网站并呈现你们公司的电子注册信息。

3、申请IDP企业版

登录苹果开发者网站iOS Dev Center,申请Apple Developer Program,只不过这次选择的是iOS Enterprise Program链接(在页面底部)。

点击Apply Now,下一页Continue,下一页选择“Use an existing Apple ID”,Continue。

下一页,输入你的Apple ID、密码登录。

后面就是确认注册协议和填写你的公司资料了(英文)。内容最好同邓氏的一样,否则对方会打电话来确认,需要更改。

填写完公司资料,还要填写委托人联系资料。注意委托人应该有代表公司签字的授权(公司认可,他们会在电话里确认)。

提交资料后,可以在邮箱里收到苹果的邮件,内容大概是感谢你提交了申请,申请的编号是多少,公司名称、邮箱地址等等,如果你想看评审流程,可以登录Member Center。

接下来就是等待苹果的电话了。

这个过程大概要2-3天,对方会安排懂中文的人员来电话,如果没什么问题,接下来(电话之后几分钟)会收到苹果的第2封邮件,大意是要你点击邮件中的链接,查看一个协议(我不知道这个协议和第1个协议有什么不同,反正我直接点同意了)。

协议同意后,显示一个页面,大意是你所申请的国家不支持在线购买苹果产品(在线支付),需要你下载一个pdf的purchase form:

iOS 开发者企业计划 - 云水禅心 - 云水禅心

 

将它打印出来,根据要求填好,然后传真给苹果。

注意,国内信用卡支持美元支付的一般是Visa卡(如招行)和Master卡(如交行),一定要找那种卡上印有“Visa”或”Master”标志的信用卡。

Cvc2 code是指信用卡背面的那串数字(7位)的末3位。

信用卡地址写申请信用卡时登记的地址。

因为公司的传真机无法发送国际传真,我将purchase form扫描后发给了亚洲苹果     chinadev@asia.apple.com , 请其转交给 Billing 团队。

亚洲苹果几分钟后自动回复了一封邮件,并在信中附了一个业务流水号: Follow-Up: 149653 xxx

下次再给亚洲苹果联系时,可以附上这个业务流水号。

然后3-5 个工作日后,约早上6点多收到扣费成功短信(信用卡提供的功能)。登录邮箱后,果然收到了苹果的2封email,1封是发票,上面有你的发票号码,单位报 账的时候把这封邮件内容打印出来就可以了。另1封是激活邮件,告诉你现在你的idp帐号已经生效了,你点击那个“login now”按钮可以登录到member center,这时可以看到你的developer program overview的状态已经改变。同时,Peoples中会包含一个成员,这个成员就是你注册IDP时所绑定的开发者帐号(Apple ID),同时也是该IDP的Team Admin或Agent。

4、制作iOS 开发者证书

4.1 在本机生成证书请求CSR

打开“钥匙串”应用程序,修改偏好设置如下图所示:

iOS 开发者企业计划 - 云水禅心 - 云水禅心

选择菜单“钥匙串访问 -> 证书助理-> 从证书颁发机构求证书”.

注意,如果此时密钥中的某个私钥处于选中状态,则菜单会变为“钥匙串访问->证书助理->用<私钥>从证书颁发机构求证书”,这样制作出来的CSR是无效的。

iOS 开发者企业计划 - 云水禅心 - 云水禅心

输入你的email地址和名字。确保email地址和名字与你注册为iOS开发者时登记的相一致。

勾选Saved to Disk(保存到磁盘)及Let me specify key pair information(指定密钥对信息),然后点Continue。

iOS 开发者企业计划 - 云水禅心 - 云水禅心

当选择了Let me specify key pair之后,会要求你指定文件保存位置。接下来按下图所示指定密钥对信息:

iOS 开发者企业计划 - 云水禅心 - 云水禅心

Continue,即生成了CSR文件。一旦生成CSR,在“登录”钥匙串中会生成一对密钥对(一个私钥,一个公钥)。你可以在钥匙串的密钥栏中查看。

4.2 提交CSR文件

用企业版IDP绑定的Apple ID( 跟制作CSR时要求输的的可能不一致,这里是注册企业版时绑定的iOS开发者帐号,即Agent)登录iOS Provision Portal 。

 

点击“Certificates-> Development” 中的 “Add Certificate”按钮。

iOS 开发者企业计划 - 云水禅心 - 云水禅心

接下来点击最下面的“Choose file”按钮,选择所生成的CSR文件,然后点 “Submit”。如果密钥长度未设置未2048,Portal会拒绝CSR。提交CSR 后,Team管理员(Agent)会收到一封提醒邮件,主题为 Certificate Request Requires Your Approval,提示你需要去同意该CSR。此时Agent需要登录Portal去同意该CSR。但实际上,Agent也可能根本不需要去点“同 意”,Portal几秒钟后就自动同意了——笔者遇到的情况就是这样的。

4.3 下载并安装开发者证书

如果机器上未安装WWDR证书,请点击 “Certificate-> Distribution”中的链接“Saved Linked File to Downloads” ,以下载WWDR证书,并通过双击WWDR证书进行安装。

在“Certificate -> Development”中, 在Your Certificate下会列出当前有效的开发者证书。 点击“Download”,即可下载到本机。下载后双击,即可安装到本机。 可以在钥匙串“证书”一栏中查看到导入的开发证书。

Team 成员只能下载自己的iOS开发证书。Team管理员有权下载所有成员的公有证书。苹果不接受CSR中的私钥。私钥仅对创建者有效,并且必须存储在系统钥匙串里。

4.4   保存私钥并迁移到其他系统

如果你在多台电脑上进行开发或者重装系统,那么把私钥存储在安全的地方是件很重要的事情。如果没有私钥,你无法在Xcode中签名代码并进行真机调试。

钥匙串在生成CSR时,就会在“登录”钥匙串中创建一个私钥。该私钥和你的用户帐号绑定,如果重装OS导致该私钥遗失,则该私钥无法再次生成。如果你想在多台电脑上开发和调试,你必须将私钥导入到每一台机器上:

在钥匙串访问程序中,选择登录钥匙串的“密钥”。可以看到有许多密钥对,选择与你的开发者证书相对应的私钥(还记得创建CSR 时要你输入的邮箱地址和名字吗?那个名字会显示在私钥的名字上)。然后选择菜单“文件->导出项目…”,将私钥保存为.p12格式 (Personal Information Exchange)。当提示输入密码时,设置一个密码并记住它,它会在导入.p12文件时使用。现住,你可以把.p12文件拷贝到其他机器上并双击它进行 安装,这时会提示你输入导出私钥时设置的密码。

5、设备IDs

所谓设备ID(device ID又称UDID)是Apple 设备上的40位16进制码,每台Apple设备的device ID都是唯一的,Apple以此来识别不同的iOS设备。

我们通过在Provision Portal中录入设备的device ID,可以允许开发者在指定真实设备上进行调试。在Provision Portal中最多允许输入100个device ID。

因此,录入device ID是后续制作Provision Profile的必需步骤(而Provision Profile又是真机调试的必需步骤)。

5.1 获取device ID

两种获取device ID的方式:

把Apple 设备(iPhone,iPod)连接电脑,打开Xcode的Orgnizer:

iOS 开发者企业计划 - 云水禅心 - 云水禅心

把Apple 设备(iPhone,iPod)连接电脑,打开iTunes:

iOS 开发者企业计划 - 云水禅心 - 云水禅心

那个40位16进制的数字就是device ID。

5.2 添加单个device ID

以Team管理员登录Provision Portal,点击Devices页面中的“Add Device”按钮,在其中输入:

Device Name:设备名称,输入一个描述该设备的名字。

UDID:即device ID。

点击提交即可。

iOS 开发者企业计划 - 云水禅心 - 云水禅心

6、创建App ID

App ID是识别不同应用程序的唯一编码。如果你的程序要连接Apple Push Notification服务(一种push通知),需要用到App ID。如果应用程序之间要共享钥匙串数据,也会用到App ID。总之,App ID在iOS设备上大量被使用。在这里App ID的最大用处是制作真机调试用的Provision Profile(它需要提供一个App ID)。

一个App ID有两部分构成:一个10位字符的Bundle Seed ID前缀,这个Bundle Seed ID由Apple分配,全球唯一,保证不会重复;一个Bundle Identifier后缀,这个Bundle Identifier由Team管理员指派,Apple建议用反域名规则命名这个Bundle Identifier。例如: 8E549T7128.com.apple.AddressBook.

如果你写了一系列应用程序,它们共用相同的钥匙串(如共用密码),或者根本就不使用钥匙串访问,你可以只创建一个App ID,所有的应用程序都使用以星号结尾的App ID。这个星号就是通配符,只能用于App ID最后一个字符。例如,这个App ID可以是: R2T24EVAEE.com.domainname.* 或者 R2T24EVAEE.*

6.1 创建App ID

以Agent或Team 管理员登录Provision Portal,点击“App ID”页面中的“New App ID”按钮。

iOS 开发者企业计划 - 云水禅心 - 云水禅心

App ID Name:给这个App ID一个名字。如果存在多个App ID,每个App ID需要一个易于识别的名称。

App ID:如前面所述,Bundle Seed ID是Apple分配的,其实这里只需要你输入Bundle Identifier。可以使用统配符*。

7、制作开发者Provision Profile

拥有了开发者证书(Development Certificate),只是表明你有权利在电脑上进行开发,在模拟器上运行程序,但你还不能在iPhone上运行你开发的程序。其实如果你只是在模拟 器上调试程序的话,要不要开发者证书都无所谓,因为证书只是用来代码签名(Code Sign)的,如果在模拟器上跑的话,你可以选择不签名(don’t code sign)。

如果要在真机上调试就不一样了。它需要一个Provision Profile,没有这个Provision Profile,苹果设备无法安装运行你开发的程序。这个Provision Profile中记录了一些信息:开发者证书、开发者Apple ID、一系列设备ID(开发者可以使用哪几部设备进行调试)。

7.1 创建开发者Provision Profile

以Agent登录Provision Portal,在“Provisioning->Development”,点击“New Profile”按钮。

Profile Name:输入Profile的名字,随意。

Certificate: 选择开发者证书。

App ID:选择一个App ID。

Devices:设备ID列表。

 

点击“Submit”,即会生成Development Provisioning Profile。

iOS 开发者企业计划 - 云水禅心 - 云水禅心

7.2 安装Development Provision Profile

所有Team成员都可以下载Development Provision Profile。但只有Profile中记录了设备ID的设备以及iOS开发者证书所指定的开发者能够使用这个Profile。

在Portal 的“Provisioning->Development”,点击某个profile右边的“download”按钮。下载profile后,将下 载到的文件拖拽到桌面Dock面板的Xcode图标上(或者直接拖到Xcode的Orgnizer中)。这会将profile文件拷贝 到~/Library/MobileDevice/Provisioning Profiles目录。

iOS 开发者企业计划 - 云水禅心 - 云水禅心

7.3 签名并调试

在Xcode中打开工程,选中 Target,打开info窗口,在Build面板中找到“Code Signing Identify”,打开并点击下面的“Any iOS Device” :

 

iOS 开发者企业计划 - 云水禅心 - 云水禅心

在弹出菜单菜单中选择你的签名,该签名应当和一个灰色的Profile 对应。这个Profile就是我们前面安装的Development Provision Profile。例如,我们在7.1中创建的Profile 的Profile Name为My First Development Provisioning Profile,那么我们选择的签名就是位于“My First Development Provisioning Profile”(显示为灰色)下面的Team Leader的开发证书。也就是说“My First Development Provisioning Profile”中绑定的开发证书是Team Leader签名的。

在Properties面板(其实就是info.plist中的内容),根据你的App ID设置你的Bundle Identifier。如果你的App ID是A1B2C3D4E5.com.domainname.applicationname( 我们在前面创建的App ID),那么Bundle Identifier可以是 com.domainname.applicationname 。如果App ID使用了通配符,比如 A1B2C3D4E5.com.domainname.* ,则Bundle Identifier可以是com.domainname.<任意字符>。

iOS 开发者企业计划 - 云水禅心 - 云水禅心

点击项目窗口左上角的下拉框,选择“ Device | Debug ”,然后点击“Build and Debug”按钮,编译并在真机上运行程序。

8、发布应用程序

发布应用程序需要使用发布证书(Distribution Certificate)。发布证书的制作,跟制作开发者证书的步骤是一样的,只不过使用的是Provision Portal的“Certificates->Distribution”功能。

把制作号的发布证书下载、安装到本机。

但是发布用的Provision Profile稍有不同。 企业版IDP只有两种发布方式:In House和Ad Hoc。两种Profile制作步骤稍有区别。 用In House方式发布是企业版IDP真正区别于其他版本的IDP所在。我们重点介绍In House方式的发布。

8.1 制作In House 方式的Destribution Provision Profile

以Team Admin登录Provision Portal,打开“Provisioning Distribution”页面。

 

iOS 开发者企业计划 - 云水禅心 - 云水禅心

Distribution Method:发布方式,选择In House。

Profile Name:Profile名称,用于区别多个Profile。

Distribution Certificate:选择要在Profile中绑定的发布证书。

App ID:指定一个已有的AppID。

Devices(optional):要绑定的device ID。由于In House方式可以在任何Apple 设备上发布,所以不需要设定Devices,这一项为空。

点击“Submit”,生成Profile。将Profile下载到本地进行安装。方法:把Profile文件拖拽到Dock上的Xcode图标。

8.2 制作Ad Hoc方式的Distribution Provision Profile

 

以Admin或Agent登录Provision Portal。 打开“Provisioning Distribution”页面。

iOS 开发者企业计划 - 云水禅心 - 云水禅心

与In House方式大同小异,只不过发布方式选择Ad Hoc,同在Devices(optional)栏勾选要绑定的device ID,最多可选择100个。

点击“Submit”,生成Profile。将Profile下载到本地进行安装。

8.3 编译In House发布版本

打开你的工程。在工程的info窗口的Configuration面板,从Configuration列表中选择Release,点击 “Duplicate”按钮,将复制出来的Configuration改名为Distribution。

iOS 开发者企业计划 - 云水禅心 - 云水禅心

 

打开Target的Info窗口,在Build面板,将Configuration修改为Distribution:

 

 

iOS 开发者企业计划 - 云水禅心 - 云水禅心

 

点击“Any iOS Device”,在弹出菜单中选择对应Profile下对应的发布证书,这个Profile应该就是前面6.1中制作并安装的In House 方式制作的Distribution Provision Profile(还记得Profile Name吗?):

 

iOS 开发者企业计划 - 云水禅心 - 云水禅心

 

切换到Properties面板,在Identifier栏输入Bundle Identifier。该Bundle Identifier应根据App ID填写。

在工程窗口,选择当前配置为Distribution:

iOS 开发者企业计划 - 云水禅心 - 云水禅心

 

点击“File->New File”菜单,然后选择“Code Signing->Entitlements”:

iOS 开发者企业计划 - 云水禅心 - 云水禅心

 

打开Entitlements.plist,反选“get-task-allow”,保存。 该选项允许其他进程(比如调试器)附加到你的程序,当然,在发布阶段,这个选项应当设置为false。

注意,根据Apple的文档,iOS 4.0/Xcode3.2.3之后创建的Entitlements文件不再包括get-task-allow选项——默认情况下,如果Entitlements中没有get-task-allow选项,则不允许附加进程(即无法调试)。

在调试配置下运行时,你不需要Entitlements 文件,因此是允许附加进程的(可以进行调试)。但是有时候,你已经有了一个Entitlements文件(比如你已经运行过Distribution配 置),如果你再次运行Debug配置,则程序无法启动,因为get-task-allow默认为false(iOS 4.0及Xcode3.2.3以后)。这种情况下,请手动添加一个boolean类型的get-task-allow键,并设置为false。

iOS 开发者企业计划 - 云水禅心 - 云水禅心

 

再次打开Target的Build设置面板。在“Code Signing Entitlements”中,输入Entitlements.plist的文件名。

iOS 开发者企业计划 - 云水禅心 - 云水禅心

 

点击“Build”编译。注意:你需要准备一个57*57像素的图标,iPhone和iPod会在主屏上显示该图标。

选中工程文件夹Products下面的.app文件,然后点击Action下拉菜单中的Reveal in Finder。

8.4 制作安装包

iPhone 应用程序的安装文件主要有两种:.ipa格式和.app格式。前者是以.ipa为后缀名的文件(已经包含了ProvisionProfile文件),后者 实际是以.app为后缀的文件夹(不包含ProvisionProfile文件)。因此,前者可以直接发布给用户进行安装,而后者需要和 ProvisionProfile文件打包在一起进行发布。

8.4.1 制作ipa包

当把.app 文件安装到iTunes的资料库之后,应用程序就是以.ipa的方式存在了。在“资料库->应用程序”中选中这个应用程序图标,右键,选择“在 Finder中显示”,然后就可以在Finder中把这个.ipa文件拷贝出来了。.ipa文件即可用后面的方法进行安装。

8.4.2 制作rar/zip包

把编译后的.app 文件和ProvisionProfile文件一起压缩为rar/zip文件,即可发送给其他人进行安装,或者发布到网络上以供下载。注意,不要使用Mac 自带的归档工具。因为windows使用ANSI编码而Mac使用Unicode编码,二者互不兼容,这样使用归档工具压缩出来的rar/zip包无法在 windows下解开。你可以使用开源的压缩工具keka:

http://www.kekaosx.com/release/Keka-0.1.4.2.dmg

keka能制作在windows下兼容的压缩包。解压缩后的文件可用后面介绍的2种方法之一进行安装。如果一种方法不能安装,可换用另一种方法。

 

 

8.5 安装应用程序

Ad Hoc或In House发布的应用程序,可以将.app与Provision Profile文件打包在一起发送给用户。用户可以用两种方式安装:使用iTunes,或者使用iPhone配置使用工具。

8.5.1 使用iTunes

用户将压缩包中的.app和Provision Profile文件拖到iTunes的“资料库->应用程序”下,然后和iPhone/iPod进行同步。

8.5.2 使用iPhone配置实用工具

iPhone配置工具是完全免费的,你可以从这里下载:

http://support.apple.com/kb/DL926?viewlocale=zh_CN

安装后会在“应用程序/实用工具”中生成一个快捷方式“iPhone配置实用工具”。

同样,将iPhone/iPod 连上电脑,打开“iPhone配置实用工具”,将.app和Provision Profile文件拖放到“iPhone配置实用工具”的“资料库->应用程序”下,然后选中你的iPhone/iPod,在右边“安装或删除应用 程序列表”中,点击某个应用程序右边的“安装”按钮进行安装。

 

9、问题及错误

如果Xcode出现Code sign错误:

Code Sign Errors: profile doesn’t match any valid certificate/private key pair in the default keychain

同时在Organizer中出现下列提示:

A valid signing identity matching this profile could not be found in your keychain

则需要把钥匙串中的所有证书和密钥删除,然后重新请求证书、修复provision profile、下载并安装,一般可以得到解决。

iPhone企业版开发者申请小记

http://b.imi.im/?p=348

前面介绍过了 个人版的申请,开这里,我们继续企业版的申请 :)
请注意这个企业版并不是大家理解的大家一起开发用的公司帐号,不是Company,是Enterprise,或者叫 in-house, 此证书不需要经过App Store批准就可安装到用户手机上,或者说是个无限制版的AdHoc

下面是企业应用的一些细节问题:

1. 需要证明您的企业有500名以上员工

2. AdHoc版本只能发给最多100个人,并且需要知道手机的UDID, 企业应用程序没有限制,也不需要手机ID

3. 可以用Private API !因为没人审核你,娃哈哈!!无法无天了

4. 用户安装非常简单,只需要从网络或者邮件里下载这个程序和想要的预置文件,通过iTunes软件打开后同步iPhone即可安装。任何人都可以安装运行,所以要确保此程序存放的位置安全。

5. 用户安装后,程序可以自己升级而不需要重新给每个用户发放新版本。(相当于企业自己有一个app store)

6. 申请此资格需要299美金

7. 企业DUNS编码 (在线填写)
注: 企业可通过D&B网站http://www.dnb.com进行申请,中国企业的话可直接至其中文网站进行邓氏编码注册,其中国公司为上海华夏邓白氏商业信息咨询有限公司(http://www.huaxiadnb.com/chinese) 为方便起见可直接向D&B中国公司联系进行申请,需要提供一些资料,并支付费用(一千到两千RMB左右)。请注意同一企业在各地的实体应该有不同 的邓氏编码,因此如果企业在各地有分公司或者不同实体厂区的话,应在申请邓氏编码时告知D&B,根据实际情况申请该编码。

通过 itms:services:在线安装ipa ,跨过app-store

1.需要一个html文件,引导下载用户在线安装ipa

 

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>
<html>
<head>
<title>一键安装掌上综调iPhone版</title>
</head>

<body>
<a href=’itms- services://?action=download-manifest&url=http://222.177.4.242/ios /d.plist’>一键安装掌上综调iPhone版</a>
</body>
</html>

 

 

2. 上文中的d.plist文件内容如下,其实它是一个XML文件,有关plist文件,请自行查阅google

 

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>
<plist version=”1.0″>
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string>http://222.177.4.242/download?attachId=022DB5EAF88A57B175D24060DCD1BA70</string>
</dict>
<dict>
<key>kind</key>
<string>display-image</string>
<key>needs-shine</key>
<true/>
<key>url</key>
<string>http://222.177.4.242/ios/icon.png</string>
</dict>
<dict>
<key>kind</key>
<string>full-size-image</string>
<key>needs-shine</key>
<true/>
<key>url</key>
<string>http://222.177.4.242/ios/icon.png</string>
</dict>
</array><key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>com.ccssoft.mopclient.chongqing</string>
<key>bundle-version</key>
<string>1.0.0</string>
<key>kind</key>
<string>software</string>
<key>subtitle</key>
<string>掌上综调</string>
<key>title</key>
<string>掌上综调</string>
</dict>
</dict>
</array>
</dict>
</plist>

 

上面2中的http://222.177.4.242/download?attachId=022DB5EAF88A57B175D24060DCD1BA70 这是ipa包所在的网络地址

 

3.自行找一个icon.png放在上面两个文件的同一个目录,此图片用作在iphone上显示程序图标。 http://222.177.4.242/ios/icon.png

 

4.使用iphone safari浏览器,浏览http://222.177.4.242/ios/d.html文件,即可安装了。简单吧。

iOS 5的StoryBoard

StoryBoard是iOS 5的新特征,旨在代替历史悠久的NIB/XIB(其实StoryBoard还是基于NIB/XIB的,不过开发人员已经无需直接跟NIB打交道了)。目前关于StoryBoard的文档并不多,苹果的iOS 5的开发者文档里也仅有不多的介绍。所以,本文只是简单的谈谈本人对StoryBoard的一些粗浅的理解。(StoryBoard有时也叫做StoryBoarding,我不太注意这种细节,所以两个词经常会混用,如果你英语可以的话,能体会到两者的细微差别)

iOS <wbr>5的StoryBoard

StoryBoarding机制比之NIB/XIB的的优势何在呢?个人认为,StoryBoard有以下几个优点:

能够减少很多跟View相关的代码;

能够使View和Controller进一步解耦;

能够优化程序的“页面流”,使程序的结构更清楚 ;

要理解这些优点,我们先要对NIB有一个基本的认识。通常,NIB是和ViewController相关联的,很多ViewController都有对应的NIB文件。NIB文件的作用是描述用户界面以及初始化对象和界面元素对象。其实开发者在NIB里描述的界面和初始化的对象都能够在代码中实现;之所以用Interface Builder来绘制界面,是为了减少那些设置界面属性的无聊和重复的代码,让开发人员能够集中精力做程序的功能。

而StoryBoard的出现,则是进一步加强了这方面的功能;NIB文件是没有办法描述从一个ViewController到另一个ViewController的过渡的。这种过渡只能靠手写代码来实现。相信很多人都会经常用到 -presentModalViewController:animated:以及-pushViewController:animated:这两个方法。这种代码在Storyboarding里将成为历史;取而代之的是Segue。Segue定义了从一个ViewController到另一个ViewController的过渡。在Storyboard里,我们只需要像连接界面对象和Action Method那样把ViewController之间用Segue连接起来就可以了,不再需要手写代码了。即便你像自定义Segue,你也只需写Segue的实现,而无需编写调用的代码,StoryBoard会帮你调用的。这就是上面所说的第一个优点。

iOS <wbr>5的StoryBoard

要用好Storyboarding机制,那么必须严格遵守MVC原则。要让View和Controller充分解耦;并且不同的Controller之间也要充分解耦。否则,程序的业务逻辑就会乱成一团,很难理解,维护和除虫(Debug)。

举个例子来说:在过去,特别是初学Cocoa Touch开发的时候,很多人都喜欢直接把AppDelegate当ViewController用,直接在AppDelegate和MainMenu.xib之间交互。应该说,这是一个非常不好的习惯。AppDelegate的作用很简单,就是处理UIApplication的回调,而不应该负责用户界面的处理。很多iOS教程为了省事,都直接把AppDelegate当ViewController用,甚至直接举例在UIWindow上绘制界面。虽然,作为教程这么做很简单明了,因为UIWindow也是UIView的子类,但是这却不是一种优良的实践。因为由ViewController来负责处理View才是正确的做法。

近一段时间,苹果的项目模版经常发生改变,特别是自从Xcode 4发布之后,程序模版(如,View Based Application)开始鼓励使用UIWindow的rootViewController属性来指定第一屏的ViewController,以保证AppDelegate专注于它应该做的事情。而引入StoryBoard之后,AppDelegate已经不管ViewController的事情了 ;第一屏所使用的ViewController(也就是rootViewController)可以在StoryBoard中设置。这样,程序的入口点就能从StoryBoard的“设计图”上一目了然了。这是第二个优点。

iOS <wbr>5的StoryBoard

至于第三个优点,就是StoryBoard的“设计图”了。StoryBoard能够包含一个程序所有的ViewController以及它们之间的连接。因此,StoryBoard甚至可以作为程序的“设计图”来用了。理想情况下,在程序开发接近尾声的时候,我们只需对比StoryBoard的“流程”和最初程序的设计“流程”,就知道程序有没有“走样”了。

iOS <wbr>5的StoryBoard

说完了优点,我们来看看从NIB/XIB到StoryBoard的迁移,我们需要有哪些理解和实践上的改变呢?

首先,自然是(在做程序开发的时候)ViewController不再需要NIB/XIB了(虽然在后台还是用的NIB)。以前在NIB/XIB上做的连接Outlet和Action的操作都可以在StoryBoard上完成了;

第二,孤儿View(独立于ViewController的View)是不能出现在StoryBoard里的,View必须通过ViewController来管理(StoryBoard更像是Controller对象的容器,而不是View对象的容器,NIB/XIB可以作为View对象的容器);

第三,ViewController之间的过渡代码已经是历史了,用StoryBoard可以直接可视化地连接不同的ViewController;

第四,UIWindow对象的作用被进一步淡化,甚至可以这么说:其实很多程序根本无需用到UIWindow对象。AppDelegate也不再被鼓励(也不能)用来做ViewController--你甚至无法在Interface Builder的StoryBoard图上找到AppDelegate对象--因为它本来就不应该用来处理界面(View)的。

最后,写优质的代码,严格遵守MVC设计模式,这样不仅能够让你用好StoryBoard,也能帮助你理解StoryBoard的原理。

StoryBoard是非常好的鼓励MVC和代码解耦的手段,能够让开发人员写出更加容易维护的代码。不过对于初学者来说,确实是个对理解力的小挑战。不过作为初学者也不用担心,一旦突破了理解障碍,你就会发现StoryBoard也非常好用--就像最初理解NIB/XIB时,Outlet和Action“拉线”来“拉线”去,看起来也很神奇;理解之后,发现原来“拉线”神马的也没那么神秘。

好了,絮絮叨叨的啰嗦了这么多无聊的文字,相信你也看累了。如果你依然对我写的东西不知所云的话,你可以稍稍研究一下Xcode 4.2的几个内建模版,然后和使用XIB的模版对比一下,看看苹果是怎么用StoryBoard的,能够很好的帮助你理解Storyboarding机制。当然,千万不要忘记亲自动手用一用StoryBoard!

Happy Coding!

【更新】

在看了WWDC 2011 的session video:UIViewController Containment这个视频之后,我感觉,正确的处理UIViewController之间的层级关系对于Storyboard来说非常重要,两者能够相得益彰。而window.rootViewController的使用,虽然也是鼓励用户不要把AppDelegate当ViewController用,更重要的是鼓励用户使用正确的UIViewController层级关系。