#
摘要: Docker 是 2014 年最为火爆的技术之一,几乎所有的程序员都听说过它。Docker 是一种“轻量级”容器技术,它几乎动摇了传统虚拟化技术的地位,现在国内外已经有越来越多的公司开始逐步使用 Docker 来替换现有的虚拟化平台了。作为一名 Java 程序员,我们是时候一起把 Docker 学起来了!本文会对虚拟化技术与 Docker 容器技术做一个对比,然后引出一些 ...
阅读全文
Spring Cloud Security OAuth2 是 Spring 对 OAuth2 的开源实现,优点是能与Spring Cloud技术线无缝集成,如果全部使用默认配置,开发者只需要添加注解就能完成 OAuth2 授权服务的搭建。
1. 添加依赖
授权服务是基于Spring Security的,因此需要在项目中引入两个依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
前者为 Security,后者为Security的OAuth2扩展。
2. 添加注解和配置
在启动类中添加@EnableAuthorizationServer
注解:
@SpringBootApplication
@EnableAuthorizationServer
public class AlanOAuthApplication {
public static void main(String[] args) {
SpringApplication.run(AlanOAuthApplication.class, args);
}
}
完成这些我们的授权服务最基本的骨架就已经搭建完成了。但是要想跑通整个流程,我们必须分配 client_id
, client_secret
才行。Spring Security OAuth2的配置方法是编写@Configuration
类继承AuthorizationServerConfigurerAdapter
,然后重写void configure(ClientDetailsServiceConfigurer clients)
方法,如:
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory() // 使用in-memory存储
.withClient("client") // client_id
.secret("secret") // client_secret
.authorizedGrantTypes("authorization_code") // 该client允许的授权类型
.scopes("app"); // 允许的授权范围
}
3. 授权流程
访问授权页面:
localhost:8080/oauth/authorize?client_id=client&response_type=code&redirect_uri=http://www.baidu.com
此时浏览器会让你输入用户名密码,这是因为 Spring Security 在默认情况下会对所有URL添加Basic Auth认证。默认的用户名为user
, 密码是随机生成的,在控制台日志中可以看到。

画风虽然很简陋,但是基本功能都具备了。点击Authorize
后,浏览器就会重定向到百度,并带上code
参数:

拿到code
以后,就可以调用
POST/GET http://client:secret@localhost:8080/oauth/token
来换取access_token
了:
curl -X POST -H "Cache-Control: no-cache" -H "Content-Type: application/x-www-form-urlencoded" -d 'grant_type=authorization_code&code=Li4NZo&redirect_uri=http://www.baidu.com' "http://client:secret@localhost:8080/oauth/token"
返回如下:
{
"access_token": "32a1ca28-bc7a-4147-88a1-c95abcc30556",
"token_type": "bearer",
"expires_in": 2591999,
"scope": "app"
}
到此我们最最基本的授权服务就搭建完成了。然而,这仅仅是个demo,如果要在生产环境中使用,还需要做更多的工作。
4. 使用MySQL存储access_token和client信息
把授权服务器中的数据存储到数据库中并不难,因为 Spring Cloud Security OAuth 已经为我们设计好了一套Schema和对应的DAO对象。但在使用之前,我们需要先对相关的类有一定的了解。
4.1 相关接口
Spring Cloud Security OAuth2通过DefaultTokenServices
类来完成token生成、过期等 OAuth2 标准规定的业务逻辑,而DefaultTokenServices
又是通过TokenStore
接口完成对生成数据的持久化。在上面的demo中,TokenStore
的默认实现为InMemoryTokenStore
,即内存存储。 对于Client信息,ClientDetailsService
接口负责从存储仓库中读取数据,在上面的demo中默认使用的也是InMemoryClientDetialsService
实现类。说到这里就能看出,要想使用数据库存储,只需要提供这些接口的实现类即可。庆幸的是,框架已经为我们写好JDBC实现了,即JdbcTokenStore
和JdbcClientDetailsService
。
4.2 建表
要想使用这些JDBC实现,首先要建表。框架为我们提前设计好了schema, 在github上:https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql
在使用这套表结构之前要注意的是,对于MySQL来说,默认建表语句中主键是varchar(255)类型,在mysql中执行会报错,原因是mysql对varchar主键长度有限制。所以这里改成128即可。其次,语句中会有某些字段为LONGVARBINARY
类型,它对应mysql的blob
类型,也需要修改一下。
4.3 配置
数据库建好后,下一步就是配置框架使用JDBC实现。方法还是编写@Configuration
类继承AuthorizationServerConfigurerAdapter
:
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Bean // 声明TokenStore实现
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Bean // 声明 ClientDetails实现
public ClientDetailsService clientDetails() {
return new JdbcClientDetailsService(dataSource);
}
@Override // 配置框架应用上述实现
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
endpoints.tokenStore(tokenStore());
// 配置TokenServices参数
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(endpoints.getTokenStore());
tokenServices.setSupportRefreshToken(false);
tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
tokenServices.setAccessTokenValiditySeconds( (int) TimeUnit.DAYS.toSeconds(30)); // 30天
endpoints.tokenServices(tokenServices);
}
完成这些后,框架就会将中间产生的数据写到mysql中了。oauth_client_details
是client表,可以直接在该表中添加记录来添加client:

4.4 需要注意的地方
这里不得不说 Spring 设计有一个奇葩地的方。注意看oauth_access_token
表是存放访问令牌的,但是并没有直接在字段中存放token。Spring 使用OAuth2AccessToken
来抽象与令牌有关的所有属性,在写入到数据库时,Spring将该对象通过JDK自带的序列化机制序列成字节直接保存到了该表的token
字段中。也就是说,如果只看数据表你是看不出access_token
的值是多少,过期时间等信息的。这就给资源服务器的实现带来了麻烦。我们的资源提供方并没有使用Spring Security,也不想引入 Spring Security 的任何依赖,这时候就只能将 DefaultOAuth2AccessToken
的源码copy到资源提供方的项目中,然后读取token
字段并反序列化还原对象来获取token信息。但是如果这样做还会遇到反序列化兼容性的问题,具体解决方法参考我另一篇博文:http://blog.csdn.net/neosmith/article/details/52539614
5. 总结
至此一个能在生产环境下使用的授权服务就搭建好了。其实我们在实际使用时应该适当定制JdbcTokenStore
或ClientDetailsService
来实适应业务需要,甚至可以直接从0开始实现接口,完全不用框架提供的实现。另外,Spring 直接将DefaultOAuth2AccessToken
序列化成字节保存到数据库中的设计,我认为是非常不合理的。或许设计者的初衷是保密access_token
,但是通过加密的方法也可以实现,完全不应该直接扔字节。不过通过定制TokenStore
接口,我们可以使用自己的表结构而不拘泥于默认实现。
http://blog.csdn.net/tracker_w/article/category/6360121
http://blog.csdn.net/neosmith/article/details/52539927
在Spring Cloud Netflix栈中,各个微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使用HTTP客户端。我们可以使用JDK原生的URLConnection
、Apache的Http Client
、Netty的异步HTTP Client, Spring的RestTemplate
。但是,用起来最方便、最优雅的还是要属Feign了。
Feign简介
Feign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用Feign, 我们可以做到使用HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。比如:
@Autowired
private AdvertGropRemoteService service; // 远程服务
public AdvertGroupVO foo(Integer groupId) {
return service.findByGroupId(groupId); // 通过HTTP调用远程服务
}
开发者通过service.findByGroupId()
就能完成发送HTTP请求和解码HTTP返回结果并封装成对象的过程。
Feign的定义
为了让Feign知道在调用方法时应该向哪个地址发请求以及请求需要带哪些参数,我们需要定义一个接口:
@FeignClient(name = "ea") // [A]
public interface AdvertGroupRemoteService {
@RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET) // [B]
AdvertGroupVO findByGroupId(@PathVariable("groupId") Integer adGroupId) // [C]
@RequestMapping(value = "/group/{groupId}", method = RequestMethod.PUT)
void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName)
A: @FeignClient
用于通知Feign组件对该接口进行代理(不需要编写接口实现),使用者可直接通过@Autowired
注入。
B: @RequestMapping
表示在调用该方法时需要向/group/{groupId}
发送GET
请求。
C: @PathVariable
与SpringMVC
中对应注解含义相同。
Spring Cloud应用在启动时,Feign会扫描标有@FeignClient
注解的接口,生成代理,并注册到Spring容器中。生成代理时Feign会为每个接口方法创建一个RequetTemplate
对象,该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里。
在本例中,我们将Feign与Eureka和Ribbon组合使用,@FeignClient(name = "ea")
意为通知Feign在调用该接口方法时要向Eureka中查询名为ea
的服务,从而得到服务URL。
Feign的Encoder、Decoder和ErrorDecoder
Feign将方法签名中方法参数对象序列化为请求参数放到HTTP请求中的过程,是由编码器(Encoder)完成的。同理,将HTTP响应数据反序列化为java对象是由解码器(Decoder)完成的。
默认情况下,Feign会将标有@RequestParam
注解的参数转换成字符串添加到URL中,将没有注解的参数通过Jackson转换成json放到请求体中。注意,如果在@RequetMapping
中的method
将请求方式指定为POST
,那么所有未标注解的参数将会被忽略,例如:
@FeignClient(name = "ea") // [A]
public interface AdvertGroupRemoteService {
@RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET) // [B]
AdvertGroupVO findByGroupId(@PathVariable("groupId") Integer adGroupId) // [C]
@RequestMapping(value = "/group/{groupId}", method = RequestMethod.PUT)
void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName)
此时因为声明的是GET请求没有请求体,所以obj
参数就会被忽略。
在Spring Cloud环境下,Feign的Encoder*只会用来编码没有添加注解的参数*。如果你自定义了Encoder, 那么只有在编码obj
参数时才会调用你的Encoder。对于Decoder, 默认会委托给SpringMVC中的MappingJackson2HttpMessageConverter
类进行解码。只有当状态码不在200 ~ 300之间时ErrorDecoder才会被调用。ErrorDecoder的作用是可以根据HTTP响应信息返回一个异常,该异常可以在调用Feign接口的地方被捕获到。我们目前就通过ErrorDecoder来使Feign接口抛出业务异常以供调用者处理。
Feign的HTTP Client
Feign在默认情况下使用的是JDK原生的URLConnection
发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection
。我们可以用Apache的HTTP Client替换Feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。Spring Cloud从Brixtion.SR5
版本开始支持这种替换,首先在项目中声明Apache HTTP Client和feign-httpclient
依赖:
@RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET)
void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName, DataObject obj);
然后在application.properties
中添加:
feign.httpclient.enabled=true
总结
通过Feign, 我们能把HTTP远程调用对开发者完全透明,得到与调用本地方法一致的编码体验。这一点与阿里Dubbo中暴露远程服务的方式类似,区别在于Dubbo是基于私有二进制协议,而Feign本质上还是个HTTP客户端。如果是在用Spring Cloud Netflix搭建微服务,那么Feign无疑是最佳选择。
http://blog.csdn.net/tracker_w/article/category/6360121
http://blog.csdn.net/neosmith/article/details/52449921
2016
基于SPRING CLOUD的微服务框架
http://jhipster.cn/
摘要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