公司介绍 产品展示 业务支持 解决方案 文档资料
网站导航 访客留言 技术论坛
     
  产品资料
  业界动态
     
  JAVA技术


首  页 > 文档资料 > JAVA技术  
 
  Spring中的Web映射机制

Spring的映射机制可以将将某些Web请求转交给特定的处理器(Handler)处理,Spring默认包含了两种处理映射机制:BeanNameUrlHandlerMapping和SimpleUrlHandlerMapping,下面我们将一个例子来说明如何使用好这两种处理映射来方便我们的开发,在以下的例子中,我们将牵涉到以下几个方面:xml-rpc、JasperReports和Velocity,在进行Demo之前,希望你能够对这些知识有所了解。

在企业应用开发中,我们通常会使用Servlet做Web映射来提供服务,如Web Service、Hessian、JBoss的http-invoker等,在这里我们需要如下要求,通过web方式查看JasperReports报表和Velocity的文件模板,同时要求将一些服务以xml-rpc方式发布。JasperReports的模板.japser文件加上提供的相应的数据库连接就可以形成JasperPrint对象,最终以pdf方式导出,输出到客户的浏览器端。Velocity的模板.vm文件加上提供的VelocityEngine就可以将模板以html文本导出到浏览器端。查看JasperReports模板和Velocity模板很相似,只需要提供相应的资源就可以成功导出,显示到客户端浏览器上。xml-rpc则是将服务发布出去,供其他客户端调用,如javascript、perl等,其中主要是提供和更新数据,因为这些语言可以实现一定的业务逻辑,这种形式的服务对应用的整合非常有帮助的。以上这三种形式都牵涉到资源的调用,如数据库连接、VelocityEngine、业务逻辑对象,这些对Spring的IoC机制来说,实现起来是非常方便的,也极大的简化了我们的开发。下面我们就这些问题进行实际操作。

