WebWind介绍

447928011 贡献于2011-08-17

作者 微软用户  创建于2011-05-11 08:02:00   修改者微软用户  修改于2011-05-12 07:01:00字数12356

文档摘要:WebWind是一个Java MVC框架。和常见的MVC框架如Struts不同,WebWind天生支持用户友好的URL,让Web应用程序对搜索引擎更加友好,开发更简单。
关键词:

 WebWind介绍 WebWind是一个Java MVC框架。和常见的MVC框架如Struts不同,WebWind天生支持用户友好的URL,让Web应用程序对搜索引擎更加友好,开发更简单。 网站:http://code.google.com/p/webwind/wiki/DeveloperConfig 功能 WebWind提供了非常高效但却简单的方法来简化Web应用程序的开发: · 友好的URL支持,例如“/blog/display/20090909”。 · 将HTTP处理映射到自定义的方法。 · 支持拦截器以便处理事务、日志等功能。 · 支持ExceptionHandler实现统一的异常处理入口。 · 支持文件上传。 和Struts等传统MVC框架不同,WebWind不需要开发者实现特定的接口如 “Action”或“Controller”。你可以简单地直接在任何类中定义不同方法来处理URL: public class Blog {     @Mapping("/hello/$1")     public String hello(String name) {         return "

Hello, " + name + "

";     }     @Mapping("/")     public Renderer index() throws Exception {         return new TemplateRenderer("/index.jsp");     } } 配置 WebWind的配置非常简单,请按照以下步骤: 在web.xml中声明DispatcherServlet 首先,请在web.xml中添加一个Servlet的声明:     dispatcher     org.expressme.webwind.DispatcherServlet             container         Guice                 modules         org.expressme.sample.BlogModule                 template         Velocity         0     dispatcher     / 请注意,所有参数均是大小写敏感的。 参数“container”用于指定您使用的IoC容器,WebWind内置支持两种IoC容器:Spring和Guice。 如果希望使用其他IoC容器,可以指定完整的类名。请参考如何集成其他IoC容器. 参数template用于指定如何渲染页面,WebWind内置支持两种模板:Jsp和Velocity。 Jsp是缺省的模板。如果指定Velocity作为模板,则还需要在/WEB-INF/目录下放置一个velocity.properties的配置文件。 如果希望使用其他模板引擎,例如FreeMarker,请参考[DeveloperExtension#集成第三方模板引擎 如何集成第三方模板引擎]。 是标准的Servlet配置,设置为0可以强制Web服务器立即加载并初始化该Servlet。 非常重要的一点是,在servlet-mapping中,必须将“/”映射到DispatcherServlet。和Struts(或其他MVC框架)映射*.do不同,WebWind让你完全控制并管理URL结构。以下URL均被支持: · /blog/display/20090909 · /post/2009/09/09/12345.html · /user/1002/35af98c260_1.js 因此,必须将/映射到WebWind提供的DispatcherServlet。 如果你使用Guice作为IoC容器,则module参数是必须的,它指定了Guice需要的Module的完整类名。 如果你使用Spring作为IoC容器,则需要添加以下配置到web.xml中,以便在WebWind启动前加载Spring:     org.springframework.web.context.ContextLoaderListener Spring默认的配置文件applicationContext.xml必须放置到/WEB-INF/目录下。 以上就是所有的配置!无需额外的配置文件! 继续学习第一个'Hello, world'应用程序。 另一种替代方案 如果你已经将/映射到了某个Servlet,WebWind还提供了另一个DispatcherFilter,可以替代DispatcherServlet:     dispatcher     org.expressme.webwind.DispatcherFilter             container         Guice                 modules         org.expressme.sample.BlogModule                 template         Velocity         dispatcher     /* 区别在于: · 没有配置。 · 参数是/*而不是/。 Hello, world WebWind版本的'Hello, world'非常简单: import org.expressme.webwind.Mapping; public class MyPage {     @Mapping("/hello")     public String hello() {         return "

Hello, world

";     } } 注意到不需要任何框架提供的如Action或Controller之类的接口。URL映射通过Java 5的注解直接定义在方法上。 确保该JavaBean被你的IoC容器管理。启动Web服务器就可以在浏览器中看到如下Web页面: 传递参数 让我们做一个小小的扩展,让这个应用程序能向所有人说'Hello'。你可以直接在URL后添加一个参数,例如,/hello?name=michael,并在旧式的MVC框架中处理参数。不过,/hello/michael这样的URL看起来是不是更简单: @Mapping("/hello/$1") public String hello(String name) {     return "

