#
摘要Spring 框架给企业软件开发者提供了常见问题的通用解决方案,包括那些在未来开发中没有意识到的问题。但是,它构建的 J2EE 项目变得越来越臃肿,逐渐被 Spring Boot 所替代。Spring Boot 让我们创建和运行项目变得更为迅速,现在已经有越来越多的人使用它。我们已经在几个项目中使用了 Spring Boot ,今天我们就来一起讨论一下如何改进 Spring Boot 应用的性能。
Spring 框架给企业软件开发者提供了常见问题的通用解决方案,包括那些在未来开发中没有意识到的问题。但是,它构建的 J2EE 项目变得越来越臃肿,逐渐被 Spring Boot 所替代。Spring Boot 让我们创建和运行项目变得更为迅速,现在已经有越来越多的人使用它。我们已经在几个项目中使用了 Spring Boot ,今天我们就来一起讨论一下如何改进 Spring Boot 应用的性能。
首先,从之前我在开发中遇到的一个问题说起。在一次查看项目运行日志的时候,我偶然发现了一个问题,日志里显示这个项目总是加载 Velocity 模板引擎,但实际上这个项目是一个没有 web 页面的 REST Service 项目。于是我花了一点时间去寻找产生这个问题的原因,以及如何改进 Spring Boot 应用的性能。在查找了相关的资料后,我得出的结论如下:
组件自动扫描带来的问题
默认情况下,我们会使用 @SpringBootApplication 注解来自动获取的应用的配置信息,但这样也会给应用带来一些副作用。使用这个注解后,会触发自动配置( auto-configuration )和 组件扫描 ( component scanning),这跟使用 @Configuration、@EnableAutoConfiguration 和 @ComponentScan 三个注解的作用是一样的。这样做给开发带来方便的同时,也会有两方面的影响:
1、会导致项目启动时间变长。当启动一个大的应用程序,或将做大量的集成测试启动应用程序时,影响会特别明显。
2、会加载一些不需要的多余的实例(beans)。
3、会增加 CPU 消耗。
针对以上两个情况,我们可以移除 @SpringBootApplication 和 @ComponentScan 两个注解来禁用组件自动扫描,然后在我们需要的 bean 上进行显式配置:
// 移除 @SpringBootApplication and @ComponentScan, 用 @EnableAutoConfiguration 来替代
@Configuration
@EnableAutoConfiguration
public class SampleWebUiApplication {
// 
// 用 @Bean 注解明确显式配置,以便被 Spring 扫描到
@Bean
public MessageController messageController(MessageRepository messageRepository) {
return new MessageController(messageRepository);
} 如何避免组件自动扫描带来的问题
我们在上面提到,@SpringBootApplication 注解的作用跟 @EnableAutoConfiguration 注解的作用是相当的,那就意味着它也能带来上述的三个问题。要避免这些问题,我们就要知道我们需要的组件列表是哪些,可以用 -Ddebug 的方式来帮助我们明确地定位:
mvn spring-boot:run -Ddebug … ========================= AUTO-CONFIGURATION REPORT ========================= Positive matches: ----------------- DispatcherServletAutoConfiguration - @ConditionalOnClass classes found: org.springframework.web.servlet.DispatcherServlet (OnClassCondition) - found web application StandardServletEnvironment (OnWebApplicationCondition) ...
接着拷贝 Positive matches
中列出的信息:
DispatcherServletAutoConfiguration
EmbeddedServletContainerAutoConfiguration
ErrorMvcAutoConfiguration
HttpEncodingAutoConfiguration
HttpMessageConvertersAutoConfiguration
JacksonAutoConfiguration
JmxAutoConfiguration
MultipartAutoConfiguration
ServerPropertiesAutoConfiguration
PropertyPlaceholderAutoConfiguration
ThymeleafAutoConfiguration
WebMvcAutoConfiguration
WebSocketAutoConfiguration
然后来更新项目配置,显式地引入这些组件,引入之后,再运行一下应用确保没有错误发生:
@Configuration
@Import({
DispatcherServletAutoConfiguration.class,
EmbeddedServletContainerAutoConfiguration.class,
ErrorMvcAutoConfiguration.class,
HttpEncodingAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
JacksonAutoConfiguration.class,
JmxAutoConfiguration.class,
MultipartAutoConfiguration.class,
ServerPropertiesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
ThymeleafAutoConfiguration.class,
WebMvcAutoConfiguration.class,
WebSocketAutoConfiguration.class,
})
public class SampleWebUiApplication {}
在上面的代码中,我们可以删掉我们不需要的组件信息,来提高应用的性能,比如在我的项目中,不需要 JMX 和 WebSocket 功能,我就删掉了它们。删掉之后,再次运行项目,确保一切正常。
将Servlet容器变成Undertow
默认情况下,Spring Boot 使用 Tomcat 来作为内嵌的 Servlet 容器。我们可以启动项目,然后用 VisualVM 或者 JConsole 来查看应用所占的内存情况:

以上是我使用 Spring Boot 的默认方式启动应用后,用 VisualVM 监控到的内存的占用情况:堆内存占用 110M,16 个线程被开启。
可以将 Web 服务器切换到 Undertow 来提高应用性能。Undertow 是一个采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。Undertow 是红帽公司的开源产品,是 Wildfly 默认的 Web 服务器。首先,从依赖信息里移除 Tomcat 配置:
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
然后添加 Undertow:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
启动项目后,用 VisualVM 监控到的信息显示:堆内存占用 90M,13个线程被开启。

总结
这些都是我们在项目开发中使用到的一些优化 Spring Boot 应用的小技巧,对于大的应用性能的提高还是很明显的。大家可以尝试一下,然后告诉我们你的测试结果。
最后,附上代码,大家可以去这里下载:spring-boot-performance。
文中大部分内容参考英国一个架构师的博客 和 DZone 近期发布的文章,在此感谢两位大牛。参考文章及链接:
(1)Spring Boot 性能优化:Spring Boot Performance;
(2)Spring Boot 内存优化:Spring Boot Memory Performance。
(3)https://www.techempower.com/benchmarks/;
(4)Spring 应用程序优化:Optimizing Spring Framework for App Engine Applications。
摘要
spring cloud config server配置好了数据库连接信息,这个项目读取config,获取连接信息。这里以mybtis作为列子。从服务器读取jdbc信息后,运行mybatis程序。
确认服务是否成功
http://localhost:8888/demo-config/test
{"name":"demo-config","profiles":["test"],"label":"master","version":"02d28ad4925aa9bd1bf8a48d2edbf04ce61aa45a","propertySources":[{"name":"https://git.oschina.net/penghaozhong/demo.git/demo-config-repo/demo-config-test.properties","source":{"jdbc.url":"jdbc:mysql://localhost:3306/demo?characterEncoding=UTF-8","jdbc.username":"root","jdbc.driver":"com.mysql.jdbc.Driver","jdbc.password":"xxxxxx","jdbc.type":"mysql"}}]}
2. 配置读取配置文件

在bootstrap.properties中添加读取配置管理的地址。
3. 读取配置文件属性,这里采用@ConfigurationProperties
/**
* 读取数据库配置文件
* @author penghaozhong
*
*/
@ConfigurationProperties(prefix = DataSourceProperties.PREFIX, ignoreUnknownFields = false)
public class DataSourceProperties {
public DataSourceProperties() {
super();
}
//对应配置文件里的配置键
public final static String PREFIX="jdbc";
private String type;
private String driver;
private String url;
private String username;
private String password;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
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;
}
}
4. 配置mybatis
@Configuration
@MapperScan("com.phz.test.spring.cloud.demo")
@EnableConfigurationProperties(DataSourceProperties.class)
@EnableTransactionManagement
public class MybatisDataSource {
// mybaits mapper xml搜索路径
private final static String MAPPERLOCATIONS = "classpath:/mappings/**/*.xml";
private final static String CONFIGLOCATION = "classpath:/mybatis-config.xml";
@Autowired
private DataSourceProperties dataSourceProperties;
private DruidDataSource datasource = null;
@Bean(destroyMethod = "close")
public DataSource dataSource(){
datasource = new DruidDataSource();
datasource.setUrl(dataSourceProperties.getUrl());
datasource.setDbType(dataSourceProperties.getType());
datasource.setDriverClassName(dataSourceProperties.getDriver());
datasource.setUsername(dataSourceProperties.getUsername());
datasource.setPassword(dataSourceProperties.getPassword());
return datasource;
}
@PreDestroy
public void close() {
if(datasource != null){
datasource.close();
}
}
@Bean
public SqlSessionFactory sqlSessionFactoryBean() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource());
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resolver.getResources(MAPPERLOCATIONS));
sqlSessionFactoryBean.setConfigLocation(resolver.getResource(CONFIGLOCATION));
sqlSessionFactoryBean.setTypeAliasesPackage("com.phz.test.spring.cloud.demo.entity");
return sqlSessionFactoryBean.getObject();
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
什么是spring-loaded?
spring-loaded是一个对于jvm代理运行时期改变类文件的重载(重新加载),它转换类loadtime让他们服从后重新加载。不像“热代码替换”只允许一次简单的改变JVM运行(例如更改方法体)spring-loaded允许您添加/修改/删除/字段/方法构造函数。注释类型/方法/字段/构造函数也可以修改和可以添加/删除/修改值的枚举类型。
有什么好处?
开发测试阶段:能够在启动后动态更改代码调试,无需重启减少切换debug时间(ps:对于eclipse而言,在debug时期只能做到动态更新方法体不能增加)
对于线上测试发布阶段: 能够在出现问题后直接替换class文件而不重启应用(ps:对于外部提供的服务jar形式同样能做到)
怎么使用?
项目地址
https://github.com/spring-projects/spring-loaded
第一步:下载文件
http://repo.spring.io/release/org/springframework/springloaded/1.2.5.RELEASE/springloaded-1.2.5.RELEASE.jar第二步:配置jvm启动参数
eclipse
eclipse:run as --> run configurations --> arguments -->> VM arguments
-javaagent:E:\repository\org\springframework\spring-load\springloaded-1.2.5.RELEASE.jar
-noverify -Dspringloaded=verbose
详细描述:
-javaagent: 配置java代理使用下载后的jar包路径
-noverify: 禁用字节码验证
-Dspringloaded=verbose 显示springloaded时的详细信息