Spring使用DispatcherServlet进行映射将web请求定位到指定处理器上,这个也是Spring的MVC基础,在这里我们进行设定,以保证映射的成功。在web.xml文件我们进行以下设置:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-hibernate.xml /WEB-INF/ServiceView-servlet.xml</param-value>
</context-param>
………
<!-- ServiceView:提供资源查看和服务调用 -->
<servlet>
<servlet-name>ServiceView</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServiceView</servlet-name>
<url-pattern>*.jasper</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServiceView</servlet-name>
<url-pattern>*.vm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServiceView</servlet-name>
<url-pattern>/xml-rpc/*</url-pattern>
</servlet-mapping>

在这里我们创建一个DispatcherServlet实例,名称为ServiceView,同时为该Servlet创建三个映射,完成我们需要的功能,Spring会按照规范,要求我们创建一个名为ServiceView-servlet.xml的文件,在该文件中进行相关设定。在这里将三种映射关系放在一个xml文件中进行设置,主要处于功能方面上的考虑,将相近功能的映射配置放在一个文件中,可以使结构更清晰,更容易维护。ServiceView-servlet.xml文件内容:

<?xml version="1.0" encoding="gb2312" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<!-- ServiceView:提供资源查看和服务调用 -->
<beans>
<!--处理JasperReports报表的Controller-->
<bean id="ViewJasperReportController" class="com.jetmaven.oa.ViewJasperReportController">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>

<!-- 处理Velocity模板的Controller-->
<bean id="ViewVelocityTemplateController" class="com.jetmaven.oa.ViewVelocityTemplateController">
<property name="engine">
<ref bean="VelocityEngine"/>
</property>
<property name="encoding">
<value>gb2312</value>
</property>
</bean>
<!--处理JasperReports和Velocity映射-->
<bean id="ServiceViewUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="*.jasper">ViewJasperReportController</prop>
<prop key="*.vm">ViewVelocityTemplateController</prop>
</props>
</property>
</bean>

<!-- 以下是通过BeanNameUrlHandlerMapping进行映射-->
<bean id="defaultHandlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 处理xml-rpc服务-->
<bean id="/service1" class="com.jetmaven.oa.XmlRpcController">
<property name="handlers">
<map>
<entry key="demo">
<bean class="com.jetmaven.oa.BasicService"></bean>
</entry>
</map>
</property>
</bean>
</beans>

在ServiceView-servlet.xml我们使用两种两种映射方式SimpleUrlHandlerMapping和BeanNameUrlHandlerMapping,JasperReports和Velocity采用SimpleUrlHandlerMapping,而xml-rpc采用BeanNameUrlHandlerMapping,所以我们在xml-rpc的Controller声明之前要声明BeanNameUrlHandlerMapping,保证BeanNameUrlHandlerMapping的实现。在xml-rpc的Controller声明中,我们声明的id是依据上下文(Context)进行的,如”/service1”,那么在调用时应包含servlet映射中加上前缀:xml-rpc,结果如下:http://localhost:port/webappname/xml-rpc/service1,这些你得注意一下。在文件中,我们利用到DataSource和VelocityEngine,这些信息在另一个Spring文件中申明。代码如下:

<!-- setting VelocityEngine-->
<bean id="VelocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="resourceLoaderPath">
<value>file:/e:/source/intellij/power_acl</value>
</property>
</bean>
<!-- setting database source-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/power_acl?autoReconnect=true</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>abc123</value>
</property>
</bean>

VelocityEngine的申明应当包含resourceLoaderPath,这样才能保证模板的成功加载。

我们已经将所有的配置设置好啦,下面我们要进行代码编写啦。通过Spring的IoC机制,你将发现代码编写容易多啦,这样犯错误的机会就少啦。

ViewVelocityTemplateController文件:
package com.jetmaven.oa;

import org.apache.velocity.app.VelocityEngine;
import org.springframework.ui.velocity.VelocityEngineUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
* @author <a href="mailto:youmail@yourdomain.com">yourname</a> Date: 2004-11-22
*/
public class ViewVelocityTemplateController implements Controller
{
private VelocityEngine engine;
private String encoding;

public VelocityEngine getEngine()
{
return engine;
}

public void setEngine(VelocityEngine engine)
{
this.engine = engine;

}

public String getEncoding()
{
return encoding;
}

public void setEncoding(String encoding)
{
this.encoding = encoding;
}

public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception
{
response.setContentType("text/html;charset=gb2312");
String relativeUri = request.getRequestURI().replaceFirst(request.getContextPath(), "");
File reportFilePath = new File(request.getSession(true).getServletContext().getRealPath(relativeUri));
if (reportFilePath.exists())
{
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(response.getOutputStream()));
VelocityEngineUtils.mergeTemplate(engine, relativeUri, encoding, getVelocityContextFromRequest(request), writer);
writer.flush();
writer.close();
} else
{
setError404(response);
}
return null;
}

/**
* 从request中构建VelocityContext对象(提取request中的属性值)
*
* @param request HttpServletRequest变量
* @return VelocityContext对象
*/
private Map getVelocityContextFromRequest(HttpServletRequest request)
{
Map context = new HashMap();
Enumeration allAttrKey = request.getAttributeNames();
while (allAttrKey.hasMoreElements())
{
String attrKey = (String) allAttrKey.nextElement();
context.put(attrKey, request.getAttribute(attrKey));
}
return context;
}

/**
* 设置404错误,指定的jasper文件未找到
*
* @param response web的response变量
* @throws java.io.IOException 异常
*/
private void setError404(HttpServletResponse response) throws IOException
{
response.setContentType("text/html;charset=gb2312");
response.setStatus(404);
response.getOutputStream().write("Error:404,File not Found!".getBytes());
}
}

经过以上的设置,通过Spring的IoC和映射机制,我们很容易实现模型复杂的功能,这一切对开发是非常有帮助。

相关文件下载:

ServiceView-servlet.xml

ViewJasperReportController.java

ViewVelocityTemplateController.java

XmlRpcController.java