Hello, " + name + "

"; } 现在,Web页面显示如下: 你也许已经猜到了,URL中的$1将被自动赋值到方法hello(String)的第一个参数name变量中。完全正确! 以上两个方法还可以合并到一起,不会产生冲突: import org.expressme.webwind.Mapping; public class MyPage {     @Mapping("/hello")     public String hello() {         return "

Hello, world

";     }     @Mapping("/hello/$1")     public String hello(String name) {         return "

Hello, " + name + "

";     } } 处理URL 正如你看到的,WebWind不需要实现任何特定接口,可以在一个Class中定义多个方法,每一个带有@Mapping的方法都可以处理一个URL。 能够处理URL的方法必须满足: · 必须是public,并且不是static。 · 必须返回void、String或org.expressme.wind.Renderer。 · 方法参数必须被WebWind支持。参考支持的参数类型。 · 方法参数的个数要和URL中参数个数匹配。 方法可以抛出任何类型的异常。 定义URL WebWind在内部使用正则表达式来处理URL,不过,正则表达式不是那么容易编写,因此,WebWind使用易读的格式如/user/$1/$2.html来表示URL。 当你在URL中定义了参数后,WebWind就自动将URL的参数传递给方法参数。URL参数的占位符是$,索引从1开始,最多至9,因此,你可以最多传递9个参数。 每个$n(n=1至9)都将匹配URL的某一组值,包括空字符串,但是,不会匹配包含/的字符串,因此: /user/$1.html将匹配/user/123456.html,但不会匹配/user/123/456.html。 因此,以下的URL定义是无效的: · /user/$2.html:因为$1没有找到。 · /blog/$1/$3.html: 因为$2没有找到。 以下的URL定义是有效的,但不推荐使用: · /user/$1$2.html:因为$1永远匹配到空字符串。 · $1.html:无法匹配到任何URL,因为URL总是以/开头。 URL中的参数将自动被转换为方法参数的合适类型。例如: @Mapping("/user/$1/$2.html") public void handle(long userId, int postId) throws Exception {     // $1被转换为long,$2被转换为int... } 支持的参数类型 不是所有的Java类型都能被转换,因为WebWind必须能够将String转换到正确的Java类型。内置的支持类型包括String和所有基本类型以及其包裹类型(int,Integer,boolean,Boolean等): 类型 转换方法 可能抛出异常 java.lang.String 无 无 boolean, Boolean Boolean.valueOf(String) 无 char, Character String.charAt(0) IllegalArgumentException byte, Byte Byte.parse(String) NumberFormatException short, Short Short.parse(String) NumberFormatException int, Integer Integer.parse(String) NumberFormatException long, Long Long.parse(String) NumberFormatException float, Float Float.parse(String) NumberFormatException double, Double Double.parse(String) NumberFormatException TODO: How to add more types 选择IoC容器 正如我们讨论过的,WebWind从不管理任何Web组件,而是向IoC容器请求所有实例。WebWind内置支持两种IoC容器:Guice和Spring。 所有被IoC容器管理的组件都将被自动扫描,并提取标记有@Mapping的public方法。例如,定义带有两个URL映射的方法的类: public class Blog {     @Mapping("/hello/$1")     public String hello(String name) {         return "

Hello, " + name + "