java命令启动
java -javaagent:E:\repository\org\springframework\spring-load\springloaded-1.2.5.RELEASE.jar -noverify Test 类似
java jar包动态替换
1.打成runnable Jar
2.命令启动:
java -javaagent:E:\repository\org\springframework\spring-load\springloaded-1.2.5.RELEASE.jar -noverify -Dspringloaded=watchJars=main.jar main.jar
/** * 类Test.java的实现描述:TODO 类实现描述 * @author Administrator 2016年7月4日 下午4:55:59 */ public class Test { public static void main(String[] args) throws InterruptedException { while(true) { try { println(); Thread.sleep(1000); } catch (Throwable e) { e.printStackTrace(); } } } public static void println() { System.out.println("112222221222222"); } }
改变为
/** * 类Test.java的实现描述:TODO 类实现描述 * @author Administrator 2016年7月4日 下午4:55:59 */ public class Test { public static void main(String[] args) throws InterruptedException { while(true) { try { println(); Thread.sleep(1000); } catch (Throwable e) { e.printStackTrace(); } } } public static void println() { System.out.println("test replace jar"); } }
3.重新打包替换
PS:实测在window下无用 手上无linux机器待测试
1
Spring Cloud 为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性 Token、全局锁、决策竞选、分布式会话和集群状态)操作的开发工具。使用 Spring Cloud 开发者可以快速实现上述这些模式。
主要有eureka做服务发现、config做分布式配置、zuul做api-gateway、feign做客户端负载均衡、hystrix做断路器、turbine做聚合的monitor、graphite做指标监控。
http://blog.csdn.net/liaokailin/article/category/6212338
MICROSERVICE WITH SPRING-CLOUD.
https://github.com/kennyk65/Microservices-With-Spring-Student-Files
!!!spring-cloud-study
http://git.oschina.net/itmuch/spring-cloud-study
一个ring buffer实现多线程通信。由于他们之间通信不需要锁所以性能有很大的提高。
Disruptor更多的应用在高速事务中,利用JVM的伪内存,这也可能是它为LMAX而生的,和akka的应用场景不一样。
一般编写并发应用程序马上想到多线程或者多进程。但多线程需要处理资源竞争,共享访问等问题,搞不好容易出现死锁,当程序规模比较大时,排查难度很大。 Actor模型提供了另一种编写并发应用程序的思路。 有点类似Node.JS的基于事件异步处理. (其实我觉得基于消息异步和基于事件异步是一回事)
什么是基于消息异步呢?很简单,比如要开展一个项目,需要多人协作。作为项目经理的你,只需要像手下发出命令,个人各干各的,互不干扰。做完了就回送一个消息给项目经理,项目经理再分派新的任务. (可能比喻得不恰当,但Actor的基本思路就是这样,你不需要考虑资源共享和线程并发什么的, Actor库屏蔽了这些底层的实现细节 . 每个Actor就相当于一个人或者叫一个处理者,他们的职责很单一,就是响应对方发来的消息,做出响应,并回送一个响应消息。 每个Actor负责做自己的份内事,最后有一个调度角色的Actor将所有Actor管理起来,形成一个整体)
Akka 是针对Scala和Java的Actor库,JActor是一个用纯Java编写的Actor库。
https://github.com/LMAX-Exchange/disruptorhttp://www.oschina.net/p/disruptor
1 JPA概述
JPA(Java Persistence API,Java持久化API),定义了对象-关系映射(ORM)以及实体对象持久化的标准接口。
JPA是JSR-220(EJB3.0)规范的一部分,在JSR-220中规定实体对象(EntityBean)由JPA进行支持。
所以JPA不局限于EJB3.0,而是作为POJO持久化的标准规范,可以脱离容器独立运行,开发和测试更加方便。
JPA在应用中的位置如下图所示:

JPA维护一个Persistence Context(持久化上下文),在持久化上下文中维护实体的生命周期。主要包含三个方面的内容:
- ORM元数据。JPA支持annotion或xml两种形式描述对象-关系映射。
- 实体操作API。实现对实体对象的CRUD操作。
- 查询语言。约定了面向对象的查询语言JPQL(Java Persistence Query Language)。
JPA的主要API都定义在javax.persistence包中。如果你熟悉Hibernate,可以很容易做出对应:
org.hibernate | javax.persistence | 说明 |
---|
cfg.Configuration | Persistence | 读取配置信息 |
SessionFactory | EntityManagerFactory | 用于创建会话/实体管理器的工厂类 |
Session | EntityManager | 提供实体操作API,管理事务,创建查询 |
Transaction | EntityTransaction | 管理事务 |
Query | Query | 执行查询 |

2 实体生命周期
实体生命周期是JPA中非常重要的概念,描述了实体对象从创建到受控、从删除到游离的状态变换。对实体的操作主要就是改变实体的状态。
JPA中实体的生命周期如下图:

- New,新创建的实体对象,没有主键(identity)值
- Managed,对象处于Persistence Context(持久化上下文)中,被EntityManager管理
- Detached,对象已经游离到Persistence Context之外,进入Application Domain
- Removed, 实体对象被删除
EntityManager提供一系列的方法管理实体对象的生命周期,包括:
- persist, 将新创建的或已删除的实体转变为Managed状态,数据存入数据库。
- remove,删除受控实体
- merge,将游离实体转变为Managed状态,数据存入数据库。
如果使用了事务管理,则事务的commit/rollback也会改变实体的状态。
3 实体关系映射(ORM)
3.1 基本映射
对象端 | 数据库端 | annotion | 可选annotion |
---|
Class | Table | @Entity | @Table(name="tablename") |
property | column | – | @Column(name = "columnname") |
property | primary key | @Id | @GeneratedValue 详见ID生成策略 |
property | NONE | @Transient | |
3.2 ID生成策略
ID对应数据库表的主键,是保证唯一性的重要属性。JPA提供了以下几种ID生成策略
- GeneratorType.AUTO ,由JPA自动生成
- GenerationType.IDENTITY,使用数据库的自增长字段,需要数据库的支持(如SQL Server、MySQL、DB2、Derby等)
- GenerationType.SEQUENCE,使用数据库的序列号,需要数据库的支持(如Oracle)
- GenerationType.TABLE,使用指定的数据库表记录ID的增长 需要定义一个TableGenerator,在@GeneratedValue中引用。例如:
@TableGenerator( name="myGenerator", table="GENERATORTABLE", pkColumnName = "ENTITYNAME", pkColumnValue="MyEntity", valueColumnName = "PKVALUE", allocationSize=1 )
@GeneratedValue(strategy = GenerationType.TABLE,generator="myGenerator")
3.3 关联关系
JPA定义了one-to-one、one-to-many、many-to-one、many-to-many 4种关系。
对于数据库来说,通常在一个表中记录对另一个表的外键关联;对应到实体对象,持有关联数据的一方称为owning-side,另一方称为inverse-side。
为了编程的方便,我们经常会希望在inverse-side也能引用到owning-side的对象,此时就构建了双向关联关系。 在双向关联中,需要在inverse-side定义mappedBy属性,以指明在owning-side是哪一个属性持有的关联数据。
对关联关系映射的要点如下:
关系类型 | Owning-Side | Inverse-Side |
---|
one-to-one | @OneToOne | @OneToOne(mappedBy="othersideName") |
one-to-many / many-to-one | @ManyToOne | @OneToMany(mappedBy="xxx") |
many-to-many | @ManyToMany | @ManyToMany(mappedBy ="xxx") |
其中 many-to-many关系的owning-side可以使用@JoinTable声明自定义关联表,比如Book和Author之间的关联表:
@JoinTable(name = "BOOKAUTHOR", joinColumns = { @JoinColumn(name = "BOOKID", referencedColumnName = "id") }, inverseJoinColumns = { @JoinColumn(name = "AUTHORID", referencedColumnName = "id") })
关联关系还可以定制延迟加载和级联操作的行为(owning-side和inverse-side可以分别设置):
通过设置fetch=FetchType.LAZY 或 fetch=FetchType.EAGER来决定关联对象是延迟加载或立即加载。
通过设置cascade={options}可以设置级联操作的行为,其中options可以是以下组合:
- CascadeType.MERGE 级联更新
- CascadeType.PERSIST 级联保存
- CascadeType.REFRESH 级联刷新
- CascadeType.REMOVE 级联删除
- CascadeType.ALL 级联上述4种操作
3.4 继承关系
JPA通过在父类增加@Inheritance(strategy=InheritanceType.xxx)来声明继承关系。A支持3种继承策略:
- 单表继承(InheritanceType.SINGLETABLE),所有继承树上的类共用一张表,在父类指定(@DiscriminatorColumn)声明并在每个类指定@DiscriminatorValue来区分类型。
- 类表继承(InheritanceType.JOINED),父子类共同的部分公用一张表,其余部分保存到各自的表,通过join进行关联。
- 具体表继承(InheritanceType.TABLEPERCLASS),每个具体类映射到自己的表。
其中1和2能够支持多态,但是1需要允许字段为NULL,2需要多个JOIN关系;3最适合关系数据库,对多态支持不好。具体应用时根据需要取舍。
4 事件及监听

