`
maiguang
  • 浏览: 262386 次
  • 性别: Icon_minigender_1
  • 来自: 焦作
社区版块
存档分类
最新评论

ajax、Struts、spring的无缝结合

阅读更多

去年初,正好负责一个医药信息系统的设计开发,架构设计时,采用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=&quot;list&quot;[/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的开发应用。欢迎大家拍砖!
分享到:
评论

相关推荐

    开发基于Struts Spring Hibernate Ajax

    Spring提供了事务管理、数据访问集成、Web应用框架等多个模块,可以无缝集成Struts,形成MVC架构的一部分。Spring还引入了Spring MVC,这是一款轻量级的Web框架,可以替代Struts,提供更现代的开发体验。 **3. ...

    ajax、Struts、spring整合工程

    综上所述,"ajax、Struts、spring整合工程"是一个展示如何在Java Web开发中将这三个关键技术有效结合的实际案例。通过这样的整合,开发者可以构建出用户体验更好、代码结构更清晰、可维护性更强的Web应用。

    Struts+Spring+Hibernate+Ajax的Demo

    在这个Demo中,Dojo可能被用来创建用户界面,包括按钮、表单、对话框等,同时它也支持Ajax请求,与DWR框架结合,实现了前端和后端的无缝通信。 总的来说,这个"Struts+Spring+Hibernate+Ajax的Demo"展示了如何综合...

    开发基于Struts Spring Hibernate Ajax的网上信息发布平台(Struts Hibernate Spring Ajax)--上机贯穿案例

    Spring MVC是Spring的一部分,它提供了一个更高级的MVC架构,可以与Struts无缝集成,用于处理业务逻辑和数据访问。 **Hibernate**: Hibernate是一个强大的对象关系映射(ORM)框架,它可以将Java对象与数据库表进行...

    struts+spring+hibernate(三大框架),外加ajax

    通过研究这个项目,你可以深入了解四大技术的协同工作,学习如何在实际项目中搭建和配置Struts、Spring、Hibernate和Ajax的集成环境,以及如何编写相应的业务逻辑和UI展示。这对于提升Java Web开发技能非常有帮助。...

    struts2+spring+mybatis+easyui的实现

    同时,Spring与Struts2可以通过Spring-Struts2插件无缝集成,使得Action可以直接由Spring管理,增强了系统的可测试性。 **MyBatis** 是一个轻量级的持久层框架,它将SQL语句与Java代码分离,提供了更灵活的SQL操作...

    Struts1.1+spring2.5+ibatis2.3+Ajax整合的源代码

    Struts1.1+Spring2.5+Ibatis2.3+Ajax整合是一个经典的Java Web开发框架组合,常用于构建企业级应用。这个源代码集合提供了如何将这四个技术有效地结合在一起的实例,以实现一个功能强大的、具有无刷新特性的用户界面...

    mongo集成spring struts2 json velocity

    通过Spring的DispatcherServlet,Struts2的Action和Controller可以被无缝集成,提供更灵活的控制流管理。 Struts2是本项目中的控制器层,它的核心是Action类,每个Action对应一个用户请求。Struts2通过配置文件或...

    使用ajax+struts+hibernate+spring的blog

    **使用Ajax+Struts+Hibernate+Spring构建在线博客系统** 在Web开发中,Ajax、Struts、Hibernate和Spring是四个非常关键的技术框架,它们分别在不同的层面上为开发者提供了强大的功能支持。本项目是一个基于这些技术...

    SSH(struts2,Hibernate,Spring)整合及测试亲测可用

    **Struts2** 是一个基于MVC设计模式的Web应用框架,它在Struts1的基础上进行了大量的改进和增强,提供了更强大的动作拦截器、更加灵活的配置方式以及对AJAX的良好支持。Struts2的核心是Action类,它是业务逻辑的载体...

    spring+struts+hibernate+ajax

    标题中的"spring+struts+hibernate+ajax"是一个典型的Java Web开发技术栈,它涉及到四个关键组件:Spring框架、Struts框架、Hibernate持久化框架以及Ajax异步请求技术。接下来,我们将深入探讨这些技术及其在实际...

    Struts2+AJAX+JPA+Spring合集(英文版)

    本篇文章将深入探讨Struts2、AJAX、JPA与Spring这四种技术的结合使用,以及它们如何共同构建出强大的企业级应用。 #### 一、Struts2:灵活的MVC框架 Struts2是Apache基金会下的一个开源项目,它是基于MVC(Model-...

    某大型企业OA ajax dwr jquery spring hibernate struts

    OA系统可能采用了Struts作为前端控制器,Spring作为应用的核心框架,Hibernate负责数据持久化,DWR用于前后端通信,jQuery则优化了用户界面和交互体验。ERP(Enterprise Resource Planning)和MIS(Management ...

    基于hibernate+spring+struts的学生选课系统

    Spring框架则提供了全面的后端服务支持,如事务管理、AOP(面向切面编程)、IoC( inversion of control,控制反转)等,它还能够与其他框架(如Hibernate)无缝集成。Struts是经典的MVC框架,负责处理HTTP请求,...

    struts2+spring3+hibernate3+jquery+springside 做一个OA2

    它提供了强大的插件架构,可以与其他框架如Spring无缝集成。 2. **Spring3**: Spring是企业级Java应用的核心框架,提供了依赖注入(DI)和面向切面编程(AOP)等功能。Spring3版本在该框架中引入了更多改进,如...

    struts2+spring3+ibatis2.3+jquery_ajax1.7

    Struts2、Spring3、iBatis2.3和jQuery_AJAX1.7是经典的Java Web开发技术栈,它们各自扮演着不同的角色,构建出高效、灵活的应用系统。Struts2是一个MVC(Model-View-Controller)框架,负责处理用户请求并控制应用...

    Struts2.0大结合

    Struts2.0可以无缝集成Spring框架,实现依赖注入(DI),便于管理Action的生命周期。同时,Spring的安全、事务管理等特性也能在Struts2.0中得到利用。 七、实践应用 通过实际项目案例,可以深入理解Struts2.0在开发...

    Struts+Spring+Hibernate+ExtJs毕业系统

    ExtJS 使用 MVC 模式,支持数据绑定和远程数据交互,与后端的 Struts 和 Spring 结合,可以创建动态、交互性强的Web应用。它的组件包括表格、表单、树形结构、面板、图表等,能实现复杂的布局和数据展示。 在...

    Dwr2+Struts2+Spring2+Hiberinate

    同时,Struts2与DWR结合,可以实现前后端数据的无缝交互。 3. **Spring2**:Spring框架是企业级Java应用的核心组件,它提供了依赖注入(DI)、面向切面编程(AOP)以及全面的事务管理等功能。在这个实例中,Spring2...

    struts2、JSTL、Spring、JS、JSP标签大全

    Struts2还支持多种视图技术,如JSP、FreeMarker等,并且能够与其他框架如Hibernate、Spring无缝集成。 2. **JSTL(JavaServer Pages Standard Tag Library)**:JSTL是一组用于JSP的标签库,旨在减少在页面中使用...

Global site tag (gtag.js) - Google Analytics