";     }     @Mapping("/")     public Renderer index() throws Exception {         return new TemplateRenderer("/index.htm");     } } IoC容器中JavaBean的生命周期可以为Singleton或Prototype,不过要确保其是无状态的,而WebWind总是以Singleton模式持有这些Bean的实例。 使用Guice 如果你使用Guice作为IoC容器,则需要在web.xml中指定Module类:     modules     org.expressme.sample.BlogModule 参考配置以获得更多关于Guice的配置信息。 编写Module类: public class BlogModule implements Module {     public void configure(Binder binder) {         binder.bind(Blog.class).asEagerSingleton();     } } 使用Spring 如果你使用Spring作为IoC容器,则需要在Spring的配置文件(通常是applicationContext.xml)中定义Bean: 参考配置以获得更多关于Spring的配置信息。 需要支持更多IoC容器 如果你想使用除了Guice和Spring的其他IoC容器,你需要做更多的工作。 WebWind允许你使用任何IoC容器(例如HiveMind,PicoContainer等),通过编写自定义的ContainerFactory来实现,例如: package sample; import java.util.List; import org.expressme.wind.container.ContainerFactory; public class MyContainerFactory implements ContainerFactory {     public List findAllBeans() throws ServletException {         // TODO: return all objects managed by IoC container     }     public void init(Config config) throws ServletException {         // TODO: init or find IoC container instance     } } 你必须实现以上两个方法。对于有经验的开发人员来说很容易,请参考SpringContainerFactory.java和GuiceContainerFactory.java作为示例。 然后在web.xml中声明自定义ContainerFactory的完整类名:     container     sample.MyContainerFactory 使用模板 作为示例,可以直接返回一个简单的HTML如Hello, world!。不过,在真实世界中,复杂的Web页面通常由各种模板引擎生成。WebWind内置支持两种模板引擎:JSP和Velocity。 在WebWind中渲染一个模板是非常简单的: 1. 将所有数据放入Map中作为模型; 2. 创建一个TemplateRenderer并返回。 参考下面的例子: public class IndexPage {     @Mapping("/")     public Renderer index() {         Map model = new HashMap();         model.put("name", "Michael");         model.put("date", new Date());         return new TemplateRenderer("/index.jsp", model);     } } 如果没有配置任何模板,缺省的模板引擎是JSP。例如,上面的代码对应的模板index.jsp的内容看起来像这样:   Hello, <%=request.getAttribute("name") %>!   It is <%=request.getAttribute("date") %>! 如果使用Velocity作为模板,需要准备一个Velocity模板文件,例如,index.htm:   Hello, ${name}! It is ${date.toString()}! 参考配置以获得更多关于Velocity的配置信息。 需要支持更多模板引擎 如果你需要使用除JSP和Velocity之外的其他模板,你需要更多的工作。 WebWind允许你使用任何模板引擎(例如FreeMarker等),通过编写自定义的TemplateFactory来实现。例如: package sample; import org.expressme.wind.template.ContainerFactory; public class MyTemplateFactory implements TemplateFactory {     public Template loadTemplate(String path) throws Exception {         return new MyTemplate(path);     }     public void init(Config config) {         // TODO: init your template engine here...     } } 你需要实现以上两个方法。对于有经验的开发人员来说这很容易。参考JspTemplateFactory.java和VelocityTemplateFactory.java作为示例。 还需要实现MyTemplate类,并且从Template派生: package sample; import java.io.PrintWriter; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.expressme.wind.template.Template; public class MyTemplate implements Template {     private String path;     public MyTemplate(String path) {         this.path = path;     }     public void render(HttpServletRequest request, HttpServletResponse response, Map model) throws Exception {         String content = build_content_by_template(model);         PrintWriter pw = response.getWriter();         pw.write(content);         pw.flush();     } } 在web.xml中声明你的TemplateFactory的完整类名:     template     sample.MyTemplateFactory 使用拦截器 拦截器(Interceptor)和Servlet规范的Filter类似,但是,拦截器由IoC容器管理。WebWind自动从IoC容器中查找所有的拦截器。拦截器可以用来实现事务、日志等功能。 定义一个拦截器非常简单: import org.expressme.webwind.*; @InterceptorOrder(0) public class PerformanceInterceptor implements Interceptor {     public void intercept(Execution execution, InterceptorChain chain) throws Exception {         long start = System.currentTimeMillis();         try {             chain.doInterceptor(execution);         }         finally {             long last = System.currentTimeMillis() - start;             System.out.println("Execute " + last + " ms for URL: " + execution.request.getRequestURI());         }     } } 但是不要忘记调用chain.doInterceptor(execution),否则,处理HTTP请求的过程将终止。 一个以上的拦截器组成拦截器链。@InterceptorOrder用于指定每个拦截器的顺序,数字小的拦截器排在前面 处理异常 当处理一个HTTP请求抛出Exception时,ExceptionHandler可以处理所有Exception。你需要在IoC容器中实例化一个ExceptionHandler: public class MyExceptionHandler implements ExceptionHandler {     public void handle(HttpServletRequest request, HttpServletResponse response, Exception e) throws Exception {         // TODO: handle exception or re-throw it...     } } WebWind会自动检测到ExceptionHandler。如果没有定义任何ExceptionHandler,一个DefaultExceptionHandler将被使用。 它不做任何事情,仅仅打印出异常堆栈,供调试使用。如果定义了多个ExceptionHandler,WebWind仅使用第一个,并忽略其他的ExceptionHandler。 请注意,不能假定IoC容器中JavaBean是按某种顺序排列的。 推荐自定义ExceptionHandler,对于处理未登录的重定向非常有用。 处理文件上传 WebWind通过集成Commons FileUpload支持文件上传。无需任何配置,只需将commons-fileupload-1.2.x.jar放入/WEB-INF/lib/目录下即可。如果没有找到Commons FileUpload,文件上传功能就被禁用。 处理文件上传非常简单: public class FileUpload {     @Mapping("/fileupload")     public String post() throws Exception {         HttpServletRequest request = ActionContext.getActionContext().getHttpServletRequest();         if (request instanceof MultipartHttpServletRequest) {             MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;             // we are assume that file is uploaded with field name 'myfile':             String filename = multipartRequest.getFileName("myfile");             // now get file name like 'C:\WINDOWS\Notepad.ini'...             InputStream input = multipartRequest.getFileInputStream("myfile");             // TODO: read file content here...             input.close();             return "redirect:/upload-success.htm";         }         throw new IOException("Not a multipart request!");     } } 普通的Form字段可以通过HttpServletRequest.getParameter(String)正常读取。 常用匹配的正则表达式 匹配中文字符的正则表达式: [\u4e00-\u9fa5] 匹配双字节字符(包括汉字在内):[^\x00-\xff] 应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1) String.prototype.len=function(){return this.replace([^\x00-\xff]/g,"aa").length;} 匹配空行的正则表达式:\n[\s| ]*\r 匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/ 匹配首尾空格的正则表达式:(^\s*)|(\s*$) 应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现,如下: String.prototype.trim = function() { return this.replace(/(^\s*)|(\s*$)/g, ""); } 利用正则表达式分解和转换IP地址: 下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的Javascript程序: function IP2V(ip) { re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g //匹配IP地址的正则表达式 if(re.test(ip)) { return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1 } else { throw new Error("Not a valid IP address!") } } 不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下: var ip="10.100.20.168" ip=ip.split(".") alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1)) 匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* 匹配网址URL的正则表达式:http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)? 利用正则表达式去除字串中重复的字符的算法程序:[注:此程序不正确,原因见本贴回复] var s="abacabefgeeii" var s1=s.replace(/(.).*\1/g,"$1") var re=new RegExp("["+s1+"]","g") var s2=s.replace(re,"") alert(s1+s2) //结果为:abcefgi 我原来在CSDN上发贴寻求一个表达式来实现去除重复字符的方法,最终没有找到,这是我能想到的最简单的实现方法。思路是使用后向引用取出包括重复的字符,再以重复的字符建立第二个表达式,取到不重复的字符,两者串连。这个方法对于字符顺序有要求的字符串可能不适用。 得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1 s="http://www.9499.net/page1.htm" s=s.replace(/(.*\/){0,}([^\.]+).*/ig,"$2") alert(s) 利用正则表达式限制网页表单里的文本框输入内容: 用正则表达式限制只能输入中文:onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,)" onbeforepaste="clipboardData.setData(text,clipboardData.getData(text).replace(/[^\u4E00-\u9FA5]/g,))" 用正则表达式限制只能输入全角字符: onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,)" onbeforepaste="clipboardData.setData(text,clipboardData.getData(text).replace(/[^\uFF00-\uFFFF]/g,))" 用正则表达式限制只能输入数字:onkeyup="value=value.replace(/[^\d]/g,) "onbeforepaste="clipboardData.setData(text,clipboardData.getData(text).replace(/[^\d]/g,))" 用正则表达式限制只能输入数字和英文:onkeyup="value=value.replace(/[\W]/g,) "onbeforepaste="clipboardData.setData(text,clipboardData.getData(text).replace(/[^\d]/g,))"

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享文档获得金币 ] 2 人已下载

下载文档