通过在实体的方法上标注@PrePersist,@PostPersist等声明即可在事件发生时触发这些方法。
5 Query Language 查询语言
JPA提供两种查询方式,一种是根据主键查询,使用EntityManager的find方法:
T find(Class entityClass, Object primaryKey)
另一种就是使用JPQL查询语言。JPQL是完全面向对象的,具备继承、多态和关联等特性,和hibernate HQL很相似。
使用EntityManager的createQuery方法:
Query createQuery(String qlString)
5.1 使用参数
可以在JPQL语句中使用参数。JPQL支持命名参数和位置参数两种参数,但是在一条JPQL语句中所有的参数只能使用同一种类型。
举例如下:
Query query = em.createQuery("select p from Person p where p.personid=:Id"); query.setParameter("Id",new Integer(1));
Query query = em.createQuery("select p from Person p where p.personid=?1"); query.setParameter(1,new Integer(1));
5.2 命名查询
如果某个JPQL语句需要在多个地方使用,还可以使用@NamedQuery 或者 @NamedQueries在实体对象上预定义命名查询。
在需要调用的地方只要引用该查询的名字即可。
例如:
@NamedQuery(name="getPerson", query= "FROM Person WHERE personid=?1")
@NamedQueries({ @NamedQuery(name="getPerson1", query= "FROM Person WHERE personid=?1"), @NamedQuery(name="getPersonList", query= "FROM Person WHERE age>?1") })
Query query = em.createNamedQuery("getPerson");
5.3 排序
JPQL也支持排序,类似于SQL中的语法。例如: Query query = em.createQuery("select p from Person p order by p.age, p.birthday desc");
5.4 聚合查询
JPQL支持AVG、SUM、COUNT、MAX、MIN五个聚合函数。例如:
Query query = em.createQuery("select max(p.age) from Person p"); Object result = query.getSingleResult(); String maxAge = result.toString();
5.5 更新和删除
JPQL不仅用于查询,还可以用于批量更新和删除。
如:
Query query = em.createQuery("update Order as o set o.amount=o.amount+10"); //update 的记录数 int result = query.executeUpdate();
Query query = em.createQuery("delete from OrderItem item where item.order in(from Order as o where o.amount<100)"); query.executeUpdate();
query = em.createQuery("delete from Order as o where o.amount<100"); query.executeUpdate();//delete的记录数
6 事务管理
JPA支持本地事务管理(RESOURCELOCAL)和容器事务管理(JTA),容器事务管理只能用在EJB/Web容器环境中。
事务管理的类型可以在persistence.xml文件中的“transaction-type”元素配置。
JPA中通过EntityManager的getTransaction()方法获取事务的实例(EntityTransaction),之后可以调用事务的begin()、commit()、rollback()方法。
Date: 2012-12-30 16:46:29 CST
Author: Holbrook
Org version 7.8.11 with Emacs version 24
git有诸多好处,网上都说的很清楚了,在这里我不再赘述。对于我来说,私下里想做一些项目,而又不能很好的保存自己的代码和进行版本控制,这时候,就用到了git。下面,就以我个人为例讲讲git从0开始如何安装使用。
Step1 准备工作
msysgit,下载地址为http://msysgit.github.io/。
Eclipse IDE for Java EE Developers(必须是这个,自带Egit,或者自行安装Egit插件),在Eclipse官网下载,地址http://www.eclipse.org/downloads/。
github账号,github官网注册一个,地址https://github.com/。
廖雪峰的git教程,地址为http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000,讲得很好,我大概花了3个晚上的时间看,如果仅仅是为了安装上,可以先暂时略过,后面再看。
Step2 msysgit安装
一路next就行,注意可能会遇到360的拦截(该死,点击允许本程序所有操作或者安装前就退出360即可)。
Step3 git用户名和邮箱配置
单击开始菜单,打开Git Bush,

