struts2文件上传相关资料收集整合

来源:互联网 发布:win7部分软件显示乱码 编辑:程序博客网 时间:2024/05/20 06:51

 前一阵子有些朋友在电子邮件中问关于Struts 2实现文件上传的问题, 所以今天我们就来讨论一下这个问题。

实现原理
Struts 2是通过Commons FileUpload文件上传。Commons FileUpload通过将HTTP的数据保存到临时文件夹,然后Struts使用fileUpload拦截器将文件绑定到Action的实例中。从而我们就能够以本地文件方式的操作浏览器上传的文件。

具体实现
前段时间Apache发布了Struts 2.0.6 GA,所以本文的实现是以该版本的Struts作为框架的。以下是例子所依赖类包的列表:

 
清单1 依赖类包的列表

首先,创建文件上传页面FileUpload.jsp,内容如下:

<% @ page language = " java " contentType = " text/html; charset=utf-8 " pageEncoding = " utf-8 " %>
<% @ taglib prefix = " s " uri = " /struts-tags " %>

<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="
http://www.w3.org/1999/xhtml" >
< head >
    < title > Struts 2 File Upload </ title >
</ head >
< body >
    < s:form action ="fileUpload" method ="POST" enctype ="multipart/form-data" >
        < s:file name ="myFile" label ="Image File" />
        < s:textfield name ="caption" label ="Caption" />       
        < s:submit />
    </ s:form >
</ body >
</ html > 清单2 FileUpload.jsp
在FileUpload.jsp中,先将表单的提交方式设为POST,然后将enctype设为multipart/form-data,这并没有什么特别之处。接下来,<s:file/>标志将文件上传控件绑定到Action的myFile属性。

其次是FileUploadAction.java代码:

 package tutorial;

 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Date;

 import org.apache.struts2.ServletActionContext;

 import com.opensymphony.xwork2.ActionSupport;

 public class FileUploadAction extends ActionSupport  {
     private static final long serialVersionUID = 572146812454l ;
     private static final int BUFFER_SIZE = 16 * 1024 ;
   
     private File myFile;
     private String contentType;
     private String fileName;
     private String imageFileName;
     private String caption;
   
     public void setMyFileContentType(String contentType)  {
         this .contentType = contentType;
    }
   
     public void setMyFileFileName(String fileName)  {
         this .fileName = fileName;
    }
       
     public void setMyFile(File myFile)  {
         this .myFile = myFile;
    }
   
     public String getImageFileName()  {
         return imageFileName;
    }
   
     public String getCaption()  {
         return caption;
    }
 
      public void setCaption(String caption)  {
         this .caption = caption;
    }
   
     private static void copy(File src, File dst)  {
         try  {
            InputStream in = null ;
            OutputStream out = null ;
             try  {               
                in = new BufferedInputStream( new FileInputStream(src), BUFFER_SIZE);
                out = new BufferedOutputStream( new FileOutputStream(dst), BUFFER_SIZE);
                 byte [] buffer = new byte [BUFFER_SIZE];
                 while (in.read(buffer) > 0 )  {
                    out.write(buffer);
                }
             } finally  {
                 if ( null != in)  {
                    in.close();
                }
                  if ( null != out)  {
                    out.close();
                }
            }
         } catch (Exception e)  {
            e.printStackTrace();
        }
    }
   
     private static String getExtention(String fileName)  {
         int pos = fileName.lastIndexOf( " . " );
         return fileName.substring(pos);
    }
 
    @Override
     public String execute()      {       
        imageFileName = new Date().getTime() + getExtention(fileName);
        File imageFile = new File(ServletActionContext.getServletContext().getRealPath( " /UploadImages " ) + " / " + imageFileName);
        copy(myFile, imageFile);
         return SUCCESS;
    }
   
} 清单3 tutorial/FileUploadAction.java
在FileUploadAction中我分别写了setMyFileContentType、setMyFileFileName、setMyFile和setCaption四个Setter方法,后两者很容易明白,分别对应FileUpload.jsp中的<s:file/>和<s:textfield/>标志。但是前两者并没有显式地与任何的页面标志绑定,那么它们的值又是从何而来的呢?其实,<s:file/>标志不仅仅是绑定到myFile,还有myFileContentType(上传文件的MIME类型)和myFileFileName(上传文件的文件名,该文件名不包括文件的路径)。因此,<s:file name="xxx" />对应Action类里面的xxx、xxxContentType和xxxFileName三个属性。

FileUploadAction作用是将浏览器上传的文件拷贝到WEB应用程序的UploadImages文件夹下,新文件的名称是由系统时间与上传文件的后缀组成,该名称将被赋给imageFileName属性,以便上传成功的跳转页面使用。

下面我们就来看看上传成功的页面:

<% @ page language = " java " contentType = " text/html; charset=utf-8 " pageEncoding = " utf-8 " %>
<% @ taglib prefix = " s " uri = " /struts-tags " %>

<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="
http://www.w3.org/1999/xhtml" >
< head >
    < title > Struts 2 File Upload </ title >
</ head >
< body >
    < div style ="padding: 3px; border: solid 1px #cccccc; text-align: center" >
        < img src ='UploadImages/<s:property value ="imageFileName" /> ' />
        < br />
        < s:property value ="caption" />
    </ div >
</ body >
</ html > 清单4 ShowUpload.jsp
ShowUpload.jsp获得imageFileName,将其UploadImages组成URL,从而将上传的图像显示出来。

然后是Action的配置文件:

<? xml version="1.0" encoding="UTF-8" ?>

<! DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "
http://struts.apache.org/dtds/struts-2.0.dtd" >

< struts >
    < package name ="fileUploadDemo" extends ="struts-default" >
        < action name ="fileUpload" class ="tutorial.FileUploadAction" >
            < interceptor-ref name ="fileUploadStack" />
            < result name ="success" > /ShowUpload.jsp </ result >
        </ action >
    </ package >
</ struts > 清单5 struts.xml
fileUpload Action显式地应用fileUploadStack的拦截器。

最后是web.xml配置文件:

<? xml version="1.0" encoding="UTF-8" ?>
< web-app id ="WebApp_9" version ="2.4"
    xmlns ="
