This framework has a built-in servlet DispatchServlet for integration. It can construct an WebExecutor from its init parameters, and dispatching all requests to this WebExecutor at runtime.
It also has some init parameters for extending, or intergrating with other frameworks (Such as Spring, Velocity, Freeemarker).
You only need to add this servlet into you web.xml, then set some init parameters and the URL it can processing.
The following is an example:
<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>
It contains all the init parameters the servlet supported:
- encoding
- soybean-milk-config
- external-resolver-factory-key
- webObjectSoruce-factory-class
- application-executor-key
The following are detail specification of these init parameters:
Set the encoding of this servlet.
If you did not set it, "UTF-8" will be used as default.
soybean-milk-config (Optional)
Set the configuration file of this framework. It can be a file in classpath (such as "my/config/soybean-milk.cfg.xml"), or a file in "/WEB-INF" folder of your application (such as "/WEB-INF/cfg/soybean-milk.cfg.xml").
If you did not set it, "/WEB-INF/soybean-milk.cfg.xml" will be used as default.
external-resolver-factory-key (Optional)
Set the external ResolverFactory key in your application (ServletContext). If you set this parameter, the DispatchServlet will find external ResolverFactory with this key and integrate it.
You can integrate other IOC container (such as Spring or Guice) by setting this init parameter.
The following is a example of Spring integration:
First, you must write a ResolverFactory class:
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);
}
}
and a ServletContext listener with adding it after Spring init listener in web.xml:
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>
Then, setting external-resolver-factory-key value to be "springAppContextResolverFactory".
Now, you can use any id of <bean> defined in Spring as the resolver attribute of <invoke>.
For example, if there is a bean in Spring like this:
<bean id="helloWorldBean"> .... </bean>
Then, you can define its action like this:
<action name="/helloWorld.do"> <invoke> request.message=helloWorldBean.helloWorld() </invoke> <target url="/helloWorld.jsp" /> </action>
There is also a very simple way, by overriding the getInitExternalResolverFactory() method of DispatchServlet class:
package my.web;
public class DispatchServlet extends org.soybeanMilk.web.servlet.DispatchServlet
{
private static final long serialVersionUID = 1L;
@Override
protected ResolverFactory getInitExternalResolverFactory()
throws ServletException
{
final BeanFactory beanFactory=
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
return new ResolverFactory()
{
@Override
public Object getResolver(Serializable key)
{
if(beanFactory == null)
return null;
try
{
return beanFactory.getBean(key.toString());
}
catch(Exception e)
{
return null;
}
}
};
}
}
Then, you just need to use this DispatchServlet instead:
<servlet> <servlet-name>dispatchServlet</servlet-name> <servlet-class>my.web.DispatchServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>
webObjectSoruce-factory-class (Optional)
Set the customized WebObjectSourceFactory. You can make the framework to use your own WebObjectSource by setting this init parameter. For example, you can define an WebObjectSource that supporting more scopes, so that they can be used in the Invoke method arguments or result keywords.
You can use this init parameter to integrate some other View frameworks, such as Velocity or FreeMarker.
The following is a example of Velocity integration:
First, write a MyWebObjectSourceFactory class as following
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 getObjectFromUnknownScope(String scope, String keyInScope, Type expectType)
{
if("vm".equals(scope))
return velocityContext.get(keyInScope);
else
return super.getObjectFromUnknownScope(scope, keyInScope, expectType);
}
@Override
protected void setObjectToUnknownScope(String scope, String keyInScope, Object value)
{
if("vm".equals(scope))
velocityContext.put(keyInScope, value);
else
super.setObjectToUnknownScope(scope, keyInScope, value);
}
//...
}
}
And set the value of webObjectSoruce-factory-class to be "my.MyWebObjectSourceFactory".
Then, write a Servlet for processing Velocity request of "*.vm"
public class MyVelocityViewServlet extends HttpServlet
{
//...
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
Context vc=(Context)req.getAttribute("myVelocityContext");
//...
}
//...
}
That's OK!
Now, if you have an Action like this :
<action name="/myVelocityTest.do">
<invoke>
vm.myResult = myResolver.method( vm.arg0, request.arg1 );
</invoke>
<target url="/myVelocityTest.vm" />
</action>
You will be able to use "myResult" object in your "myVelocityTest.vm" template.
application-executor-key (Optional)
Set the WebExecutor object key in your application (ServletContext). It helps you getting all the information of this framework at runtime.
And noting will be saved in your application (ServletContext) if you did not set it.