输入以下命令
git config --global user.name "Your Name"
git config --global user.email email@example.com
用户名和邮箱替换为自己的,为本台机器所有仓库指定用户名和email地址。
Step4 创建SSH Key
因为本地git仓库和远程的github仓库之间是通过ssh加密的,所以,还需要创建一个SSH Key。
输入以下命令
ssh-keygen -t rsa -C youremail@example.com
同样将邮箱替换为自己的。在路径C盘->用户->用户名,找到.ssh文件夹,打开就可以看到两个文件id_rsa和id_rsa.pub,
打开id_rsa.pub,将其中的内容复制下来(这就相当于一把钥匙,持有钥匙的人可以访问你的内容,下一个小结讲解这把钥匙的用途),下面是我的

Step5 与github上的仓库相关联
注册一个github账号
注册完成之后,点击右上角的settings(就是那个齿轮,设置的图标)

进入设置页面

选SSH Keys,点击add SSH key,就可以添加了,title随便填写,将从id_rsa.pub中复制的内容粘贴到这里。从此,gitgub仓库就能够识别你本地的仓库了。也就是说,你离将本地代码推送到github上,或者将github上的代码克隆到本地,就只差一步了。(可参考廖雪峰前辈的教程先进行在非Eclipse下的操作,更有感觉)
Step6 Egit的使用
首先,登入你的github账号,点击加号,选择New repositrory,创建一个新的仓库,如图所示。