http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi ="
http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation ="
http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >

    < display-name > Struts 2 Fileupload </ display-name >

    < filter >
        < filter-name > struts-cleanup </ filter-name >
        < filter-class >
            org.apache.struts2.dispatcher.ActionContextCleanUp
        </ filter-class >
    </ filter >
   
    < filter >
        < filter-name > struts2 </ filter-name >
        < filter-class >
            org.apache.struts2.dispatcher.FilterDispatcher
        </ filter-class >
    </ filter >
   
    < filter-mapping >
        < filter-name > struts-cleanup </ filter-name >
        < url-pattern > /* </ url-pattern >
    </ filter-mapping >

    < filter-mapping >
        < filter-name > struts2 </ filter-name >
        < url-pattern > /* </ url-pattern >
    </ filter-mapping >

    < welcome-file-list >
        < welcome-file > index.html </ welcome-file >
    </ welcome-file-list >

</ web-app > 清单6 WEB-INF/web.xml
发布运行应用程序,在浏览器地址栏中键入:
http://localhost:8080/Struts2_Fileupload/FileUpload.jsp,出现图示页面:

 
清单7 FileUpload页面

选择图片文件,填写Caption并按下Submit按钮提交,出现图示页面:

 
清单8 上传成功页面

更多配置
在运行上述例子,如果您留心一点的话,应该会发现服务器控制台有如下输出:

Mar 20 , 2007 4 : 08 : 43 PM org.apache.struts2.dispatcher.Dispatcher getSaveDir
INFO: Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir
Mar 20 , 2007 4 : 08 : 43 PM org.apache.struts2.interceptor.FileUploadInterceptor intercept
INFO: Removing file myFile C:/Program Files/Tomcat 5.5 /work/Catalina/localhost/Struts2_Fileupload/upload_251447c2_1116e355841__7ff7_00000006.tmp 清单9 服务器控制台输出
上述信息告诉我们,struts.multipart.saveDir没有配置。struts.multipart.saveDir用于指定存放临时文件的文件夹,该配置写在struts.properties文件中。例如,如果在struts.properties文件加入如下代码:

struts.multipart.saveDir = /tmp 清单10 struts配置
这样上传的文件就会临时保存到你根目录下的tmp文件夹中(一般为c:/tmp),如果此文件夹不存在,Struts 2会自动创建一个。

错误处理
上述例子实现的图片上传的功能,所以应该阻止用户上传非图片类型的文件。在Struts 2中如何实现这点呢?其实这也很简单,对上述例子作如下修改即可。

首先修改FileUpload.jsp,在<body>与<s:form>之间加入“<s:fielderror />”,用于在页面上输出错误信息。

然后修改struts.xml文件,将Action fileUpload的定义改为如下所示:

        < action name ="fileUpload" class ="tutorial.FileUploadAction" >
            < interceptor-ref name ="fileUpload" >
                < param name ="allowedTypes" >
                    image/bmp,image/png,image/gif,image/jpeg
                </ param >
            </ interceptor-ref >
            < interceptor-ref name ="defaultStack" />           
            < result name ="input" > /FileUpload.jsp </ result >
            < result name ="success" > /ShowUpload.jsp </ result >
        </ action > 清单11 修改后的配置文件
显而易见,起作用就是fileUpload拦截器的allowTypes参数。另外,配置还引入defaultStack它会帮我们添加验证等功能,所以在出错之后会跳转到名称为“input”的结果,也即是FileUpload.jsp。

发布运行应用程序,出错时,页面如下图所示:

 
清单12 出错提示页面

上面的出错提示是Struts 2默认的,大多数情况下,我们都需要自定义和国际化这些信息。通过在全局的国际资源文件中加入“struts.messages.error.content.type.not.allowed=The file you uploaded is not a image”,可以实现以上提及的需求。对此有疑问的朋友可以参考我之前的文章《在Struts 2.0中国际化(i18n)您的应用程序》。

实现之后的出错页面如下图所示:

 
清单13 自定义出错提示页面

同样的做法,你可以使用参数“maximumSize”来限制上传文件的大小,它对应的字符资源名为:“struts.messages.error.file.too.large”。

字符资源“struts.messages.error.uploading”用提示一般的上传出错信息。

多文件上传
与单文件上传相似,Struts 2实现多文件上传也很简单。你可以将多个<s:file />绑定Action的数组或列表。如下例所示。

< s:form action ="doMultipleUploadUsingList" method ="POST" enctype ="multipart/form-data" >
    < s:file label ="File (1)" name ="upload" />
    < s:file label ="File (2)" name ="upload" />
    < s:file label ="FIle (3)" name ="upload" />
    < s:submit />
</ s:form > 清单14 多文件上传JSP代码片段
如果你希望绑定到数组,Action的代码应类似:

     private File[] uploads;
     private String[] uploadFileNames;
     private String[] uploadContentTypes;

     public File[] getUpload()  { return this .uploads; }
      public void setUpload(File[] upload)  { this .uploads = upload; }
 
      public String[] getUploadFileName()  { return this .uploadFileNames; }
      public void setUploadFileName(String[] uploadFileName)  { this .uploadFileNames = uploadFileName; }
 
      public String[] getUploadContentType()  { return this .uploadContentTypes; }
      public void setUploadContentType(String[] uploadContentType)  { this .uploadContentTypes = uploadContentType; } 清单15 多文件上传数组绑定Action代码片段
如果你想绑定到列表,则应类似:

     private List < File > uploads = new ArrayList < File > ();
     private List < String > uploadFileNames = new ArrayList < String > ();
     private List < String > uploadContentTypes = new ArrayList < String > ();

     public List < File > getUpload()  {
         return this .uploads;
    }
      public void setUpload(List < File > uploads)  {
         this .uploads = uploads;
    }
 
      public List < String > getUploadFileName()  {
         return this .uploadFileNames;
    }
      public void setUploadFileName(List < String > uploadFileNames)  {
         this .uploadFileNames = uploadFileNames;
    }
 
      public List < String > getUploadContentType()  {
         return this .uploadContentTypes;
    }
      public void setUploadContentType(List < String > contentTypes)  {
         this .uploadContentTypes = contentTypes;
    } 清单16 多文件上传列表绑定Action代码片段
总结
在Struts 2中实现文件上传的确是轻而易举,您要做的只是使用<s:file />与Action的属性绑定。这又一次有力地证明了Struts 2的简单易用。


struts2文件上传与下载(1)

struts学习   2009-07-18 09:51   阅读51   评论0   字号: 大大  中中  小小        其实这节的内容没有任何struts2的内容.只是介绍只用html来实现文件的上传.之所以要写这个,就是能理解一些底层的实现

只写两个页面...

upload.jsp

<body>

 <form action="result.jsp" method="post" enctype="multipart/form-data"> //注意,这里默认是enctype="application/x-www-form-urlencoded".也就是字符串类型.必须转换成这个..还有.method必须是"post".这两点特别注意
 
 Information: <input type="text" name="info"><br>
 File: <input type="file" name="file"><br>
 
 <input type="submit" name="submit" value=" submit ">
 
 </form> //其他都没什么不一样..

</body>

result.jsp

<%@ page language="java" contentType="text/html; charset=GB18030"
    pageEncoding="GB18030"%>
<%@ page import="java.io.*" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>Insert title here</title>
</head>
<body>

 
<% //都是java代码..直接写页面上不行...不过我们只是为了演示...就算了.
 InputStream is = request.getInputStream();

 BufferedReader br = new BufferedReader(new InputStreamReader(is));
 
 String buffer = null;
 
 while((buffer = br.readLine()) != null)
 {
  out.print(buffer + "<br>"); 
 }
%>


</body>
</html>

struts2文件上传与下载(2)

struts学习   2009-07-18 20:20   阅读80   评论0   字号: 大大  中中  小小      本节还是不用struts2的内容实现文件的上传...不过这节的内容实现了文件彻底意义上的上传(上一节是通过读字符流的方式将文本文件的内容读出来并显示)..这节是讲文件复制到我们需要的地方(其实就是我们一般意义上的上传)

    这里,我们不需要用struts的过滤器(其实就是不需要用struts了.因为我们在web.xml上面定义的struts过滤器,我们这里要将它注释掉,然后自己写servlet)...

   首先,还是先将两个页面放上来..

upload2.jsp  注意,这里我将这两个jsp文件都放到upload文件夹下面了...所以一些目录代码会有些修改

.<body>
 <form action="/struts2/UploadServlet" method="post" enctype="multipart/form-data"> //再次强调,这里的method必须是post.还有enctype也必须改成这个. 这里的action为什么是这个.看下面我设置servlet的就明白了..
  fname:<input type="text" name="name" ><br>
  password:<input type="password" name="password"><br>
  file1:<input type="file" name="file1"><br>
  file2:<input type="file" name="file2"><br>
  <input type="submit">
 </form>

result2.jsp //到时候我会设置servlet跳转到这个页面.所以不用着急

<body>
 name:<%=request.getAttribute("name") %><br>//到时候我会把这个字段的内容放到attribute里面..
 password:${requestScope.password }<br>
 file1:${requestScope.file1 }<br>
 file2:${requestScope.file2 }
 
  </body>

2 创建自己的servlet.这里是关键 ..

package com.test.servlet;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadServlet extends HttpServlet {

 public void doPost(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException { //因为我们是用post方法传进来的.所以只需要实现doPost方法

  DiskFileItemFactory factory = new DiskFileItemFactory();  //创建一个factory
 
  String path="D://file"; //这里是上传文件存放的路径.注意这里的反斜杠要两个/
  factory.setRepository(new File(path));//factory中注入文件名称
  factory.setSizeThreshold(1024*1024);//注入文件限制大小
 
  ServletFileUpload upload = new ServletFileUpload(factory);
  try {
   List<FileItem> list = upload.parseRequest(request);//将传入的request内容封装成一个list对象
  
   for(FileItem item : list)//对象循环..每一个item对应一个对象.比如name 是一个对象 file1也是一个对象
   {
    if(item.isFormField()) //判断是否为文件对象..也就是说.如果这个对象是文件的话返回假..否则返回真
    {
     String color=#ff0000>//获取这个name属性.对应页面里的那个 value = item.getString("GBK"); //获取对应的value,也就是说我们输入的这个值.
     request.setAttribute(name, value);//注入到attribute中
     System.out.println(value);
    } else
    {
     String name = item.getFieldName();//同理,这里是file1 和 file2 
     String value = item.getName(); //注意,这里是getName.而不是上面的getString .这个是根据浏览器的不同,会返回文件的名字或者路径..比如 C:/aaa.txt..有的浏览器就返回aaa.txt.而有的浏览器就返回C:/aaa.txt.所以下面进行了统一
     int start = value.lastIndexOf("
//");//获取最后一个反斜杠的位置.
     String fieldName = value.substring(start+1);//最后一个反斜杠的位置后面的那串字符串就是我们的文件名.
     System.out.println(name);
     request.setAttribute(name, fieldName);
    
    
      try {
       item.write(new File(path,fieldName)); //注意,这里提供了一个item对象的write方法..其实也就是将上传的文件放到path路径代表的地方,另存为的文件名是fieldName
      } catch (Exception e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
    
     //下面注释的部分就是不用write方法自己复制字节流的办法
//     OutputStream out = new FileOutputStream(new File(path,fieldName));
//     InputStream is = item.getInputStream();
//     int length = 0;
//     byte[] b = new byte[400];
//     while ((length = is.read(b)) > 0)
//     {
//      out.write(b);
//     }
//     out.close();
//     is.close();
    
    }
   }
  
  
  
  } catch (FileUploadException e) {
   e.printStackTrace();
  }
  request.getRequestDispatcher("/upload/result2.jsp").forward(request, response);//将页面跳转到result2.jsp.
 
 }

}

 

3 修改web.xml...直接将代码贴上来了.蛮容易的.注意看,那个strut2的filter被我注释掉了..

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
 xmlns="
http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
http://java.sun.com/xml/ns/j2ee
 
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 
 
<!--  
 <filter>
  <filter-name>struts2</filter-name>
  <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
 </filter>
 
 <filter-mapping>
  <filter-name>struts2</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

-->
  <servlet>
    <servlet-name>UploadServlet</servlet-name>
    <servlet-class>com.test.servlet.UploadServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>UploadServlet</servlet-name>
    <url-pattern>/UploadServlet</url-pattern>
  </servlet-mapping>

</web-app>


 

至此,整个工程就结束了.当然一定要导入两个包,一个是common-fileupload.jar.还有一个是common-io.jar ..

我们之所以要说这些和struts无关的东西就是为了能了解struts2关于文件上传的底层实现..其实,strut2就是这么实现文件上传的.


struts2文件上传与下载(3)

struts学习   2009-07-20 10:06   阅读158   评论0   字号: 大大  中中  小小     这里,我们终于要用strust2自带的文件上传系统来做我们自己的文件上传了....

    首先,当然是写页面了..

upload.jsp  这个在webroot下面的upload文件夹下...没啥可说的.就是一个html

<body>

 <form action="upload.action" method="post" enctype="multipart/form-data">
 
 Information: <input type="text" name="info"><br>
 File: <input type="file" name="file"><br>
 
 <input type="submit" name="submit" value=" submit ">
 
 </form>

</body>

result.jsp 这里记得加strust2标签引入...

<body><br>

info:<s:property value="info"/><br>
filename:<s:property value="fileFileName"/>


</body>

2 写action的java文件 upload.java

这里比较长.我一个个解释

package com.test.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import com.opensymphony.xwork2.ActionSupport;

public class upload extends ActionSupport {
 
 private String info;
 private File file ; // 这里对应的jsp页面上的两个字段.没啥可以说.
 private String fileFileName;//注意,这个表示的是file这个上传对象的文件名..这个是struts2自己封装的.可以自动获取,不用和上一节一样需要我们自己去写代码.. 这里的名字后面部分"FileName"是固定的,前面的file就是上面那个file.也就是说和jsp页面的那个字段的name是对应的..
 private String fileContentType;//这里也同样,表示文件类型.struts2已经封装好的.后面的"ContentType"也是固定的.
 public String getInfo() { //下面大部分都是get,set方法,没啥好说的.都是自动生成的.
  return info;
 }
 public void setInfo(String info) {
  this.info = info;
 }
 public File getFile() {
  return file;
 }
 public void setFile(File file) {
  this.file = file;
 }
 public String getFileFileName() {
  return fileFileName;
 }
 public void setFileFileName(String fileFileName) {
  this.fileFileName = fileFileName;
 }
 public String getFileContentType() {
  return fileContentType;
 }
 public void setFileContentType(String fileContentType) {
  this.fileContentType = fileContentType;
 }
 
 @Override
 public String execute() throws Exception {
  //重头戏从这里开始
  InputStream is = new FileInputStream(file); //定义一个输入流..file对应上面的上传文件对象.
  String root = "D://file";//这里先定义一个文件上传的目录...就是将上传的文件放到D盘的file文件下面.
  File diskfile  = new File(root,this.getFileFileName());//定义输出流存放的文件夹..文件名为getFileFileName .也就是说,是和上传的文件相同.
  OutputStream os = new FileOutputStream(diskfile);//定义一个输出流..对应输出的文件夹
 
 
  byte[] buffer = new byte[400];//这里和之前的上传与下载第一节里的内容一样.不多解释了..
  int length = 0;
  while((length = is.read(buffer))>0)
  {
   os.write(buffer);
  }
  is.close();
  os.close();
 
  return SUCCESS;
 }

}

3.最后就是strut.xml配置文件了

注意,我为了避免干扰,讲拦截器都注释掉了...

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "
http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

 <constant name="struts.i18n.encoding" value="gbk"></constant>//这里定义一个编码方式是用gbk.这样你传文件的时候就可以用中文的文件名.要不然就出乱码
 
 <constant value="d:/"></constant>//这里定义的是临时目录..文件上传的时候会先将文件复制到临时目录,然后将临时目录里的文件用IO的方式上传.
 
 <constant value="message"></constant>
 
 <package name="struts2" extends="struts-default">

  <interceptors>
   <interceptor name="myInterceptor" class="com.test.interceptor2.MyInterceptor">
    <param name="hello">world</param>
   </interceptor>
  
   <interceptor name="myInterceptor2" class="com.test.interceptor2.MyInterceptor2">
   </interceptor>
  
   <interceptor name="myInterceptor3" class="com.test.interceptor2.MyInterceptor3">
  
   </interceptor>
  
   <interceptor-stack name="myStack">
  
   <!--
    <interceptor-ref name="myInterceptor"></interceptor-ref>
    <interceptor-ref name="myInterceptor2"></interceptor-ref>
   
    -->
    
    <interceptor-ref name="defaultStack"></interceptor-ref>
   
   </interceptor-stack>
  </interceptors>

  <default-interceptor-ref name="myStack"></default-interceptor-ref>

  <action name="login" class="com.test.action.LoginAction">
   <result name="input">/login2.jsp</result>
   <result name="success">/result.jsp</result>
   <result name="failer">/login2.jsp</result>
  </action>
 
  <action name="pointConverter" class="com.test.action.PointAction">
   <result name="success">/output.jsp</result>
   <result name="input">/input.jsp</result>
  </action>
 
  <action name="upload" class="com.test.action.upload">
   <result>/upload/result.jsp</result>
  </action>
 
  <action name="register" class="com.test.action.RegisterAction" method="test">
   <result name="success">/success.jsp</result>
   <result name="input">/register2.jsp</result>
  <!--  
   <interceptor-ref name="myInterceptor3">
    <param name="excludeMethods">test,execute</param>
    <param name="includeMethods">test</param>
   </interceptor-ref>
   <interceptor-ref name="defaultStack"></interceptor-ref>
   -->
  </action>
 
 </package>

</struts>
其他没可以说的.这样,我们的文件上传就已经实现了..

注意,要注入common-io.jar和common-fileupload.jar..
struts2上传与下载(4)多文件上传

struts学习   2009-07-20 13:56   阅读64   评论0   字号: 大大  中中  小小     上一节,我们完成了单个文件的上传.但是,很明显,实际应用里面,我们必须完成多文件的上传.

首先,我们先完成固定个数的多文件上传

我们修改JSP页面

upload.jsp

<body>

<form action="upload.aciton" method="post" enctype="multipart/form-data">

Information:<input type="text" name="info"><br>

file1:<input type="file" name="file"><br>

file2:<input type="file" name="file"><br>

file3:<input type="file" name="file"><br>//注意,这里的name属性都是file.这样表单提交会是一个file类型的数组

</body>

很明显,action也需要修改...

注意,其实action就修改了两个地方..一个是File类型的file变成了List<File> file 这样系统会自动给我们返回一个List数组..修改相应的get,set方法.第二个修改的地方是 execute方法里.读IO的时候进行了一个for循环.这个也不难看懂..

package com.test.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import com.opensymphony.xwork2.ActionSupport;

public class upload extends ActionSupport {
 
 private String info;
 private List<File> file ;
 private List<String> fileFileName;
 private List<String> fileContentType;
 
 public String getInfo() {
  return info;
 }

 public void setInfo(String info) {
  this.info = info;
 }

 public List<File> getFile() {
  return file;
 }

 public void setFile(List<File> file) {
  this.file = file;
 }

 public List<String> getFileFileName() {
  return fileFileName;
 }

 public void setFileFileName(List<String> fileFileName) {
  this.fileFileName = fileFileName;
 }

 public List<String> getFileContentType() {
  return fileContentType;
 }

 public void setFileContentType(List<String> fileContentType) {
  this.fileContentType = fileContentType;
 }

 @Override
 public String execute() throws Exception {
 
  for(int i=0;i<file.size();i++)
  {
   InputStream is = new FileInputStream(file.get(i));
   String root = "D://file";
   File diskfile  = new File(root,this.getFileFileName().get(i));
   OutputStream os = new FileOutputStream(diskfile);
  
  
   byte[] buffer = new byte[400];
   int length = 0;
   while((length = is.read(buffer))>0)
   {
    os.write(buffer);
   }
   is.close();
   os.close();
  }
 
 
  return SUCCESS;
 }

}
这样.这个多文件上传就做好了..还是很简单的...

现在,我们还有一个需求,我们需要动态改变上传文件的个数..其实这个也很好了解..一般用过邮箱的人都知道.系统开始会给你一个上传文件的地方.然后你可以点按钮动态添加上传的个数..我们现在就来做这个东西...

其实,这个和struts也没多大关系了..因为这个只需要修改jsp页面.而后台所有的代码都不需要修改..页面如下

upload.jsp

<%@ page language="java" contentType="text/html; charset=GB18030"
    pageEncoding="GB18030"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "
http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>Insert title here</title>

<script type="text/javascript">

 function add()
 {
 
  var td = document.getElementById("more");
 
  var br = document.createElement("br");
  var file = document.createElement("input");
  var remove = document.createElement("input");
 
  file.type="file";
  file.name="file";
  remove.type="button";
  remove.value="remove";
  remove.onclick=function()
  {
   td.removeChild(br);
   td.removeChild(file);
   td.removeChild(remove);
  }
 
  td.appendChild(br);
  td.appendChild(file);
  td.appendChild(remove);
 
 
 }

</script>

</head>
<body>

 <form action="upload.action" method="post" enctype="multipart/form-data">
   <table align="center" >
    <tr>
    <td>Information:</td><td> <input type="text" name="info"></td><td></td>
   </tr>
   <tr>
    <td>File: </td><td id="more"> <input type="file" name="file"><input type="button" value="add more.." onclick="add()"></td>
   </tr>
   <tr>
    <td colspan="2" align="center"><input type="submit" name="submit" value=" submit "></td>
   </tr>
 </table>
  </form>

</body>
</html>

这样,我们所有的工作都已经完成.其实这个说到底就是一个用javascript在客户端动态修改html..我们可以添加file或者删除file...其中的name属性还是file...很简单,不是么

 
struts文件上传与下载(5)文件大小和类型设置

struts学习   2009-07-20 17:08   阅读82   评论0   字号: 大大  中中  小小     这节说的struts框架对文件上传的大小和类型设置.

   首先,我们必须明白,struts的文件上传是通过拦截器来实现的.我们可以找到对也难怪的拦截器包..在strut2-core.jar包里面有一个struts-default.xml这个文件.我们写的struts.xml都是继承这个配置文件的.而在struts-default.xml里面有一个interceptor..叫做fileUpload..这个就是上传的拦截器..对应的class为struts-core.jar下面的org.apache.struts2.interceptor包下面有一个FileUploadInterceptor..里面可以注意两个参数.maximumSize和allowedTypes.很明显.这两个分别对应上传文件大小和类型...说到这里,我们就应该明白怎么设置了吧..我们就是在拦截器定义参数.并将参数传进去.这样子就OK了..

  如下

  <action name="upload" class="com.test.action.upload">
   <result>/upload/result.jsp</result>
   <result name="input">/upload/upload.jsp</result>
   <interceptor-ref name="fileUpload">
    <param name="maximumSize">409600</param>
    <param name="allowedTypes">text/plain</param>
   </interceptor-ref>
   <interceptor-ref name="defaultStack"></interceptor-ref>注意,这里要将默认拦截器加上.什么原因,不说了
  </action>

这里,我们注意在设置 类型的时候,后面的参数是 text/plain ..我们怎么知道这个参数是什么呢..我们可以看tomcat目录下面的conf下的web.xml  比如我的D:/apache-tomcat-6.0.14/apache-tomcat-6.0.14/conf.下的web.xml..里面有类型定义..比如  

 <mime-mapping>
        <extension>mp3</extension>
        <mime-type>audio/x-mpeg</mime-type>
    </mime-mapping>

这里就说明.后缀是mp3的对应的是audio/x-mpeg   具体用到什么就是什么....

做到这里,我们需要的基本需求已经差不多完成了..运行之后,我们会发现,如果上传文件的类型或者大小不符合要求的话.他会自动返回一个Input.然后跳转回upload.jsp...注意,这里还会自动执行addFiledError.并添加相应的错误信息..当然,错误信息的内容我们也可以修改...可以再strut2-core.jar包下面的org.apache.struts2下面找到一个struts-messages.properties文件.这里有系统默认的提示信息..我们可以修改相应的信息..在哪修改呢...还记得以前我们定义的message.properties么...我们就是进行全局修改...在message.properties下面添加

struts.messages.error.content.type.not.allowed=/u4e0a/u4f20/u6587/u4ef6/u7c7b/u578b/u9519/u8bef 

这样,类型错误的信息就会提示..后面是中文 "类型转换错误"的编码..通过jdk自带的 native2ascii 命令得到的..以前说过了,不具体说...

所有的一切都OK了.记得在JSP页面上加上<s:fielderror></s:fielderror> .这样,如果错误的话,相应的错误信息就会显示出来了...

struts2上传与下载(6) 下载

struts学习   2009-07-21 10:16   阅读63   评论0   字号: 大大  中中  小小    下载部分相应来说比较简单...只要返回一个InputStream就OK...具体的做法.

页面..

download.jsp 超级简单.就是一个<a>标签.链接到download.action

<body>
    <a href="download.action">download</a>
  </body>

action  

DownloadAction.java

package com.test.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class DownloadAction extends ActionSupport {
 
 public InputStream getDownloadFile() throws FileNotFoundException
 {//这里定义这个get方法是因为在struts.xml配置文件里要设置一个downloadFile(这里注意javabean的规范.D字从大写变回小写)这个参数.返回值是一个inputStream
  System.out.println("gose here");
  File file = new File("d://Struts2.ppt");
  InputStream in = new FileInputStream(file);//这里的InputStream是一个File类型的..
  return in;
  //return ServletActionContext.getServletContext().getResourceAsStream("/upload/Struts2.ppt");//这里是获取当前目录下的文件返回InputStream.
 }

 public String execute(){
   return SUCCESS;
 }
}

配置文件struts.xml

<action name="download" class="com.test.action.DownloadAction">
   <result type="stream">//注意,这里的类型是流类型.对应的类可以到struts-default.xml下面看
    <param >application/powerpoint</param>//这里是下载文件的类型.这里是PPT文件.默认是txt.参数的名字在上一节已经说了,可以在tomcat的conf下面的web.xml里面查找.
    <param >filename="aaa.ppt"</param>//这里是文件另存为的名字
    <param >downloadFile</param>//注意,这里这个参数就是对应action里面我们写的get方法
   </result>
 
  </action>

 

最最简单的文件下载.就是这样了..很简单了.呵呵

struts2相关内容的补充(1)

struts学习   2009-07-21 16:09   阅读26   评论0   字号: 大大  中中  小小     我们必须知道两个非常重要的配置文件.一个是default.properties 一个是struts-default.xml .下面来分别说

   default.properties在struts-core.jar包里的org.apache.struts2里面..他是一个属性文件,对应nama和value 其中几个name我们必须要注意

struts.i18n.encoding=UTF-8   系统默认的编码方式就是在这里定义的..我们可以修改为GBK.方法后面会说.

struts.multipart.saveDir=  这个没定义.是上传文件的临时文件存放目录..如果你指定,系统会报一个临时目录不存在的警告,不过他还是会给你自动配一个的.在tomcat里面...

struts.multipart.maxSize=2097152 这个很好理解.就是上传文件的大小限制.2M的大小.记得这里的单位是字节

struts.action.extension=action,, 这个是struts2的默认后缀名修改.你可以改成abc..只要相应的jsp页面里也修改就行

暂时我知道的就这么些了,以后有用到再补吧.

这里开始说配置这些属性的办法.很明显,default.properties是只读的.不许修改.我们有三种办法可以修改它..

    第一,也是最不常用的办法.在web.xml里面..比如这样

 <filter>
  <filter-name>struts2</filter-name>
  <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
  <init-param>
   <param-name>struts.i18n.encoding</param-name>在核心的控制器里进行初始化..配置一个属性就得四行代码.怎么都说不过去..虽然优先级最高,但是一般是不用的.
   <param-value>gbk</param-value>
  </init-param>
 </filter>
 
 <filter-mapping>
  <filter-name>struts2</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

    第二,在struts.xml里面配置...还记得以前我们配置编码方式不..就这样

<constant name="struts.i18n.encoding" value="gbk"></constant>
 
 <constant name="struts.multipart.saveDir" value="d:/"></constant>
   第三,在scr目录新建一个struts.properties文件...里面就是按照属性文件的方式来写..就是这样

struts.i18n.encoding = gbk

一般推荐使用第三种.

 

 

下面说下 struts-default.xml ..这个xml文件就在struts-core.jar包里.他是一个抽象包.也就是说,不能定义action.只能由继承他的xml文件才能定义action.比如我们之前一直用的struts.xml..

在struts.xml里面还有一点要说明下.就是命名空间的.问题..一般大的项目都会进行命名空间分配.这里就用到一个namespace..比如

<package name="struts2" extends="struts-default" namespace="hello">

这里,将命名空间指定为hello.假设这个package里面有一个action name为login.这样的话我们页面如果写成

<form action="login.action"> 将无法找到这个action.我们需要写成

<form action="/hello/login.action">

这里还注意一个问题..我们在用struts自带的标签的时候,我们写form action是不需要加后缀".action"的,但是加入命名空间以后我们就必须加.action..

 

最后,我们可以在struts.xml里面include其他的xml文件.这些配置文件就是为了减少struts.xml的代码量用的..这个很好理解.不多说了.


  
struts2相关内容补充(2)表单重复提交处理

struts学习   2009-07-22 14:19   阅读34   评论0   字号: 大大  中中  小小       很实用的功能..struts2处理非常简单.

1.首先在jsp的form标签下面加这个标签.就像这样

<s:form action="register"  >
 <s:token></s:token>

我们可以看到.这里会创建一个32的加密的value值.通过这个值来判断是否重复提交

2 配置文件修改..需要在对应的action申明里面添加token拦截器.如下

  <action name="register" class="com.test.action.RegisterAction" >
   <result name="success">/success.jsp</result>
   <result name="input">/register2.jsp</result>
   <result name="invalid.token">/register2.jsp</result>
   <interceptor-ref ></interceptor-ref>
 <interceptor-ref name="defaultStack"></interceptor-ref>
 </action>

3 在配置文件里添加一个result.对面的name为invalid.token..可以上上面那段代码.已经添加好了.

这里是因为,如果struts发现我们的操作是重复表单提交的话,会返回一个result .名字为 invalid.token .所以我们需要添加一个对应的处理..

注意,这里其实就是一个验证.如果验证错误的话就会返回一个invalid.token.当然他也会自动产生一个错误信息..默认可以看struts2-core.jar包下面的struts-message.properties.里面有一个

struts.messages.invalid.token=The form has already been processed or no token was supplied, please try again.

这个就是重复提交的默认错误提示.我们可以重写..以前已经说了.不具体说了.

最后说明下.这个错误信息是添加到addActionError里的.所以如果要在页面上显示的话需要添加标签

<s:actionerror/> 

struts2整合spring

struts学习   2009-07-23 10:39   阅读233   评论5   字号: 大大  中中  小小    spring的作用.之前也说明了很多.其实就是IoC和AOP...很多人都说,spring就是玩配置文件....其实,spring最大的作用就是为了减少类之间的耦合.平时使用两个类,调用的时候难免会发生耦合.但是又不能没有一点耦合.那这两个类将一点关系都没有..spring的解决办法就是IoC.叫依赖注入...比如.类A要调用类B里的办法..怎么解决呢.我们以前的办法就是类A主动去调用类B.但是spring给出的办法是需要的时候给你...而且这个地方是通过配置文件来实现的.也就是说,是配置文件来给你.

   开始之前,首先要说明一点,在struts的流程里有一步是struts.xml以后根据action name来调用对应的action类..我们之前的struts实现办法是自动生成一个action实例..是struts自动通过自带的factory来实现的..但是,我们这里需要用spring来帮我们生产action实例.当然,action里面调用的方法也通过spring来注入.

  第一步,当然是导入相应的jar包.将struts2下载里面的struts2-spring-plugin.jar放入lib下..然后通过myeclipse导入spring..具体的办法是在相应的工程目录,右键,Myeclipse -->Add Spring Capabilities.然后在对话框里面.Spring 2.0 Core 打钩(这个默认已经打钩了),还有Spring 2.0 Web 打钩,因为我们需要用到里面的一个Listener.下面选择Copy checked Library contents.....如下图

然后就一直下一步.不需要修改了..

 第二步.配置web.xml..因为我们需要通过spring来生成action实例..(也就是说.告诉struts ,spring的存在)

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
 xmlns="
http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
http://java.sun.com/xml/ns/j2ee
 
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 
 
  
 <filter>
  <filter-name>struts2</filter-name>
  <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
 </filter>
 
 <filter-mapping>
  <filter-name>struts2</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
<listener >
 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

</web-app>

 

第三步,写两个jsp页面测试.很简单,一个登陆页面,一个结果页面

login2.jsp

 <s:form action="login" >
 
 <s:textfield name="username" label="username"></s:textfield>
 <s:password name="password" label="password"></s:password>
 <s:submit ></s:submit>
 
 </s:form>

result.jsp

<body>

 username:<%=request.getParameter("username") %>
 password:<%=request.getParameter("password") %>

  </body>

两个都很简单,不多说了

第四步.写个业务处理类.包括一个接口,一个实现类..两个java文件

我们以前写的例子都是将业务代码放到action里面.很明显,这样做是不好的..我们需要将业务代码分离出来.而action只需要调用..

接口类LoginService.java 就定义了一个方法.返回一个布尔值

package com.test.service;

public interface LoginService {
 public boolean isLogin(String username,String password);
}

实现类 LoginServiceImpl.java 实现类..假如username为hello.password为world的时候返回真..其他都为假

package com.test.serviceImpl;

import com.test.service.LoginService;

public class LoginServiceImp implements LoginService {

 @Override
 public boolean isLogin(String username, String password) {
 
  if("hello".equals(username)&&"world".equals(password))
  {
   return true;
  }
  else
  {
   return false;
  }
 
 }

}

第五步,当然是写我们的action...LoginAction.java

package com.test.action;

import com.opensymphony.xwork2.ActionSupport;
import com.test.service.LoginService;

public class LoginAction extends ActionSupport {
 private String username;
 private String password;
 private LoginService loginService;//这里引入了一个LoginService.但是没有实例化.(如果在这里实例化,那就不用spring了...我们就是靠spring来注入这个loginService)
 public String getUsername() {
  return username;
 }
 public void setUsername(String username) {
  this.username = username;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
   
 public void setLoginService(LoginService loginService) {//注意这里需要定义一个set方法.因为spring需要调用这个set方法
  this.loginService = loginService;
 }
 public String execute() throws Exception{
 
  if(loginService.isLogin(username, password))
  {
   return SUCCESS;//注意,这里只有调用的代码,没有业务逻辑代码了
  }
  else {
   return INPUT;
  }
 

}


第六步..配置struts.xml

  <action name="login" class="loginAction">//注意,这里的class已经不是和以前那样的一个类的全名.而是一个自定义的名字.这个名字对应到了等下我们将要配置的applicationContext.xml(也就是spring的配置文件)里定义的bean Id ..
   <result name="input">/login2.jsp</result>
   <result name="success">/result.jsp</result>
   </action>
第七步,applicationContext.xml   spring的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans
 xmlns="
http://www.springframework.org/schema/beans"
 xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">


<bean id="loginservice" class="com.test.serviceImpl.LoginServiceImp"></bean>//这里定义了一个loginservice的组件.对应业务逻辑的实现类

<bean id="loginAction" class="com.test.action.LoginAction" scope="prototype">//定义action.scope="prototype 表示请求一次,实例化一次
 <property name="loginservice">
  <ref local="loginservice"/>//将这个业务逻辑的实现类注入...
 </property>
</bean>

</beans>

第八步..差不多都弄好了..不过需要将applicationContext.xml移到WEB-INF下面.测试,应该OK了

如果你不想把这个applicationContext.xml放到web-inf下..你可以在web.xml里面指定对应的存放地址.甚至可以写多个配置文件 ..方法是

<context-param>

    <param-name>contextConfigLocation</param-name>

    <param-value>/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml</param-value>

</context-param>

上面这个是官方网站上拉来的代码..很容易懂.不多说了...注意对应的目录

SSH框架的第一个整合例子

SSH框架整合   2009-07-25 11:28   阅读27   评论0   字号: 大大  中中  小小 ,我们先实现一个最基本的需求..添加,然后保存以后返回列表页面.这里先不包括验证什么的..都假设输入是正确的.验证到下一节说明..

我们从需求出发...一步步实现.我这里用的是myeclipse6.0 .struts2.0.16.spring2.0 hibernate3 mysql5.1

1.准备工作...当然是数据库了..在mysql数据库里,创建一个名为"user"的数据库.创建一个表也叫"user". 表里面就三个字段,id ,username ,age这里我的数据库名为 root 密码为11.

2.创建一个web project .工程名是myTest1.选择JAVA EE 5.0..点finish.

3导入hibernate.点工程右键,MyEclipse 选择Add hibernate capabilities.上面的不变.下面下面的JAR Library Installation .选择Copy cheched Library..点next .这里不需要修改,点Next.将最上面的勾去掉.我们等下自己写这个factory.点next.再将上面的勾去掉.点finish..

4.导入spring..点工程右键,MyEclipse 选择Add spring capabilities..其中Libraries选择前四个.还有一个Spring 2.0 Web libraries ..一共是五个..下面的JAR Library Installation .选择Copy cheched Library...这个.也就是将加入的jar包复制到lib目录下..点next .在产生applicationContext.xml的目录里选择WebRoot/WEB-INF 点next.把上面的√去掉.等下我们自己写...最后点FINISH.spring就导入成功了

5 导入struts2..现在myeclipse还不支持导入struts2.所以这里我们需要手动导入.方法也很简单..将struts2.0.16客户端的jar包里.选择freemarker.jar,ognl.jar.struts2-spring-plugin.jar.xwork.jar.struts-core.jar.这里不需要导入common-logging.jar.因为spring里面已经有这个jar包了.所以不需要再次导入..然后在src目录下创建一个struts.xml..这样就差不多了.

这里特别注意一下.需要将common-pool.jar包放到Lib目录下..貌似myeclipse6.5就会自动导入.6.0不会的说

6 准备工作差不多了.终于开始写页面了...首先,我们先做一个save.jsp..里面有一个表单,输入名字和年龄..

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
   
    <title>My JSP 'save.jsp' starting page</title>

  </head>
 
  <body>
 <s:form action="userAction">//注意,我们这里选择模型驱动.而不是字段驱动.

还有,这个action name 设置为 userAction ..
  <s:textfield name="user.username" label="username"></s:textfield>
  <s:textfield name="user.age" label="age"></s:textfield>
  <s:submit></s:submit>
 </s:form>
  </body>
</html>

7创建bean..这个很简单.就是在com.test.model下面创建一个User.java.标准的bean.没啥可说的

package com.test.model;

public class User {
 
 private Integer id;
 private String username;
 private int age;
 public Integer getId() {
  return id;
 }
 public void setId(Integer id) {
  this.id = id;
 }
 public String getUsername() {
  return username;
 }
 public void setUsername(String username) {
  this.username = username;
 }
 public int getAge() {
  return age;
 }
 public void setAge(int age) {
  this.age = age;
 }
 
 

}


 

7 开始写action .首先在src下面创建一个com.test.action包.在这个包下面创建UserAction.java

package com.test.action;

import com.opensymphony.xwork2.ActionSupport;
import com.test.model.User;
import com.test.service.UserService;

public class UserAction extends ActionSupport {
 
 private UserService userservice;
 
 private User user;
 
 public UserService getUserservice() {
  return userservice;
 }

 public void setUserservice(UserService userservice) {
  this.userservice = userservice;
 }

 public User getUser() {
  return user;
 }

 public void setUser(User user) {
  this.user = user;
 }
 
 public String execute(){
 
  userservice.saveUser(user);
 
  return SUCCESS;
 }
}

这里在流程上已经有点偏了.因为这里我直接写出了userserive.这个类我们还没实现..而在实现这个service以前我们又必须实现userDAO.下一步,我们实现userDAO

8 新建一个包.com.test.DAO 这个是存放DAO接口的..spring要求我们必须面向接口编程 创建一个UserDAO.java

package com.test.DAO;

//这里定义了五个方法.分别是增删改查..查里面有两个,一个是根据ID查,一个是查所有.
import java.util.List;

import com.test.model.User;

public interface UserDAO {
 
 public void addUser(User user);
 
 public void delUser(User user);
 
 public void updateUser(User user);
 
 public User selectById(Integer id);
 
 public List<User> selectAll();

}
9 创建一个com.test.DAO.impl包.实现上面定义的UserDAO ...类名是UserDAOimpl

package com.test.DAO.impl;//这里结合了hibernate.所以我们继承 HibernateDaoSupport来实现相应的操作.都很简单的..就要注意下selectALL方法.里面用到了hql语句

import java.util.List;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.test.DAO.UserDAO;
import com.test.model.User;

public class UserDAOimpl extends HibernateDaoSupport implements UserDAO {

 @Override
 public void addUser(User user) {
  this.getHibernateTemplate().save(user);

 }

 @Override
 public void delUser(User user) {
  this.getHibernateTemplate().delete(user);
 }

 @Override
 @SuppressWarnings("unchecked")
 public List<User> selectAll() {
   String hql= "from User";
   return (List<User>)this.getHibernateTemplate().find(hql);
 
 }

 @Override
 public User selectById(Integer id) {
  return (User)this.getHibernateTemplate().get(User.class, id);
 }

 @Override
 public void updateUser(User user) {
  this.getHibernateTemplate().update(user);

 }

}


10创建好了DAO实现数据库的操作..现在开始写Service业务层...由于我们没有任何事务,所以Service就是调用一次DAO层...首先还是创建一个包来放接口.com.test.service ..里面的类UserService.java

package com.test.service;

import java.util.List;

import com.test.model.User;

public interface UserService {//这里也对应DAO.写了五个方法..
 
 public void saveUser(User user);
 
 public void delUser(User user);
 
 public void updateUser(User user);
 
 public User findById(int id);
 
 public List<User> findAll();

}

11同理,当然是写这个service的实现类..com.test.service.impl包..UserServiceImpl.java

package com.test.service.impl;//这里没写什么业务,只是调用了一次dao.

import java.util.List;

import com.test.DAO.UserDAO;
import com.test.model.User;
import com.test.service.UserService;

public class UserServiceImpl implements UserService {
 
 
 private UserDAO userdao;
 
 

 public UserDAO getUserdao() {
  return userdao;
 }

 public void setUserdao(UserDAO userdao) {
  this.userdao = userdao;
 }

 @Override
 public void delUser(User user) {
 
  userdao.delUser(user);
 
 }

 @Override
 public List<User> findAll() {
  return userdao.selectAll();
 }

 @Override
 public User findById(int id) {

  return userdao.selectById(id);
 }

 @Override
 public void saveUser(User user) {
  userdao.addUser(user);

 }

 @Override
 public void updateUser(User user) {
  userdao.updateUser(user);

 }

}

12 最重要的地方开始了.就是配置applicationContext.xml.直接放上来代码,一点点解释吧.

<?xml version="1.0" encoding="UTF-8"?>
<beans
 xmlns="
http://www.springframework.org/schema/beans"
 xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName">//配置dataSource.这个部分在hibernate里面说的比较多了.不多说了
   <value>com.mysql.jdbc.Driver</value>
  </property>
  <property name="url">
   <value>jdbc:mysql://localhost/user</value>
  </property>
  <property name="username">
   <value>root</value>
  </property>
  <property name="password">
   <value>11</value>
  </property>
 </bean>
 <bean id="factory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="mappingResources">
   <value>com/test/model/User.hbm.xml</value>
  </property>
  <property name="hibernateProperties">
   <props>
    <prop key="hibernate.dialect">
     org.hibernate.dialect.MySQLDialect
    </prop>
    <prop key="hibernate.show_sql">true</prop>
   </props>
  </property>
  <property name="dataSource">
   <ref bean="dataSource"/>
  </property>
 </bean>
 
 <bean id="UserDao" class="com.test.DAO.impl.UserDAOimpl">
  <property name="sessionFactory">//这个部分也说明了.其实就是在DAO里面注入一个factory.我们在调用this.getHibernateTemplate() 的时候必须有这个factory.
   <ref bean="factory"/>
  </property>
 </bean>
 
 <bean id="UserService" class="com.test.service.impl.UserServiceImpl">
  <property name="userdao">//在类UserServiceImpl里面定义了一个userdao.这里的这个name属性必须和那里的名字相同.因为要调用那里的set方法.
   <ref bean="UserDao"/>//依赖注入.spring里面说了很多了...
  </property>
 </bean>
 
 <bean >
  <property name="userservice">//这个同上了..UserAction里面也有一个相应的set方法..
   <ref bean="UserService"/>
  </property>
 </bean>
 
 <bean id="listActionClass" class="com.test.action.ListAction">
  <property name="service">//这个是配置下面list页面的时候用的...先放上来了...免得重复黏贴
   <ref bean="UserService"/>
  </property>
 </bean>

</beans>

13 save页面的最后一步当然是配置struts.xml.结果页面下面再说

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "
http://struts.apache.org/dtds/struts-2.0.dtd">
    <struts>
   
    <package name="user" extends="struts-default">
   
     <action name="userAction" class="userActionClass">
      <result type="redirect">ListAction.action</result>//这里重定向到ListAction.显示list页面
      <result name="input">/save.jsp</result>
     </action>
    
     <action name="ListAction" class="listActionClass">
      <result >/list.jsp</result>//list页面的action配置
      <result name="input">/index.jsp</result>
     </action>
   
    </package>
   
    </struts>

14 至此,save页面已经全部完成.但是提交以后总要显示列表信息吧..也就是将数据库里的数据全部取出来显示.所以,我们在com.test.action下面再写一个action.叫ListAction.java

package com.test.action;

import java.util.Map;


import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.test.service.UserService;

public class ListAction extends ActionSupport {
 
 private UserService service;

 public UserService getService() {
  return service;
 }

 public void setService(UserService service) {
  this.service = service;
 }
 
 @SuppressWarnings("unchecked")
 @Override
 public String execute() throws Exception {
  Map request = (Map)ActionContext.getContext().get("request");获取一个request的MAP对象
 
  request.put("list", service.findAll());//放入MAP
 
  return SUCCESS;
 }
 

}

15 这里,还忘记一个重要的东西..就是bean对应的hbm.xml 因为我使用Middlegen自动生成的,所以代码多一些..ID的生产策略是加一..

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "
http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
   
<hibernate-mapping>
<!--
    Created by the Middlegen Hibernate plugin 2.1

    http://boss.bekk.no/boss/middlegen/
    http://www.hibernate.org/
-->

<class
    name="com.test.model.User"
    table="user"
>
    <meta attribute="class-description" inherit="false">
       @hibernate.class
        table="user"
    </meta>

    <id
        name="id"
        type="java.lang.Integer"
        column="id"
    >
        <meta attribute="field-description">
           @hibernate.id
            generator-class="assigned"
            type="java.lang.Integer"
            column="id"


        </meta>
        <generator class="increment" />
    </id>

    <property
        name="username"
        type="java.lang.String"
        column="username"
        not-null="true"
        length="50"
    >
        <meta attribute="field-description">
           @hibernate.property
            column="username"
            length="50"
            not-null="true"
        </meta>   
    </property>
    <property
        name="age"
        type="int"
        column="age"
        not-null="true"
        length="10"
    >
        <meta attribute="field-description">
           @hibernate.property
            column="age"
            length="10"
            not-null="true"
        </meta>   
    </property>

    <!-- Associations -->
 

</class>
</hibernate-mapping>

16 我忘记了一个非常重要的配置..web.xml.这么重要的东西.不多说了.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
 xmlns="
http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
 
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  
 <filter>
  <filter-name>struts2</filter-name>
  <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
 </filter>
 
 <filter-mapping>
  <filter-name>struts2</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>


<listener>
 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

</web-app>

17又忘记一个jar包.就是jdbc连mysql的驱动包..我用的是mysql-connector-java-5.1.7-bin.jar

18 最后是我们的列表页面.list.jsp .里面用到ognl表达式.有空得去学习下

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
 
    <title>My JSP 'list.jsp' starting page</title>
  
  </head>
 
  <body>
<h1><font color="red"><center>User List</center></font></h1>

<table align="center" border="1" width="80%">
 <tr>
  <td>序号
  </td>
 
  <td>名字
  </td>
 
  <td>年龄
  </td>
 
  <td>删除
  </td>
 
  <td>修改
  </td>
  </tr>
 <s:iterator value="#request.list" id="us">
 <tr>
  <td><s:property value="#us.id"/>
  </td>
 
  <td><s:property value="#us.username"/>
  </td>
 
 
  <td><s:property value="#us.age"/>
  </td>
 
  <td><s:a href="deleteUser.action?user.id=%{#us.id}">删除</s:a>
  </td>
 
  <td><s:a href="updatePUser.action?user.id=%{#us.id}">修改</s:a>
  </td>
  </tr>
 </s:iterator>

</table>
  </body>
</html>
19 最后..终于测试通过.

 

原创粉丝点击