框架本身已提供了一个servlet DispatchServlet, 它会依据初始化参数构造一个执行器。 在运行时,所有到这个servlet的请求都会被交给这个执行器来处理。

它还提供了一些用于扩展和整合其他框架(比如Spring、Velocity、FreeMarker)的初始化参数。

你只需要将这个servlet添加到应用的web.xml中, 配置一些初始化参数,然后设置它可以处理URL即可。

下面是一个配置示例:

<servlet>
	<servlet-name>dispatchServlet</servlet-name>
	<servlet-class>org.soybeanMilk.web.servlet.DispatchServlet</servlet-class>
	<init-param>
		<param-name>encoding</param-name>
		<param-value>UTF-8</param-value>
	</init-param>
	<init-param>
		<param-name>soybean-milk-config</param-name>
		<param-value>/WEB-INF/soybean-milk-config.xml</param-value>
	</init-param>
	<init-param>
		<param-name>external-resolver-factory-key</param-name>
		<param-value>mySpringAppContextResolverFactory</param-value>
	</init-param>
	<init-param>
		<param-name>webObjectSoruce-factory-class</param-name>
		<param-value>my.MyWebObjectSourceFactory</param-value>
	</init-param>
	<init-param>
		<param-name>application-executor-key</param-name>
		<param-value>myWebExecutor</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>dispatchServlet</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>

上面这个示例包含了DispatchServlet允许的所有初始化参数:

下面将详细介绍这几个初始化参数的作用:

encoding(可选)

设置servlet编码。

如果你没有定义这个初始化参数,框架将使用默认的“UTF-8”编码。

soybean-milk-config(可选)

指定框架配置文件的位置。它可以是类路径的资源文件,比如“my/config/soybean-milk.cfg.xml”; 也可以是应用的“/WEB-INF”目录下的文件,比如“/WEB-INF/cfg/soybean-milk.cfg.xml”。

如果你没有定义这个初始化参数,框架将会从从默认的“/WEB-INF/soybean-milk.cfg.xml”配置文件初始化。

external-resolver-factory-key(可选)

指定外部解决对象工厂在应用(ServletContext)中的关键字。 如果你设置了这个初始化参数,DispatchServlet将会从应用中查找外部解决对象工厂并将它整合到框架中。

你可以使用这个初始化参数来整合其他框架,比如IOC容器Spring和Guice。

下面是一个整合Spring的过程示例:

首先,定义一个解决对象工厂类:

public class SpringResolverFactory implements ResolverFactory
{
	private BeanFactory beanFactory;
	
	public MySpringResolverFactory(BeanFactory beanFactory)
	{
		this.beanFactory=beanFactory;
	}
	
	@Override
	public Object getResolver(Serializable resolverId)
	{
		return beanFactory == null ? null : beanFactory.getBean(resolverId);
	}
}

定义一个应用监听器,并把它配置在web.xml中Spring初始化监听器之后:

public class SpringResolverFactoryInitListener implements ServletContextListener
{
	public void contextDestroyed(ServletContextEvent event)
	{
		
	}
	
	public void contextInitialized(ServletContextEvent event)
	{
		ServletContext context=event.getServletContext();
		
		BeanFactory springContext=WebApplicationContextUtils.getWebApplicationContext(context);
		SpringResolverFactory srf=new SpringResolverFactory(springContext);
		
		context.setAttribute("springAppContextResolverFactory",rf);
	}
}

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
    <listener-class>my.SpringResolverFactoryInitListener</listener-class>
</listener>

然后,将你的DispatchServlet初始化参数external-resolver-factory-key的值设置为“springAppContextResolverFactory”。

这样,你就可以在框架配置文件<invoke>标签的resolver属性中使用在Spring中定义的那些<bean>id了。

比如,假设有下面的Spring配置:

<bean id="helloWorldBean">  
	....
</bean> 

那么你可以在SoybeanMilk配置中直接调用这个bean的方法:

<action name="/helloWorld.do">  
	<invoke> request.message=helloWorldBean.helloWorld() </invoke>  
	<target url="/helloWorld.jsp" />  
</action> 

webObjectSoruce-factory-class(可选)

设置自定义的WEB对象源工厂。 设置它,你可以让框架使用你自定义的WEB对象源。 比如,自定义一个支持更多作用域的WEB对象源,从而使调用方法的参数和返回结果支持更多的作用域。

你可以使用这个初始化参数来整合其他视图层框架,比如Velocity和FreeMarker。

下面是整合Velocity的过程示例:

首先,定义如下MyWebObjectSourceFactory

package my;
public class MyWebObjectSourceFactory implements WebObjectSourceFactory
{
	@Override
	public WebObjectSource create(HttpServletRequest request, HttpServletResponse response,
			ServletContext application)
	{
		MyWebObjectSource os=new MyWebObjectSource(request, response, application);
		Context vc=new VelocityContext();
		os.setVelocityContext(vc);
		
		request.setAttribute("myVelocityContext", vc);
		
		return os;
	}
	
	protected static class MyWebObjectSource extends WebObjectSource
	{
		private Context velocityContext;
		public Context getVelocityContext() {
			return velocityContext;
		}
		public void setVelocityContext(Context velocityContext) {
			this.velocityContext = velocityContext;
		}
		@Override
		protected Object getWithUnknownScope(String scope, String keyInScope, Class<?> objectType)
		{
			if("vm".equals(scope))
				return velocityContext.get(keyInScope);
			else
				return super.getWithUnknownScope(scope, keyInScope, objectType);
		}
		@Override
		protected void setWithUnknownScope(String scope, String keyInScope, Object obj)
		{
			if("vm".equals(scope))
				velocityContext.put(keyInScope, obj);
			else
				super.setWithUnknownScope(scope, keyInScope, obj);
		}
		
		//...
	}
}
并将DispatchServlet初始化参数webObjectSoruce-factory-class的值设置为“my.MyWebObjectSourceFactory”。

然后,编写如下Velocity视图处理Servlet用于处理*.vm请求

public class MyVelocityViewServlet extends HttpServlet
{
	//...
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException
	{
		Context vc=(Context)req.getAttribute("myVelocityContext");
		
		//...
	}
	
	//...
}

完成!

现在,如果你这样配置动作

<action name="/myVelocityTest.do">
    <invoke>
        vm.myResult = myResolver.method( vm.arg0, request.arg1 );
    </invoke>
	<target url="/myVelocityTest.vm" />
</action>

那么你将可以在“myVelocityTest.vm”模板中使用“myResult”对象。

application-executor-key(可选)

设置DispatchServlet创建的执行器在应用(ServletContext)中的保存关键字,这样你便可以在需要时访问到此框架的所有内容。

如果你没有定义这个初始化参数,DispatchServlet将不会在应用中保存它创建的执行器