`
Ivan_Pig
  • 浏览: 381989 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Struts meets Swing 1 (翻译)

阅读更多
原文:http://javaboutique.internet.com/tutorials/Swing/index.html

1.简介: 
   Jakarta Struts是基于MVC模式创建servlet应用程序的框架。大部分的Struts应用程序都是使用浏览器作为客户端,实际上Struts足够的开放,它可以使用其它的客户端模式。在这里我将在我 "Coding your second Jakarta Struts Application"这篇文章里的一个浏览器应用实例改成Swing客户端模式,只需要修改一点代码。
   这篇文章主要介绍如何使用Swing客户端去连接已经存在的Servlet应用。如果你打算开发一个java应用程序,既能够使用浏览器做客户端也可以用Swing做客户端,你就需要根据你程序的需要灵活的选择构架,如EJB或web service,他们提供了简单的接口。

2.Struts结构
   在我们开始之前,先看看浏览器如何和Struts应用通信的。这些将在我们的Swing应用程序中体现。
   *Struts应用程序是由servlet接受到GET或POST请求开始的。
   *servlet决定调用哪个"action",是从URL中获得信息的。
   *实现了Action的java类是在struts-config.xml中配置的。
   * Struts的输出由jsp来显示,jsp的名字也在struts-config.xml文件中指定。
   所以第一个非浏览器应用需要能够给servlet发送一个请求,并且能从jsp页面得到响应。

3.The URLConnection class

    使用URLConnection类能够很简单的使用java编写servlet请求代码。这个类很有趣,因为它有一些奇怪的设计。如果你想看看它的实现,我建议你读一读"Dodge the traps hiding in the URLConnection class".
    如果想发送一个带有"list"action的请求,并接受打印响应,你需要这样写代码:

URL url = new URL("http://myserver/project/list.do");
    URLConnection conn = url.openConnection();
    
    BufferedReader in = 
       new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String line;  
    while ((line = in.readLine()) != null) {
       System.out.println(line);
    }


    一般来讲你通常需要在请求的同时发送一些数据--就像提交表单那样。这些数据需要在你读取响应前发送过去。

URL url = new URL("http://myserver/project/list.do");
    URLConnection conn = url.openConnection();
    conn.setDoOutput(true);
    conn.setRequestProperty("user-agent","SWING");  
    
    BufferedWriter out =
       new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
    out.write("name1=value1&name2=value2");
    out.flush();
    out.close();
    
    String c = conn.getHeaderField("Set-Cookie");
    BufferedReader in = 
       new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String line;  
    while ((line = in.readLine()) != null) {
       System.out.println(line);
    }


    这个例子同时也显示了如何读写HTTP头信息。
    第一个例子使用GET方法与HTTP通信,而第二个例子使用POST方法通信。你同样可以使用GET方法来给servlet传送数据,但是就必须要把数据加到URL里,像这样:
URL url = new URL("http://myserver/project/list.do?name1=value1&name2=value2");


4.Identifying the client
    现在我们知道怎么发送和请求数据了,但是我们怎么接受数据呢?如果响应是给浏览器的,那响应里就包含了HTML或者还有JavaScript和样式。对于我们的Swing客户端,我们只需要数据。这将带来一个新问题:Struts应用程序如何能识别出客户端是一个浏览器,是个Swing还是其它什么呢?
    一种解决办法是在每个请求里添加参数时其能间鉴别出是哪种客户端。我在第二个例子里已经使用了user-agent这个头信息来使其识别出是个Swing客户端。
    当Struts应用程序准备好给客户端返回数据时,它就会检测user-agent的值,然后选择适合客户端的jsp页面。这将会替代Struts Action类设置的跳转信息。

String client = (String)request.getHeader("user-agent");
    // Forward control to the list page
    if (client.equals("SWING")) 
     return (mapping.findForward("swinglist"));
    else return (mapping.findForward("list"));


     "list"和"swinglist"的在Struts配置文件里定义:
<forward name="list" path="/list.jsp"/>
    <forward name="swinglist" path="/swinglist.jsp"/>


    list.jsp是为在浏览器显示的,swinglist.jsp则是在Swing上显示的。

    在我们开始创建swinglist.jsp前,先看一个例子程序,改程序将使用文章里提到的方法。

    The DVD application

    这个应用程序是在xml文件里管理DVD的。它将会以列表的方式显示所有的DVD,并且可以在详细页面里添加,修改或删除DVD.列表像这样。
     图片见原文

    DVDManager类监听DVD应用程序,它将DVD信息保存为JDOM的树结构。DVDManager从xml文件中读取DVD信息,并能够将这些信息再保存到xml文件里。xml格式很明显是返回数据给Swing应用程序的一种选择。

Returning XML data to the client

    这就意味着,swinglist.jsp要返回数据给Swing客户端,就必须以xml的方式来存放DVD。JDOM有能将树结构转换成PRintWriter的方法,我们只要简单的获取这些输出流并将它发送给Swing客户端即可。DVDmanager里的第一个新方法就是:
public void outList(PrintWriter out) {
      XMLOutputter outputter = new XMLOutputter("",false);
      // NB: the outputter does not accept XML headers:  
      outputter.setOmitDeclaration(true); 
      try {
        outputter.output(doc, out);
      } catch (IOException e) {
        e.printStackTrace();
      }    
    }


这个方法将被swinglist.jsp调用:

<%@ page language="java" %>
    <%@ page import="java.io.*" %>
    
    <jsp:useBean id="dvds" 
      class="hansen.playground.DVDManager" scope="session"/>
     
    <%
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        dvds.outList(pw); 
        pw.flush();
        out.print(sw.toString());
    %>


相似的方法我们创建一个swingdetail.jsp页面,这个页面将返回一个的xml文件,包含着单个的DVD信息:

<%@ page language="java" %>
    <%@ page import="java.io.*" %>
    
    <jsp:useBean id="dvds" 
      class="hansen.playground.DVDManager" scope="session"/>
    
    <%
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        dvds.outListElement(pw); 
        pw.flush();
        out.print(sw.toString());
    %>


    我们可以不使用JDOM的XMLOutputter类来创建xml响应而直接手动编码。让我来给个例子:如果我们只想返回DVD的名字,我们能创建一个像这样的jsp页面:
    
<%@ page language="java" %>
    <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
    <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
    
    <jsp:useBean id="dvds" 
      class="hansen.playground.DVDManager" scope="session"/>
    
    <collection>
    <logic:iterate id="dvd" indexId="i" name="dvds" property="dvds">
    <% 
    // Transfer the iteration index to the DVDManager 
    dvds.setIndex(i.intValue()); 
    %>
    <dvd>
    <title><bean:write name="dvds" property="title"/></title>
    </dvd>
    </logic:iterate>
    </collection>


当这个页面执行,它将会产生一个像这样的输出。

<collection>
      <dvd>
        <title>Amadeus</title>
      </dvd>
      <dvd>
        <title>Lord of the Rings: The Fellowship of the Ring</title>
      </dvd>
      <dvd>
        <title>The Matrix</title>
      </dvd>
    </collection>


Testing the Swing jsp-pages


    除了错误页面,DVD应用程序只使用了swinglist.jsp和swingdetail.jsp,所以让我们用DemoRequest来测试一下这两个jsp页面。
    它包含一个request方法能发送一个请求给servlet,并将响应输出到System.out。注意怎样设置请求的user-agent为"SWING"。如果我们像这样请求:
DemoRequest dr = new DemoRequest("http://localhost:8080/dvdapp2/list.do");
    dr.request();


    我们得到输出:

<collection>
      <dvd id="C">
        <title>Amadeus</title>
        <length>158</length>
        <actor>F. Murray Abraham</actor>
        <actor>Tom Hulce</actor>
        <actor>Elizabeth Berridge</actor>
      </dvd>
      <dvd id="A">
        <title>Lord of the Rings: The Fellowship of the Ring</title>
        <length>178</length>
        <actor>Ian Holm</actor>
        <actor>Elijah Wood</actor>
        <actor>Ian McKellen</actor>
      </dvd>
      <dvd id="B">
        <title>The Matrix</title>
        <length>136</length>
        <actor>Keanu Reeves</actor>
        <actor>Laurence Fishburne</actor>
      </dvd>
    </collection>



    如果和第三个代码相比,你会发现他们很像。让我们来发送个请求来请求第一个DVD的详细信息。

DemoRequest dr = new DemoRequest("http://localhost:8080/dvdapp2/list.do");
    dr.request();  
    dr = new DemoRequest("http://localhost:8080/dvdapp2/detail.do");
    dr.setData("index=0");  
    dr.request(); 


    结果不是我们期望的。我们得到了正确的DVD列表,但是输出却是这样的:
<html>
    <head>
    <title>System Error</title>
    </head>
    <body>
    <h2>System Error</h2>
    
    No DVD information available
    
    </body>
    </html>


    这是error.jsp页面返回的,它告诉我们处理Detail页面的Struts Action类没有在session范围内找到DVD列表信息。

Maintaining the Session


    这种错误你可能要花数小时去确定。或一下子就找到了原因。这里是原因。

    当服务显示的为浏览器用户提供服务时,我们都经常会忘记session状态为每个用户创建了cookie,并通过cookie来识别用户。当我们第一次访问应用时cookie会被发送到我们机器上。当我们进行下一次请求时,就该我们把cookie送还给服务器了,这样服务器就能识别出session.在测试程序里我们没有做这个,所以现在我们必须修改代码来存储返回来的cookie,并再以后的请求中把cookie发送回去。DemoRequestCookie这个新类,看这里。

     新的请求就像这样:

DemoRequestCookie dr = 
       new DemoRequestCookie("http://localhost:8080/dvdapp2/list.do");
    dr.request();  
    String cookie = dr.getCookie();
    dr = new DemoRequestCookie("http://localhost:8080/dvdapp2/detail.do");
    dr.setData("index=0");  
    dr.setCookie(cookie);
    dr.request();  



    这次输出就和期望的相符了。
. . . (list of all DVDs) . . .
    <dvd id="C">
        <title>Amadeus</title>
        <length>158</length>
        <actor>F. Murray Abraham</actor>
        <actor>Tom Hulce</actor>
        <actor>Elizabeth Berridge</actor>
    </dvd>


Updating the Struts configuration file


    我们必须在struts-config.xml里配置前面的方法。每个定义都必须包含jsp文件,且这个文件必须要Swing-counterpart。比较下配置文件。
section
name
refers to

global-forwards
error
error.jsp

  list
list.jsp

  detail
detail.jsp

action-mappings
create
detail.jsp

  update
detail.jsp

  delete
list.jsp

  cancel
list.jsp


我们添加新节点。

section
name
refers to

global-forwards
swingerror
swingerror.jsp

  swinglist
swinglist.jsp

  swingdetail
swingdetail.jsp

action-mappings
swingcreate
empty.jsp

  swingupdate
empty.jsp

  swingdelete
empty.jsp

  swingcancel
empty.jsp

就像你看到的action mappings的empty.jsp节点,它有如下内容:

<empty/>

   它包含一个单独的xml元素所以是个有效的xml文件。你会发现很奇怪的是,在创建,删除和去掉时不会需要返回任何信息,但是原因很简单。Swing客户端是胖客户端,而浏览器是瘦客户端。胖客户端能存储当前DVD的数据和可能所有DVD的列表。

    所以,胖客户端只需要从服务器段获取一次DVD列表即可,此后它将数据保存在本地。如果DVD列表不高喊所有的DVD数据,没那么当选择某个DVD时,它将会从服务器获取。这就是swingdetail action停止调用swingdetail.jsp的原因。

    有一点需要指出。在下一版本的Struts(1.1)中,将会包含不止一个配置文件。通过阅读给我的初步说明,Swing actions可能会放到其它配置文件中,这也许会是个让代码整洁的解决办法。

Coding the Swing client
   我们完成了Swing客户端的代码:
    我们知道了怎样通过URLConnection和Session cookies调用servlet。我们知道了怎样格式化xml响应。
    在下一篇文章里,我将讲述如何创建一个Swing客户端,来解析和显示xml响应,并且我们来看看如何找到错误。





分享到:
评论
2 楼 alanytam 2009-03-12  
强顶!正在找这方面的东东,打算用Struts做一个Swing的项目!好像有点挑战!打算用struts2,所以还有多加研究。

1 楼 liyaxi 2009-02-15  
有创意! 支持!

相关推荐

    struts 翻译struts 翻译struts 翻译

    struts 翻译struts 翻译struts 翻译struts 翻译struts 翻译

    struts1和struts2的区别

    struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别...

    Struts毕业设计外文翻译

    介绍了Struts入门知识,首先介绍了Struts产生的背景、Struts概念。介绍了什么应用框架。最后介绍有关超文本传输协议HTTP和公共网关接口CGI有关知识

    struts1标签struts1标签

    struts1标签struts1标签struts1标签struts1标签struts1标签struts1标签struts1标签struts1标签struts1标签struts1标签struts1标签struts1标签struts1标签struts1标签struts1标签struts1标签struts1标签

    struts1struts1

    struts1struts1struts1struts1struts1struts1struts1struts1struts1struts1struts1struts1struts1struts1struts1struts1struts1struts1struts1

    Struts2案例翻译篇-Using Struts2 Tag

    Struts2案例翻译篇-Struts2 Tags Struts2案例翻译篇-HelloWorld

    Struts1和Struts2区别

    struts1 struts2 Struts1和Struts2区别

    Struts1与Struts2本质区别

    1 在Action实现类方面的对比:Struts 1要求Action类继承一个抽象基类;Struts 1的一个具体问题是使用抽象类编程而不是接口。Struts 2 Action类可以实现一个Action接口,也可以实现其他接口,使可选和定制的服务成为...

    struts1 struts1

    struts1 struts1 struts1

    struts1 和 struts2所需jar包

    struts1 和 struts2所需jar包。主要包含以下内容: struts-1.3.10-all.zip struts-1.3.10-apps.zip struts-1.3.10-lib.zip struts-1.3.10-src.zip struts-2.3.4.1-all.zip struts.rar

    struts2 与 struts1的区别

    struts2 与 struts1的区别

    struts1标签库详解

    struts标签库struts标签库struts标签库struts标签库struts标签库struts标签库struts标签库struts标签库

    struts1—jar

    struts1核心包,整个框架所需要的jar包都有

    Struts2与Struts1区别

    Apache Struts 2即是之前大家所熟知的WebWork 2。在经历了几年的各自发展后,WebWork和Struts社区决定合二为一,也即是Struts 2  Struts 2 英文学习网站:hthttp://struts.apache.org/2.1.6/index.html

    struts1漏洞总结及整改方案

    因为最近攻防演练,对公司的资产进行梳理,发现部分应用还使用的struts1框架,所以赶快收集整理了相关的漏洞以及相关的整改方案。提供给大家。

    Struts1 fileupload Struts1文件上传 源码下载

    Struts1的fileupload的文件上传

    struts的英文文献及翻译

    struts的英文文献及翻译

    Struts In Action 电子书 Struts1电子书

    Struts In Action 电子书 Struts1电子书

    struts1_详解

    struts1_详解 struts1框架实例详解

    struts2.0整合Struts 1

    《Struts 2权威指南--基于WebWork核心的MVC开发》李纲著,是学习Struts 2不错的书籍,这里给出光盘中带包源代码。所有例子直接放入tomcat下都能运行。

Global site tag (gtag.js) - Google Analytics