如同Extjs这样的工具对于做管理后台是非常必要的。管理后台使用人数少,操作多,交互性很强,对控件的功能要求较高。又因为大多是内网操作,所以较大的js库也不是问题。所以像Extjs这样的库,可以很好的满足这样的需求。
我在寻找一个Extjs的替代品,既能产生功能强大且美观的页面效果,又不必手写Javascript。最后找到了Vaadin,其官网是 http://www.vaadin.com。
Vaadin内部使用了gwt,但提供了一套现代感比较强、比较华丽的主题,控件也很多。通过其官方演示页面就能看到:http://demo.vaadin.com/sampler
如gwt一样,vaadin也是在后台写java代码,自动生成对应的js代码供浏览器调用。这样的好处是相当明显的:
Vaadin还提供了一个Eclipse插件,以可视化的方式来设计界面。
一、基本运行方式
Vaadin程序运行于servlet容器。首先要有一个类继承于com.vaadin.Application,它是程序的入口。例如这个例子:
import com.vaadin.Application;
import com.vaadin.ui.*;
public class TestvaadinApplication extends Application {
@Override
public void init() {
Window mainWindow = new Window("Testvaadin Application");
Label label = new Label("Hello Vaadin user");
mainWindow.addComponent(label);
setMainWindow(mainWindow);
}
}
它实际上是一个servlet,我们需要在web.xml中定义:
<servlet-name>TestvaadinApplication</servlet-name>
<servlet-class>com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class>
<init-param>
<description>Front</description>
<param-name>application</param-name>
<param-value>com.example.testvaadin.TestvaadinApplication</param-value>
</init-param>
<servlet-name>TestvaadinApplication</servlet-name>
<url-pattern>/*</url-pattern>
然后在浏览器中访问 http://localhost:8080/myapp 即可看到这样的内容:
二、修改后代码后如何生效
我以debug方式运行tomcat,按说只要没有修改类结构,所做的修改应该能马上热部署。
但奇怪的是,我修改了java代码中一个Label上的文本后,刷新页面,却没有看到任何变化。打开一个新的浏览器访问该页面,却可以看到修改后的内容。这是怎么回事?在vaadin论坛上看到不少人问这个问题,终于弄明白,原来vaadin把很多东西都保存在session中,包括页面上的这些组件的内容等。当修改代码后,虽然后台代码变了,但是保存在session中的内容并没有变,所以只能在新窗口中看到修改变化。
对于这种情况,除了重启tomcat外,还可以:
虽然有些不方便,但考虑到vaadin必须以某种方式实现stateful,也只能这样了。好在第二种方法还可以接受,因为那个窗口可以一直存在,不用每次都输入?deubg。
三、如何分开前后台
如果程序中有几个独立的入口,比如前台和后台分开,通过不同的url访问,应该怎么做?
可以在程序中为每个入口定义一个类,继承于Application。因为它就相当于一个servet,我们只需要在web.xml中分别定义对应的映射关系即可。
例如,我们让用户在浏览器中输入/admins时,访问管理后台的页面,怎么做?
再定义一个类(我这里是用xtend写的):
class AdminApplication extends Application {
override init() {
val mainWindow = new Window("管理平台");
val label = new Label("你好管理员");
mainWindow.addComponent(label);
setMainWindow(mainWindow);
}
}
web.xml中也要有相应增加:
<servlet-name>AdminApplication</servlet-name>
<servlet-class>com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class>
<init-param>
<description>Admin Panel</description>
<param-name>application</param-name>
<param-value>com.example.testvaadin.AdminApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<servlet-name>AdminApplication</servlet-name>
<url-pattern>/admins/*</url-pattern>
重启tomcat后访问:
注意url的变化。
需要注意的是,一定要保证该路径/VAADIN会被vaadin处理。先看一下firebug的记录:
原来vaadin去取那些组件资源时,要访问/VAADIN。所以如果在web.xml中,没有把根目录映射到某个继承于com.vaadin.Application的类时,需要增加类似于下面这样的映射关系:
<servlet-name>AdminApplication</servlet-name>
<url-pattern>/VAADIN/*</url-pattern>
四、最简单的页面需要下载多少K资源
对于一个最简单的页面,需要下载800多K的资源。其中样式表144.5K,而js文件为686.4K,个头还不小。所以只能用于管理后台。
五、如何与其它框架结合
如前所说,vaadin这样的大个头只适合做管理后台,对于前台,还得要用传统的css方案解决。这样必然需要使用另一种框架与vaadin结合。
如果是springmvc这样的mvc框架比较简单,因为它也是基于servlet,只需要在web.xml中再定义一个入口即可。
如果是play,因为它默认不是基于servlet的,所以只能分开开发,然后将play的程序打包为war,再将两者合并在一起,修改web.xml,丢在tomcat下。这种方式理论上可行,但是还需要实际测试才行。
还有一种方式就是,将前后台完全分开,写成两个独立的应用,放在tomcat中。然后将对首页的访问重定向至某一个应用。
最后的方法是,两个程序完全分开,也不需要都放在tomcat下。在前面用nginx这样的前端通过反向代理,将前后台的请求分别映射到两个应用上。
这些方法最简单的还是第一种。