R uby on Rails有个设计思想是:用编码规定代替繁琐的配置文件 。jvm平台已经有一些类似ror的实现,比如 grails:http://docs.codehaus.org/display/GRAILS/2006/03/29/Groovy+on+Rails+(Grails)+0.1+Released 虽然由于java自身的局限,它很难做出像ruby或者groovy那样动态语言那样随心所欲的动作,但是利用它的运行时反射、动态代理等特性来尽可能体现“用编码规定代替繁琐的配置文件”这一思想。下面就转入正题。
ServletAPI对HTTP协议进行了封装,通过配置Web.xml来把不同的请求转发给不同的servlet来处理。Web框架则用一个ActionServlet,根据自己的对Action的定义来转发请求。 抛开那些繁琐的配置文件,设想一下这样一种方法:
1.Web动作的处理和响应
假设这样一个POST请求:
<
form
action
="logic/group/NewTopic"
method
="post"
>
Web动作实现Bean:
org.qqsns.web.logic.group.NewTopic
注意后面的logic/group/NewTopic 和logic.group.NewTopic , 动作类和Web动作是通过请求路径和包名相互关联。 这样,对Web动作的响应就依赖于编译期的代码的组织结构 而不是执行期的配置文件 。这样的好处是避免了维护繁琐的配置文件,特别是在没有IDE支持的情况下。
org.qqsns.web.logic.group.NewTopic类是一个实现net.wff.servlet.WebAction接口的POJO,下面是NewTopic中execute的方法片段:
//
Only method must be implemented for interface net.wff.servlet.WebAction
public
String execute(HttpServletRequest request, HttpServletResponse response)
throws
ServletException, IOException
{ // return "redirect /success.html"; // 请求重定向 return " /success.jsp " ; // 请求转发 }
execute方法的返回值手动指定了一个转发或重定向的路径。
2.输入验证
普通的Web框架都带数据输入验证功能,一般复杂程度和功能强大与否成正比。 这里简单地要求从setter方法里抛出一个包含验证信息的异常,以此来实现输入异常处理。 普通setter方法
public
void
setName(String name)
{ this .name = name; }
添加输入验证后的setter方法
public
void
setName(String name)
throws
InputException
{ if (name.length() < 3 ) throw new InputException( " Topic name must has a length greater than 3 " ); this .name = name; }
WaterFallServlet是如何处理验证信息的:
WebAction wa
=
(WebAction)Class.forName(classPath).newInstance();
//
procces forwarding
try
{ ActionHelper.setProperties(request,wa); }
catch
(InputException e)
{ // return to input view // header:referer String rtn = request.getHeader( " referer " ); // clear old errors if (rtn.indexOf( " ? " ) != 1 ) { rtn = rtn.substring( 0 ,rtn.indexOf( " ? " )); } rtn = rtn + " ?error= " + URLEncoder.encode(e.getMessage(), " UTF-8 " ); response.sendRedirect(rtn); return ; }
这样验证信息通过请求参数传回到输入页面.
3.数据绑定
假设有这样的html输入:
<
input
type
="text"
name
="name"
/>
<
input
type
="text"
name
="number"
/>
<
input
type
="text"
name
="price"
/>
下面是NewTopic中execute的方法全部:
public
String execute(HttpServletRequest request, HttpServletResponse response)
throws
ServletException, IOException
{ System.out.println(getName()); System.out.println(getNumber()); System.out.println(getPrice()); System.out.println(getLength()); return " /success.html " ; }
自动从request注入parameter,这也许是很多人喜欢Struts DynamicActionForm的原因之一。 不过这里实现更类似多了类型转换的<jsp:setProperty name="bean" property="*"/> 因为Name的类型是String,Number的类型是Integer,Price的类型是float,length的类型是double.至于其他复杂的类型,也许jsf的转换器是个更好的主意。 这样就初步解决了数据的输入绑定和验证。余下的就是业务逻辑的问题。WaterfallWebFramework源代码:http://www.blogjava.net/Files/zqc/WaterfallWebFramework.rar (只有一个配置文件,其中只有1行配置信息! )
以上就是框架的主要功能。用编码规定代替配置文件 ,也许这会是一种更加高效率的开发方式。