背景与愿景:开发环境下,tomcat对热布署的支持还不够全面,致使开发人员浪费大量时间在重起服务上。为了提高开发效率,决定引入Jrebel,它对热布署的支持相对比较全面。虽然Jrebel官方号称使用它不存在内存泄漏问题,但是占用一定的资源是肯定的,因此不考虑在正式环境下使用热布署。Jrebel实际上支持非常多中间件,除了Tomcat还包括Jetty、Resin、Weblogic等等,从理论上来讲,他跟中间件也没什么关系,但实际配置的时候还是会根据中间件有所不同,具体可以上官网查看,本文要讲的是tomcat+ eclipse+ spring+ struts2+ maven的环境。在使用Jrebel后,我们期望看到开发人员早上开机启动一次tomcat后就够了。本文的前置文章m2eclipse+tomcat实现应用布署,点击进入http://truemylife.iteye.com/blog/1669031
使用场景:Tomcat对热布署的使用场景是Servlet+JSP+JaveBean。如果项目含有其他框架时,其热布署效果就会大大降低,在与同事一同测试观察后发现:tomcat6在spring+struts框架下的项目,对java文件修改后的成功热布署概率偏低。由于概率太低,而且有无热布署成功不能确定,大部分开发人员修改类后不管什么情况直接选择重起,长此以往,浪费的时间积累起来不在少数。下面把tomcat和jrebel对热布署测试结果对比一下:
对比项 |
Jrebel |
Tomcat |
Class文件 |
绝大部分能热布署 |
小部分能热布署 |
Spring支持 |
改成用注释的方式后,可支持 |
不支持 |
Struts配置文件 |
支持 |
支持 |
页面相关文件 |
支持 |
支持 |
从对比可以看到,Jrebel最大的提升是对java类修改时,热布署大大提高;而对spring的支持实际上还是有限的,需要把IoC的实现改成使用注释的方式,而不能是配置的方式。如果你的工程的Spring已经是注释的方式,那就比较顺利,装好插件后,绝大部分情况下都能使用热布署了。如果你不是使用注释方式,那就麻烦了,要么全都改成注释方式,要么Jrebel对spring作用有限,看你自己的选择了。下面把已知Jrebel不能成功的热布署的情况作一列举:
1、替换了父类。
2、增加或删除了继承的接口。
3、Spring布署文件修改(如果改成注释方式,实际上spring只剩个别固定的第三方包的beans描述,比如数据库链接等)
4、web.xml,虽然jrebel和tomcat都支持web.xml修改的热布署,但是如果项目比较复杂,初始化工作较多的话,还是直接重起吧,直接热布署意义不大,而且重复初始化对于某些业务来说是会报错,所以建议有较复杂的初始化项目来说,还是直接重起得了。
Jrebel安装和使用
1、jrebel是商用软件,而且价格不扉,去下载个破解版吧,最新的破解版是4.0,如果网上找不到,请留下邮件。下载jrebel.jar到本地,比如放在d:\jrebel.jar
2、Eclipse window->preference->tomcat->JVM Settings,加入以下参数
-Drebel.spring_plugin=true 支持spring框架
-Drebel.aspectj_plugin=true 支持aspectj
-Drebel.struts2_plugin=true 支持strut2
-javaagent:D:\jrebel.jar 这里自行修改jrebel.jar正确的路径
-noverify
如果你要支持更多的框架,可以参考官网http://www.zeroturnaround.com/jrebel/features/frameworks/
如果你要了解更多的参数配置,可以参考官网
http://www.zeroturnaround.com/jrebel/configuration/
jrebel支持监控多个目录下的classes、配置文件、jar包是否被修改,因此建议新建并配置rebel.xml文件,如果Eclipse安装了官网的jrebel plugin,那么可以从eclipse菜单里产生rebel.xml文件。以下是rebel.xml的简单手动配置:
<?xml version="1.0" encoding="UTF-8"?>
<application
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.zeroturnaround.com"
xsi:schemaLocation="http://www.zeroturnaround.com/alderaan/rebel-2_0.xsd">
<classpath>
<dir name="E:\projects\cmac\target\classes"/>
<dir name="E:\projects\cmac\target\test-classes"/>
</classpath>
<web>
<link target="/">
<dir name="E:\projects\cmac\src\main\webapp"/>
</link>
</web>
</application>
rebel.xml更详细配置说明参考官网(http://www.zeroturnaround.com/jrebel/configuration/)
3、此时启动tomcat,会发现如下错误信息
严重: Exception starting filter Struts2
java.lang.NoClassDefFoundError: Lorg/apache/velocity/app/VelocityEngine;
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2291)
at java.lang.Class.getDeclaredFields(Class.java:1743)
at com.opensymphony.xwork2.inject.ContainerImpl.addInjectors(ContainerImpl.java:102)
at com.opensymphony.xwork2.inject.ContainerImpl$1.create(ContainerImpl.java:84)
at com.opensymphony.xwork2.inject.ContainerImpl$1.create(ContainerImpl.java:82)
at com.opensymphony.xwork2.inject.util.ReferenceCache$CallableCreate.call(ReferenceCache.java:155)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at com.opensymphony.xwork2.inject.util.ReferenceCache.internalCreate(ReferenceCache.java:81)
at com.opensymphony.xwork2.inject.util.ReferenceCache.get(ReferenceCache.java:121)
at com.opensymphony.xwork2.inject.ContainerImpl$ConstructorInjector.<init>(ContainerImpl.java:333)
at com.opensymphony.xwork2.inject.ContainerImpl$5.create(ContainerImpl.java:299)
at com.opensymphony.xwork2.inject.ContainerImpl$5.create(ContainerImpl.java:298)
at com.opensymphony.xwork2.inject.util.ReferenceCache$CallableCreate.call(ReferenceCache.java:155)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at com.opensymphony.xwork2.inject.util.ReferenceCache.internalCreate(ReferenceCache.java:81)
at com.opensymphony.xwork2.inject.util.ReferenceCache.get(ReferenceCache.java:121)
at com.opensymphony.xwork2.inject.ContainerImpl.getConstructor(ContainerImpl.java:578)
at com.opensymphony.xwork2.inject.ContainerImpl.inject(ContainerImpl.java:476)
at com.opensymphony.xwork2.inject.ContainerImpl$7.call(ContainerImpl.java:517)
at com.opensymphony.xwork2.inject.ContainerImpl.callInContext(ContainerImpl.java:565)
at com.opensymphony.xwork2.inject.ContainerImpl.inject(ContainerImpl.java:515)
at com.opensymphony.xwork2.config.impl.LocatableFactory.create(LocatableFactory.java:32)
at com.opensymphony.xwork2.inject.ContainerBuilder$4.create(ContainerBuilder.java:135)
at com.opensymphony.xwork2.inject.Scope$2$1.create(Scope.java:49)
at com.opensymphony.xwork2.inject.ContainerImpl$ParameterInjector.inject(ContainerImpl.java:447)
at com.opensymphony.xwork2.inject.ContainerImpl.getParameters(ContainerImpl.java:462)
at com.opensymphony.xwork2.inject.ContainerImpl.access$000(ContainerImpl.java:48)
at com.opensymphony.xwork2.inject.ContainerImpl$MethodInjector.inject(ContainerImpl.java:288)
at com.opensymphony.xwork2.inject.ContainerImpl$2.call(ContainerImpl.java:117)
at com.opensymphony.xwork2.inject.ContainerImpl$2.call(ContainerImpl.java:115)
at com.opensymphony.xwork2.inject.ContainerImpl.callInContext(ContainerImpl.java:558)
at com.opensymphony.xwork2.inject.ContainerImpl.injectStatics(ContainerImpl.java:114)
at com.opensymphony.xwork2.inject.ContainerBuilder.create(ContainerBuilder.java:495)
at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:170)
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:55)
at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:371)
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:424)
at org.apache.struts2.dispatcher.FilterDispatcher.init(FilterDispatcher.java:213)
at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:273)
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:254)
at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:372)
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:98)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4562)
at org.apache.catalina.core.StandardContext$2.call(StandardContext.java:5240)
at org.apache.catalina.core.StandardContext$2.call(StandardContext.java:5235)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.ClassNotFoundException: org.apache.velocity.app.VelocityEngine
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1676)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:316)
... 53 more
竟然报出需要velocity相关包,那好吧,我的项目是用maven来做管理的,在pom.xml里加上相关依赖如下:
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-tools</artifactId>
<version>2.0</version>
</dependency>
再次重起tomcat后,一切正常,可以看到jrebel关键信息在console里输出:
JRebel: Directory 'E:\projects\cmac\target\classes' will be monitored for changes.
JRebel: Directory 'E:\projects\cmac\target\test-classes' will be monitored for changes.
JRebel: Directory 'E:\projects\cmac\src\main\webapp' will be monitored for changes.
4、如果你使用maven发布并启动tomcat,那么需要安装jrebel-maven-plugin。本文前面提到只是满足开发阶段而且启动tomcat方式不是使用mvn命令方式,因此不需要安装jrebel-maven-plugin。
Spring利用注释方式实现IoC
现在大部分java项目有使用Spring框架,为了能使Jrebel更好的对Spring相关资源发生热布署作用,就得充分使用注释的方式实现依赖注入。这里对Spring实现注释方式作一下最简单的介绍,首先在applicationContext.xml里配置如下两行代码:
<context:annotation-config/>
<context:component-scan base-package="*"/>
简单的说,以上的配置让spring支持了我们将要实现的注释依赖注入。以下以登录为实例,按action层、业务层、数据库操作层、PO层分别新建四个类:
LoginAction.java//struts action
UserServiceImpl.java//business layer
UserDaoImpl.java//dao layer
User.java //pojo
那么怎样通过注释方式进行调用的呢,首先给要被调用的类加上@Component注释,Spring为了区分不同层次的类,分别定义了以下四种注释
@Reposity
@Service
@Controller
@Component
目前阶段这四个注释实际上效果是一样的,我们约定如下:PO类如有需要使用@Reposity注释;Dao和Service使用@Service注释;Action使用@Controller注释;剩余分不出层次的类使用@Component注释。
如本例,action、service、dao分别加上注释
@Scope("prototype")
@Controller("loginAction")
public class LoginAction extends BaseAction{
}
@Service("userService")
public class UserServiceImpl implements UserService{
}
@Service("userDao")
public class UserDaoImpl extends BaseDao implements UserDao{
}
Scope注释默认是singleton,可以缺省。使用这四个标签时,如果不使用参数值,那么spring会按自己规范取名,比如LoginAction,使用@Controller()注释,默认取名为loginAction。取好了名,相当于在配置文件里配置了一组bean,接下来看怎么注入依赖,比如LoginAction要调用UserService,代码片段如下:
@Scope("prototype")
@Controller("loginAction")
public class LoginAction extends BaseAction{
…
@Autowired
Private UserService userService
…
}
就这么简单,添加xwork.xml配置,新加跳转页面,这些操作统统不用重起服务。
弹出Continue or Terminate疑问
装上jrebel后,可以进入你的tomcat/conf/context.xml或server.xml,其中有一个参数reload=true,把它改成false。表示关闭tomcat自身的热布署,在eclipse里启动tomcat,修改了类,有时还是会弹出Continue or Terminate框,难道是个Bug?不得而知。不过有jrebel在不用担心,继续continue,会发现你的修改是有效的。只有碰到前面提到的不适合jrebel热布署的场景时,即使没弹出Continue or Terminate提示框,你也要自己重起服务。
Jrebel官方对热布署支持的场景列表(查看官网说明http://www.zeroturnaround.com/jrebel/features/)
Java EE Support |
Jrebel |
JVM Hot Swap |
Time to reload |
< 1s |
< 1s |
No memory leak |
YES |
YES |
Changes to method bodies |
YES |
YES |
Adding/removing Methods |
YES |
NO |
Adding/removing constructors |
YES |
NO |
Adding/removing fields |
YES |
NO |
Adding/removing classes |
YES |
NO |
Adding/removing annotations |
YES |
NO |
Changing static field value |
YES JRebel 3.0+ |
NO |
Adding/removing enum values |
YES JRebel 3.0+ |
NO |
Changing interfaces |
YES |
NO |
Replacing superclass |
NO |
NO |
Adding/removing implemented interfaces |
NO |
NO |
Skip builds for WAR directories |
YES |
YES |
Skip builds for .WAR/.EAR class updates |
YES |
YES |
Skip builds for .WAR/.EAR resource updates |
YES |
NO |
Map multiple source dirs to one .WAR/.EAR target dir |
YES |
NO |
Map classes and resources with include/exclude patterns |
YES |
NO |
Map multiple source dirs with Ant-style patterns |
YES |
NO |
Use system properties to make mapping machine-independent |
YES |
NO |
Maven plugin |
YES |
NO |
JSP EL changes |
YES |
NO |
JSP Scriptlet changes |
YES Enterprise Add-on |
NO |
EJB 1.x session bean interface changes |
YES Enterprise Add-on |
NO |
EJB 2.x session bean interface changes |
YES Enterprise Add-on |
NO |
EJB 3.x session bean interface changes |
YES JRebel 3.0+ |
NO |
JSF changes (Mojarra) |
YES JRebel 3.0+ |
NO |
JPA changes (Hibernate, EclipseLink, TopLink, OpenJPA) |
YES JRebel 3.0+ |
NO |
CDI changes (Weld) |
YES JRebel 3.0+ |
NO |
ResourceBundle |
YES |
NO |
Spring Framework 2.x or later |
YES |
NO |
Hibernate |
YES JRebel 3.0+ |
NO |
JBoss Seam 2.x or later |
YES JRebel 3.0+ |
NO |
Google Guice |
YES |
NO |
Stripes 1.x or later |
YES |
NO |
Apache log4j 1.2.x or later |
YES |
NO |
Apache Struts 1.x |
YES |
NO |
Apache Struts 2.x or later |
YES |
NO |
Apache Tapestry4 |
YES |
NO |
Apache Velocity |
YES |
NO |
Apache Wicket |
YES |
NO |
CgLib |
YES JRebel 3.0+ |
NO |
Javassist |
YES JRebel 3.0+ |
NO |
Atlassian Confluence plugins |
YES |
NO |
ClassWorlds |
YES Beta |
NO |
Apache Felix |
YES Beta |
NO |
Eclipse Equinox |
YES Beta |
NO |
IntelliJ IDEA 7.x, 8.x plugins |
YES Beta |
NO |
NetBeans plugins |
YES Beta |
NO |
Jrebel对第三方框架支持对应表
查看官网http://www.zeroturnaround.com/jrebel/features/frameworks/
相关推荐
JRebel一款热部署插件,方便开发人员实现代码修改,自动发布,节约开发时间。本资源里面讲述了JRebel的安装以及使用说明,方便刚接触的码农们。
《JRebel 使用详解:实现Web工程的热部署》 在软件开发过程中,尤其是在Java领域,经常需要频繁地测试和调试代码,而每次修改代码后都需要重新编译、打包、部署,这一过程既耗时又降低了开发效率。为了解决这个问题...
### 四、JRebel使用 1. **启动应用**:使用JRebel启动你的Java应用程序。这通常意味着通过IDE的Run/Debug配置,选择JRebel作为运行时配置。 2. **实时更新**:在编码过程中,当你保存代码更改后,JRebel会自动重新...
《MyEclipse 7.5集成JRebel安装与使用详解》 MyEclipse作为一款强大的Java集成开发环境,深受广大开发者喜爱。然而,频繁的类加载和应用重启往往消耗了大量时间,降低了开发效率。这时,JRebel的出现为开发者带来了...
**JRebel 热插件使用手记** JRebel 是一款强大的 Java 开发工具,它能够实现在不重启应用服务器的情况下实时更新代码,极大地提高了开发效率。本文将详细介绍 JRebel 的安装、配置以及如何在实际开发中充分利用其热...
4. **JRebel配置文件**:JRebel使用一个名为"jrebel.properties"的配置文件来控制其行为。用户可以根据需要自定义配置,例如排除某些不希望实时更新的文件或目录。 5. **运行与调试**:在Eclipse中启动或调试应用时...
8. **3rd-party-source**:这个目录可能包含了JRebel使用的部分第三方源码,对于开发者来说,这是一个宝贵的参考资料,可以更好地理解和使用JRebel。 安装JRebel的过程通常如下: 1. 解压下载的"update-site,...
而“JRebel for IntelliJ IDEA”相关的网页文件可能是官方文档或教程,提供了更深入的JRebel使用指南。 总的来说,这种组合提供了一个高效的开发环境,使得Java Web开发者能够在快速迭代和调试过程中节省大量时间。...
**优化JRebel使用体验:** 1. **JRebel配置优化**: 根据项目需求调整`jrebel.properties`配置,例如排除不需要热部署的库,以减少内存占用。 2. **缓存清理**: 如果遇到热部署不生效的情况,可以尝试清除JRebel的...
IDEA热部署插件,jrebel使用相关技术资料内存下载解压即可使用,
许可证服务器的作用是验证和管理用户的许可证,确保用户有权使用JRebel。"jrebel的license简易服务器"就是一种简化版的许可证服务器,通常用于提供180天的试用期,方便开发者在项目初期进行测试和评估。 **2. 安装...
**JRebel插件安装与使用详解** JRebel是一款专为Java开发者设计的JVM插件,它的主要功能是在代码改动后无需重启应用服务器,就能实时看到代码更新的效果,极大地提高了开发效率。在IntelliJ IDEA(简称IDEA)这样的...
**JRebel插件安装指南** JRebel是一款强大的Java...通过以上步骤,你应该能够成功地在Eclipse中安装并使用JRebel插件,实现快速的代码热部署,提高开发效率。记得及时更新JRebel版本,以获得最新的功能和性能优化。
安装jrebel插件后找到C盘下的.jrebel文件,直接解压替换就可以用了。
4. **启动应用**:使用配置好的JRebel 模式启动应用,此时JRebel 将自动监听并处理代码变化。 **三、使用技巧** 1. **热部署策略**:JRebel 提供了多种热部署策略,可以根据项目规模和性能需求选择合适的策略。 2...
最全最详细的JRebel的安装、破解、使用教程, 资源中包括三个文件: update-site.zip(JRebel6.4.3离线安装包) jrebelCracked.rar(JRebel6.4.3破解包) Myeclipse2015+JRebel插件的安装、配置、使用教程.docx
Jrebel 离线激活配置 使用压缩包的文件覆盖替换本地 Jrebel 文件 本地 jrebel 配置文件一般在:C:\Users\(用户名)\.jrebel
2.下载jrebel破解文件,放到eclipse的jrebel插件目录覆盖: plugins\org.zeroturnaround.eclipse.embedder_6.5.0.RELEASE\jrebel 3.启动eclipse 查看window->preferences->jrebel 会提示没有license,无视他吧,...
JRebel and XRebel 插件在idea中的使用和安装
此外,这个版本还增强了对各种框架和库的支持,如Spring、Hibernate、Struts等,确保开发者在使用这些流行技术时也能享受到JRebel带来的便利。 对于IDEA用户来说,集成JRebel的过程简单直观。用户只需下载并安装jr-...