名字叫做test2,其他都默认就好。
点击绿色按钮创建,就创建好了一个github仓库。

将地址复制下来,保存好备用。
打开Eclipse,像平常一样,新建一个web工程,或者其他你常用的工程。我这里工程叫做scott
![{4$7`FVS]283EW(~80FR(JT {4$7`FVS]283EW(~80FR(JT](http://images.cnitblog.com/blog/465427/201409/252120388895169.jpg)
右击项目,选择Team->Share Project,弹出如下窗口。

选择git,next,在弹出的界面上,①先勾选Use or create……,②createrepository,③勾选工程,④finish。

这时候,你就创建好了一个git工程,右击工程,选择Team,你可以像svn一样进行commit,synchronize等操作,但是,remote操作中,push是灰色的,表示还不能将代码推送到github仓库上去。

这时,打开Git Repository视图(具体怎么打开百度去,这都是基本常识了)

右键选择Create Remote,点OK

点击Change,弹出如下界面

URI输入之前在github上拷贝的地址,下面的内容会自动填上。你只需要再填上github上的用户名和密码即可。finish,save。
接下来的几步就简单了,在项目里面随便写点代码,然后先将新增的代码提交到本地,例如,将cat类,先add to index,然后commit。这时候,右键工程,Team->remote中就有了push选项,意味着你可以将本地代码保存在github中了。祝贺你!

点击Push,点击add All Branches Spec,将本地版本库添加,然后Finish,后面一路Next,再次查看github,可以看到代码已经成功推送。

最后,看看我们在github上的代码吧!

作者: 张万帆
欢迎任何形式的转载,但请务必注明出处。
一、Eclipse上安装GIT插件EGit
Eclipse的版本eclipse-java-helios-SR2-win32.zip(在Eclipse3.3版本找不到对应的 EGit插件,无法安装)


EGit插件地址:http://download.eclipse.org/egit/updates
OK,随后连续下一步默认安装就可以,安装后进行重启Eclipse
二、在Eclipse中配置EGit
准备工作:需要在https://github.com 上注册账号
Preferences > Team > Git > Configuration

这里的user.name 是你在https://github.com上注册用户名

user.email是你在github上绑定的邮箱。在这里配置user.name即可
三、新建项目,并将代码提交到本地的GIT仓库中
1、新建项目 git_demo,并新建HelloWorld.java类

2、将git_demo项目提交到本地仓库,如下图



到此步,就成功创建GIT仓库。但文件夹处于untracked状态(文件夹中的符号”?”表示),下面我们需要提交代码到本地仓库,如下图



OK,这样代码提交到了本地仓库
四:将本地代码提交到远程的GIT仓库中
准备工作:在https://github.com上创建仓库


点击“Create repository” ,ok,这样在github上的仓库就创建好了。
注意创建好远程仓库后,点击进去,此时可以看到一个HTTP地址,如红线框,这个是你http协议的远程仓库地址

准备工作做好了,那开始将代码提交到远程仓库吧






OK,这样提交远程GIT就完成了,可以在https://github.com核对一下代码是否已经提交

注意的问题
如果是首次提交会第一步:先在本地建立一个一样的仓库,称本地仓库。
第二步:在本地进行commit操作将把更新提交到本地仓库;
第三步: 将服务器端的更新pull到本地仓库进行合并,最后将合并好的本地仓库push到服务器端,这样就进行了一次远程提交。
如果非首次提交同样的道理
第一步:将修改的代码commit操作更新到本地仓库;
第二步:第三步: 将服务器端的更新pull到本地仓库进行合并,最后将合并好的本地仓库push到服务器端
上个月,我贴了《图形化简历》。
几天后,就收到了秋叶老师的来信,希望与我探讨一些设计问题。他写过一本畅销书《说服力-让你的PPT会说话》,眼下正在写续集。
我看了新书的样章,觉得很不错,有些内容很值得分享。
====================================
首先,我们先看一个例子。良好的设计如何使得一个平庸的文档脱胎换骨。下面是一张大学生的求职简历,再普通不过了,想要引起招聘经理的注意,恐怕很难。

秋叶老师对它进行了简单的排版,还是一张表格,还是黑白配色,没有使用任何图形元素,效果却完全不一样了。

真是令人眼前一亮,不由自主地想多看几眼。这就是优秀设计的作用:它让你脱颖而出。
====================================
秋叶老师把他的排版心得,总结为六个原则:对齐,聚拢,重复,对比,强调,留白。我是这样理解的:
一、对齐原则
相关内容必须对齐,次级标题必须缩进,方便读者视线快速移动,一眼看到最重要的信息。
二、聚拢原则
将内容分成几个区域,相关内容都聚在一个区域中。段间距应该大于段内的行距。
三、留白原则
千万不要把页面排得密密麻麻,要留出一定的空白,这本身就是对页面的分隔。这样既减少了页面的压迫感,又可以引导读者视线,突出重点内容。
四、降噪原则
颜色过多、字数过多、图形过繁,都是分散读者注意力的"噪音"。
五、重复原则
多页面排版时,注意各个页面设计上的一致性和连贯性。另外,在内容上,重要信息值得重复出现。
六、对比原则
加大不同元素的视觉差异。这样既增加了页面的活泼,又方便读者集中注意力阅读某一个子区域。
====================================
下面用一个PPT的例子,演示排版六原则。

上面这张ppt有两个毛病。一是字数太多,抓不住重点;二是右边没有对齐,使得读者的视线只能一行行地从行首到行尾移动,不能直上直下。

现在进行修改。
第一步,根据"聚拢原则",将六点分成六个区域。
第二步,根据"降噪原则",将每一点分成"小标题"和"说明文字"两部分。
第三步,根据"对齐原则",将每一个部分、每一种元素对齐。
第四步,根据"对比原则",加大"小标题"和"说明文字"在字体和颜色上的差异。
第五步,根据"留白原则",留出一定的空白。

页面的可读性大大增加。
(完)