去年初,正好负责一个医药信息系统的设计开发,架构设计时,采用Struts+JDBC(自定义采用适配器模式封装了HashMap动态VO实现的持久层)。后来ajax热潮兴起,正好系统中有很多地方需要和服务器端交互数据,如采购销售系统中的订单头/订单明细等主从表结构的维护。
[color=blue]数据交互过程[/color],我们考虑采用xml来组织数据结构,更新/保存:前台封装需要的xml,通过ajax提交---〉action解析xml
---〉改造原有的持久层实现xml持久化;
查询时:持久层根据实际需要返回xml,document对象,---〉action 处理
--〉前台自己封装js库来解析xml,并刷新部分页面。
ajax:已经有很多方法实现跨浏览器的方式,这里只介绍最简单的方式,同步模式下提交xmlStr给action(*.do)。
function sendData(urlStr,
xmlStr) {
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.open("POST", urlStr, false);
xmlhttp.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
if (xmlStr) {
xmlhttp.send(xmlStr);
} else {
xmlhttp.send();
}
return xmlhttp.responseXml;
} |
struts中我们扩展了Action,实现了xmlStr转化成document对象(dom4j),并且完善了转发方式。如
[quote]
1.DispatchAction
以一个Controller响应一组动作绝对是Controller界的真理,Struts的DispatchAction同样可以做到这点。
[list]
<action path="/admin/user" name="userForm" scope="request" parameter="method" validate="false">
<forward name="list" path="/admin/userList.jsp">
</action>
[/list] |
其中parameter="method"
设置了用来指定响应方法名的url参数名为method,即/admin/user.do?method=list
将调用UserAction的public ActionForward list(....) 函数。
public ActionForward unspecified(....)
函数可以指定不带method方法时的默认方法。[/quote]但是这样需要在url后多传递参数[size=18][color=red]method=list
[/color][/size];并且action节点配置中的[color=red]parameter="method"
[/color]也没有被充分利用,反而觉得是累赘!
因此我们直接在BaseDispatchAction中增加xml字符串解析,并充分利用action节点配置中的[color=red]parameter="targetMethod"
[/color],使得转发的时候,action能够直接转发到子类的相应方法中,减少了url参数传递,增强了配置信息可读性,方便团队开发。
同样以上述为例,扩展后的配置方式如下:
[quote]
<action path="/admin/user" scope="request" [color="red]parameter="list"[/color]" validate="false">
<forward name="list" path="/admin/userList.jsp">
</action>
[/quote] |
其中[color=red]parameter="list"[/color]
设置了用来指定响应url=/admin/user.do的方法名,它将调用UserAction的public ActionForward
list(....) 函数。
BaseDispatchDocumentAction 的代码如下,它做了三件重要的事情:
1、采用dom4j直接解析xml字符串,并返回document,如果没有提交xml数据,或者采用form形式提交的话,返回null;
2、采用模版方法处理系统异常,减少了子类中无尽的try{...}catch(){...};其中异常处理部分另作描述(你可以暂时去掉异常处理,实现xml提交和解析,如果你有兴趣,我们可以进一步交流);
3、提供了Spring配置Bean的直接调用,虽然她没有注入那么优雅,但是实现了ajax、struts、spring的结合。
BaseDispatchDocumentAction 的源码如下:
package
com.ufida.haisheng.struts;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.beanutils.ConvertUtils;
import
org.apache.commons.beanutils.converters.BigDecimalConverter;
import
org.apache.commons.beanutils.converters.ClassConverter;
import
org.apache.commons.beanutils.converters.IntegerConverter;
import org.apache.commons.beanutils.converters.LongConverter;
import org.apache.log4j.Logger;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.util.MessageResources;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.hibernate.HibernateException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.dao.DataAccessException;
import
org.springframework.web.context.support.WebApplicationContextUtils;
import com.ufida.haisheng.constants.Globals;
import com.ufida.haisheng.converter.DateConverter;
import com.ufida.haisheng.converter.TimestampConverter;
import com.ufida.haisheng.exp.ExceptionDTO;
import com.ufida.haisheng.exp.ExceptionDisplayDTO;
import
com.ufida.haisheng.exp.exceptionhandler.ExceptionHandlerFactory;
import com.ufida.haisheng.exp.exceptionhandler.ExceptionUtil;
import
com.ufida.haisheng.exp.exceptionhandler.IExceptionHandler;
import com.ufida.haisheng.exp.exceptions.BaseAppException;
import
com.ufida.haisheng.exp.exceptions.MappingConfigException;
import
com.ufida.haisheng.exp.exceptions.NoSuchBeanConfigException; |
public abstract class
BaseDispatchDocumentAction extends Action {
protected Class clazz = this.getClass();
protected static Logger log =
Logger.getLogger(BaseDispatchDocumentAction.class); |
protected static
ThreadLocal<exceptiondisplaydto>
expDisplayDetails = new
ThreadLocal<exceptiondisplaydto>();
private static final Long defaultLong = null;
private static ApplicationContext ctx = null; |
static {
ConvertUtils.register(new ClassConverter(), Double.class);
ConvertUtils.register(new DateConverter(), Date.class);
ConvertUtils.register(new DateConverter(), String.class);
ConvertUtils.register(new LongConverter(defaultLong),
Long.class);
ConvertUtils.register(new IntegerConverter(defaultLong),
Integer.class);
ConvertUtils.register(new TimestampConverter(),
Timestamp.class);
ConvertUtils.register(new BigDecimalConverter(defaultLong),
BigDecimal.class);
} |
protected static
MessageResources messages =
MessageResources.getMessageResources("org.apache.struts.actions.LocalStrings"); |
protected
HashMap<string, method=""> methods = new
HashMap<string, method="">(); |
protected Class[] types = {
ActionMapping.class, ActionForm.class, Document.class,
HttpServletRequest.class,
HttpServletResponse.class }; |
public ActionForward
execute(ActionMapping mapping, ActionForm form, HttpServletRequest
request,
HttpServletResponse response) throws Exception {
response.setContentType("text/html; charset=UTF-8");
ExceptionDisplayDTO expDTO = null;
try {
Document doc = createDocumentFromRequest(request); |
String actionMethod = mapping.getParameter();
isValidMethod(actionMethod);
return dispatchMethod(mapping, form, doc,
request, response, actionMethod);
} catch (BaseAppException ex) {
expDTO = handlerException(request, response, ex);
} catch (Exception ex) {
ExceptionUtil.logException(this.getClass(), ex);
renderText(response,"[Error :对不起,系统出现错误了,请向管理员报告以下异常信息.\n" +
ex.getMessage() + "]");
request.setAttribute(Globals.ERRORMSG,
"对不起,系统出现错误了,请向管理员报告以下异常信息.\n" + ex.getMessage());
expDTO = handlerException(request,response, ex);
} finally {
expDisplayDetails.set(null);
}
return null == expDTO ? null : (expDTO.getActionForwardName() ==
null ? null :
mapping.findForward(expDTO.getActionForwardName()));
}
|
public void
renderText(HttpServletResponse response, String text) {
PrintWriter out = null;
try {
out = response.getWriter();
response.setContentType("text/plain;charset=UTF-8");
out.write(text);
} catch (IOException e) {
log.error(e);
} finally {
if (out != null) {
out.flush();
out.close();
out = null;
}
}
} |
public void
renderHtml(HttpServletResponse response, String text) {
PrintWriter out = null;
try {
out = response.getWriter();
response.setContentType("text/html;charset=UTF-8");
out.write(text);
} catch (IOException e) {
log.error(e);
} finally {
if (out != null) {
out.flush();
out.close();
out = null;
}
}
} |
public void
renderXML(HttpServletResponse response, String text) {
PrintWriter out = null;
try {
out = response.getWriter();
response.setContentType("text/xml;charset=UTF-8");
out.write(text);
} catch (IOException e) {
log.error(e);
} finally {
if (out != null) {
out.flush();
out.close();
out = null;
}
}
} |
private
ExceptionDisplayDTO handlerException(HttpServletRequest
request,HttpServletResponse response, Exception ex) {
ExceptionDisplayDTO expDTO = (ExceptionDisplayDTO)
expDisplayDetails.get();
if (null == expDTO) {
expDTO = new
ExceptionDisplayDTO(null,this.getClass().getName());
}
IExceptionHandler expHandler =
ExceptionHandlerFactory.getInstance().create();
ExceptionDTO exDto =
expHandler.handleException(expDTO.getContext(), ex);
request.setAttribute("ExceptionDTO", exDto);
renderText(response,"[Error:" + (exDto == null ? "ExceptionDTO is
null,请检查expinfo.xml配置文件." : exDto.getMessageCode())
+ "]");
return expDTO;
}
private void isValidMethod(String actionMethod)
throws MappingConfigException {
if (actionMethod == null || "execute".equals(actionMethod) ||
"perform".equals(actionMethod)) {
log.error("[BaseDispatchAction->error] parameter = "
+ actionMethod);
expDisplayDetails.set(new ExceptionDisplayDTO(null,
"MappingConfigException"));
throw new MappingConfigException("对不起,配置的方法名不能为 " +
actionMethod);
}
}
|
protected static Document
createDocumentFromRequest(HttpServletRequest request) throws
Exception {
try {
request.setCharacterEncoding("UTF-8");
Document document = null;
SAXReader reader = new SAXReader();
document = reader.read(request.getInputStream());
return document;
} catch (Exception ex) {
log.warn("TIPS:没有提交获取XML格式数据流! ");
return null;
}
} |
protected ActionForward dispatchMethod(ActionMapping
mapping, ActionForm form, Document doc,HttpServletRequest
request,
HttpServletResponse response, String name) throws Exception {
Method method = null;
try {
method = getMethod(name);
} catch (NoSuchMethodException e) {
String message = messages.getMessage("dispatch.method",
mapping.getPath(), name);
log.error(message, e);
expDisplayDetails.set(new ExceptionDisplayDTO(null,
"MappingConfigException"));
throw new MappingConfigException(message, e);
}
ActionForward forward = null;
try {
Object args[] = { mapping, form, doc, request, response };
log.debug("[execute-begin] -> " + mapping.getPath()
+ "->[" + clazz.getName() + "->" +
name + "]");
forward = (ActionForward) method.invoke(this, args);
log.debug(" [execute-end] -> " + (null == forward ?
"use ajax send to html/htm" : forward.getPath()));
} catch (ClassCastException e) {
String message = messages.getMessage("dispatch.return",
mapping.getPath(), name);
log.error(message, e);
throw new BaseAppException(message, e);
} catch (IllegalAccessException e) {
String message = messages.getMessage("dispatch.error",
mapping.getPath(), name);
log.error(message, e);
throw new BaseAppException(message, e);
} catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
String message = messages.getMessage("dispatch.error",
mapping.getPath(), name);
throw new BaseAppException(message, t);
}
return (forward);
}
|
protected Method
getMethod(String name) throws NoSuchMethodException {
synchronized (methods) {
Method method = (Method) methods.get(name);
if (method == null) {
method = clazz.getMethod(name, types);
methods.put(name, method);
}
return (method);
}
} |
protected Object
getSpringBean(String name) throws BaseAppException {
if (ctx == null) {
ctx =
WebApplicationContextUtils.getWebApplicationContext(this.getServlet().getServletContext());
}
Object bean = null;
try {
bean = ctx.getBean(name);
} catch (BeansException ex) {
throw new NoSuchBeanConfigException("对不起,您没有配置名为:" + name +
"的bean。请检查配置文件!", ex.getRootCause());
}
if (null == bean) {
throw new NoSuchBeanConfigException("对不起,您没有配置名为:" + name +
"的bean。请检查配置文件!");
}
return bean;
}
} |
开发人员只需要继承它就可以了,我们写个简单的示例action,如下:
public class UserAction
extends BaseDispatchDocumentAction { |
public ActionForward
list(ActionMapping mapping, ActionForm actionForm,
[color=red]Document doc[/color],HttpServletRequest request,
HttpServletResponse response) throws BaseAppException { |
expDisplayDetails.set(new
ExceptionDisplayDTO(null, "userAction.search")); |
UserManager userManager =
(LogManager) getSpringBean("userManager"); |
//返回xml对象到前台
renderXML(response,
userManager.findUsersByDoc(doc));
return null;
} |
至此,我们成功实现了ajax--struts--spring的无缝结合,下次介绍spring的开发应用。欢迎大家拍砖!
分享到:
相关推荐
Spring提供了事务管理、数据访问集成、Web应用框架等多个模块,可以无缝集成Struts,形成MVC架构的一部分。Spring还引入了Spring MVC,这是一款轻量级的Web框架,可以替代Struts,提供更现代的开发体验。 **3. ...
综上所述,"ajax、Struts、spring整合工程"是一个展示如何在Java Web开发中将这三个关键技术有效结合的实际案例。通过这样的整合,开发者可以构建出用户体验更好、代码结构更清晰、可维护性更强的Web应用。
在这个Demo中,Dojo可能被用来创建用户界面,包括按钮、表单、对话框等,同时它也支持Ajax请求,与DWR框架结合,实现了前端和后端的无缝通信。 总的来说,这个"Struts+Spring+Hibernate+Ajax的Demo"展示了如何综合...
Spring MVC是Spring的一部分,它提供了一个更高级的MVC架构,可以与Struts无缝集成,用于处理业务逻辑和数据访问。 **Hibernate**: Hibernate是一个强大的对象关系映射(ORM)框架,它可以将Java对象与数据库表进行...
通过研究这个项目,你可以深入了解四大技术的协同工作,学习如何在实际项目中搭建和配置Struts、Spring、Hibernate和Ajax的集成环境,以及如何编写相应的业务逻辑和UI展示。这对于提升Java Web开发技能非常有帮助。...
同时,Spring与Struts2可以通过Spring-Struts2插件无缝集成,使得Action可以直接由Spring管理,增强了系统的可测试性。 **MyBatis** 是一个轻量级的持久层框架,它将SQL语句与Java代码分离,提供了更灵活的SQL操作...
Struts1.1+Spring2.5+Ibatis2.3+Ajax整合是一个经典的Java Web开发框架组合,常用于构建企业级应用。这个源代码集合提供了如何将这四个技术有效地结合在一起的实例,以实现一个功能强大的、具有无刷新特性的用户界面...
通过Spring的DispatcherServlet,Struts2的Action和Controller可以被无缝集成,提供更灵活的控制流管理。 Struts2是本项目中的控制器层,它的核心是Action类,每个Action对应一个用户请求。Struts2通过配置文件或...
**使用Ajax+Struts+Hibernate+Spring构建在线博客系统** 在Web开发中,Ajax、Struts、Hibernate和Spring是四个非常关键的技术框架,它们分别在不同的层面上为开发者提供了强大的功能支持。本项目是一个基于这些技术...
**Struts2** 是一个基于MVC设计模式的Web应用框架,它在Struts1的基础上进行了大量的改进和增强,提供了更强大的动作拦截器、更加灵活的配置方式以及对AJAX的良好支持。Struts2的核心是Action类,它是业务逻辑的载体...
标题中的"spring+struts+hibernate+ajax"是一个典型的Java Web开发技术栈,它涉及到四个关键组件:Spring框架、Struts框架、Hibernate持久化框架以及Ajax异步请求技术。接下来,我们将深入探讨这些技术及其在实际...
本篇文章将深入探讨Struts2、AJAX、JPA与Spring这四种技术的结合使用,以及它们如何共同构建出强大的企业级应用。 #### 一、Struts2:灵活的MVC框架 Struts2是Apache基金会下的一个开源项目,它是基于MVC(Model-...
OA系统可能采用了Struts作为前端控制器,Spring作为应用的核心框架,Hibernate负责数据持久化,DWR用于前后端通信,jQuery则优化了用户界面和交互体验。ERP(Enterprise Resource Planning)和MIS(Management ...
Spring框架则提供了全面的后端服务支持,如事务管理、AOP(面向切面编程)、IoC( inversion of control,控制反转)等,它还能够与其他框架(如Hibernate)无缝集成。Struts是经典的MVC框架,负责处理HTTP请求,...
它提供了强大的插件架构,可以与其他框架如Spring无缝集成。 2. **Spring3**: Spring是企业级Java应用的核心框架,提供了依赖注入(DI)和面向切面编程(AOP)等功能。Spring3版本在该框架中引入了更多改进,如...
Struts2、Spring3、iBatis2.3和jQuery_AJAX1.7是经典的Java Web开发技术栈,它们各自扮演着不同的角色,构建出高效、灵活的应用系统。Struts2是一个MVC(Model-View-Controller)框架,负责处理用户请求并控制应用...
Struts2.0可以无缝集成Spring框架,实现依赖注入(DI),便于管理Action的生命周期。同时,Spring的安全、事务管理等特性也能在Struts2.0中得到利用。 七、实践应用 通过实际项目案例,可以深入理解Struts2.0在开发...
ExtJS 使用 MVC 模式,支持数据绑定和远程数据交互,与后端的 Struts 和 Spring 结合,可以创建动态、交互性强的Web应用。它的组件包括表格、表单、树形结构、面板、图表等,能实现复杂的布局和数据展示。 在...
同时,Struts2与DWR结合,可以实现前后端数据的无缝交互。 3. **Spring2**:Spring框架是企业级Java应用的核心组件,它提供了依赖注入(DI)、面向切面编程(AOP)以及全面的事务管理等功能。在这个实例中,Spring2...
Struts2还支持多种视图技术,如JSP、FreeMarker等,并且能够与其他框架如Hibernate、Spring无缝集成。 2. **JSTL(JavaServer Pages Standard Tag Library)**:JSTL是一组用于JSP的标签库,旨在减少在页面中使用...