`

Struts1.2

阅读更多

改自:http://www.blogjava.net/nokiaguy/archive/2009/01/13/251101.html

一、本文给出的程序要实现什么功能
    mystruts是一个录入和查询产品信息的程序。为了方便起见,本例中的产品信息表只包括了产品 ID、产品名称和产品价格三个字段。 mystruts的主要功能如下:

   1.   接受用户输入的产品 ID、产品名称和产品价格。

 2. 验证这些字段的合法性。如果某些字段的输入不合法(如未输入产品 ID),程序会 forward到一个信息显示页,并显示出错原因。

 3. 如果用户输入了正确的字段值,程序会将这些字段值保存到数据库中,并显示“保存成功”信息。

   4. 用户输入产品名称,并根据产品名称进行模糊查询。如果存在符合要求的产品信息。程序会以表格形式显示这些产品的信息,同时显示记录数。如果未查到任何记录,会显示“没有符合要求的记录 !”信息。

---------------------------------------------------------------------------------------------------------------------------------

另外,为了便于查找错误,我加入了调试是用的日志信息,加入log4j的包log4j-1.2.16.jar到WEB_INF-lib目录里.

使用教程请看http://www.blogjava.net/zJun/archive/2006/06/28/55511.html

在SRC目录里创建log4j.properties

 

log4j.rootCategory=INFO, stdout 

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=MSG:%m--TIME:%d{HH:mm:ss,SSS}---LOCATION:%l %n

--------------------------------------------------------------------------------------------------------------------------------

二、编写程序前的准备工作

1. 建立数据库
    在编写程序之前,需要建立一个数据库( struts )和一个表 (t_products) ,建立数据库和表的 SQL 脚本如下所示:

  # 建立数据库struts
  CREATE DATABASE IF NOT EXISTS struts DEFAULT CHARACTER SET GBK;

  # 建立表t_products
  CREATE TABLE IF NOT EXISTS struts.t_products (
    product_id varchar(4) NOT NULL,
    product_name varchar(50) NOT NULL,
    price float NOT NULL,
    PRIMARY KEY  (product_id)
  ) ENGINE=InnoDB DEFAULT CHARSET=gbk;

 

建立一个支持 struts1.x samples 工程
    
MyEclipse建立一个 samples工程( Web工程),现在这个 samples工程还不支持 Struts1.x(没有引入相应的 Struts jar包、 struts-config.xml文件以及其他和 Struts相关的配置)。然而,在 MyEclipse中这一切并不需要我们手工去加入。而只需要使用 MyEclipse的【 New Struts Capabilities】对话框就可以自动完成这些工作。

      首先选中 samples工程,然后在右键菜单中选择【 MyEclipse > New Struts Capabilities】,启动【 New Struts Capabilities】对话框。对默认的设置需要进行如下的改动:

(1)   将Struts specification改为Struts 1.2。

(2) Base package for new classes 改为 struts

(3) Default application resources 改为 struts.ApplicationResources
改完后的【 New Struts Capabilities】对话框如图 1所示。

图1

在设置完后,点击 Finish按钮关闭对话框。在向 samples工程添加支持 Struts的功能后,主要对 samples工程进行了三个操作。

1)引入了 Struts 1.2 jar包(在 samples的工程树中多了一个 Struts 1.2 Libraries节点)。

2)在 WEB-INF目录中添加了一个 struts-config.xml文件。文件的默认内容 如下面的代码所示:

  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://struts.apache.org/dtds/struts-config_1_2.dtd">  
  <struts-config>
    <data-sources />
    <form-beans />
    <global-exceptions />
    <global-forwards />
    <action-mappings />
    <message-resources parameter="struts.ApplicationResources" />
  </struts-config>

3)在 WEB-INF中的 web.xml文件中添加了处理 Struts动作的 ActionServlet的配置,默认代码 如下:

<servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
      <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <init-param>
      <param-name>debug</param-name>
      <param-value>3</param-value>
    </init-param>
    <init-param>
      <param-name>detail</param-name>
      <param-value>3</param-value>
    </init-param>
    <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

 到目前为止, samples工程已经完全支持 Struts了。读者可以看到,如果不使用 MyEclipse,那么上面所列出的配置文件的内容都必须手工输入。因此,使用 MyEclipse来开发 Struts程序可以省去很多配置 xml文件的工作。

三、实现程序的首页 (index.jsp)

    首先在 <samples工程目录 >中建立一个 mystruts目录,然后在 <samples工程目录 >" mystruts目录中建立一个 index.jsp文件,这个文件的内容如下。

 <%@ page pageEncoding="GBK"%>
  <%-- 引用Struts tag--%>
  <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
  <html>
      <head>
          <title>主界面</title>
      </head>
      <body>
          <table align="center" cellpadding="10" width="100%">
              <tr>
                  <td align="right" width="50%">
                  <%-- 使用Struts tag--%>
                      <html:link forward="newProduct_link">录入产品信息</html:link>
                  </td>
                  <td>
                      <html:link forward="searchProduct_link">查询产品信息</html:link>
                  </td>
              </tr>
          </table>
      </body>
  </html>

  MyEclipse中启动 Tomcat(如果 Tomcat处于启动状态,在修改完配置文件后,建议在 MyEclipse Servers页重新发布 samples工程,以使修改生效)。在 IE中输入如下的 URL

http://localhost:8080/samples/mystruts/index.jsp

    我们发现在输入上面的 URL后,在 IE中并未显示正确的运行结果,而是抛出了如下的异常:

java.net.MalformedURLException: Cannot retrieve ActionForward named newProduct

   
这个异常表明程序并未找到一个叫 newProduct forward forward将在后面详细地讲述)。因此,可以断定,在 JSP中使用 forward时,这个 forward必须存在。下面我们来添加 index.jsp页面中所使用的两个 forward newProduct searchProduct。这两个 forward分别引向了建立产品信息的页面 (newProduct.jsp)和查询产品信息的页面 (searchProduct.jsp)。我们可以在 struts-config.xml文件中 <struts-config>节点中添加两个全局的 forward,代码如下:

  <global-forwards >
  	<forward name="newProduct_link" path="/mystruts/newProduct.jsp"></forward>
  	<forward name="searchProduct_link" path="/mystruts/searchProduct.jsp"></forward>
  </global-forwards>

 上面的代码中所示的 newProduct.jsp searchProduct.jsp目前并不存在(将在以后实现这两个 JSP页面),现在重新输入上述的 URL,会得到如图 2所示的效果。

   如果想让 index.jsp成为默认的 JSP页面,可以在 web.xml中的 <welcome-file-list>节点中加入如下的内容:

 <welcome-file>index.jsp</welcome-file>

  这时在 IE中只要输入如下的 URL就可以访问 index.jsp页面了。

http://localhost:8080/samples/mystruts

四、实现添加和查询产品信息页面
   
在本节中主要实现了用于输入产品信息( newProduct.jsp)和查询产品信息 (searchProduct.jsp) JSP页面。

    newProduct.jsp页面中有一个 form,在 form中含有三个文本框,用于分别输入产品 ID、产品名称和产品价格。
<samples工程目录 >"mystruts目录中建立一个 newProduct.jsp文件,代码如下:

  <%@ page pageEncoding="GBK"%>
  <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
  <html>
      <head>
          <title>录入产品信息</title>
      </head>
      <body>
          <%-- 向saveProduct动作提交产品信息 --%>
          <html:form action="saveProduct"> 
              <table width="100%">
                  <tr>
                      <td align="center">
                          产品编号:
                          <html:text property="productID" maxlength="4" />
                          <p>
                              产品名称:
                              <html:text property="productName" />
                          <p>
  
                              产品价格:
                              <html:text property="price" />
                      </td>
                  </tr>
                  <tr>
                      <td align="center">
                          <br>
                          <html:submit value=" 保存 " />
                      </td>
                  </tr>
              </table>
          </html:form>
      </body>
  </html>

  searchProduct.jsp 页面中有一个 form ,为了方便起见,在 form 中只提供了一个文本框用于对产品名称进行模糊查询。在 <samples 工程目录 >" mystruts 目录中建立一个 searchProduct.jsp 文件,代码如下:

<%@ page pageEncoding="GBK"%>
  <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
  <html>
      <head>
          <title>查询产品信息</title>
      </head>
      <body>
          <%--  向searchProduct动作提交查询请求 --%>
          <html:form action="searchProduct">
              <table width="100%">
                  <tr>
                      <td align="center">
                          产品名称:
                          <html:text property="productName" />
                      </td>
                  </tr>
                  <tr>
                      <td align="center">
                          <br>
                          <html:submit value=" 查询 " />
                      </td>
                  </tr>
              </table>
          </html:form>
      </body>
  </html>

  现在启动 Tomcat,并使用如下两个 URL来访问 newProduct.jsp searchProduct.jsp

http://localhost:8080/samples/mystruts/newProduct.jsp
http://localhost:8080/samples/mystruts/searchProduct.jsp

IE中输入上面的两个 URL后,并不能显示出相应的界面,而会抛出 JspException 异常,表明未找到 saveProduct searchProduct 动作。从这一点可以看出,如果在 JSP 中使用 Struts Action ,这些 Action 必须事先在 struts-config.xml 文件中定义,否则, JSP 程序就无法正常访问。在这两个页面所使用的动作( saveProduct searchProduct )将会在下面的部分介绍。

 

现在启动 Tomcat,并使用如下两个 URL来访问 newProduct.jsp searchProduct.jsp

http://localhost:8080/samples/mystruts/newProduct.jsp
http://localhost:8080/samples/mystruts/searchProduct.jsp

IE中输入上面的两个 URL后,并不能显示出相应的界面,而会抛出 JspException 异常,表明未找到 saveProduct searchProduct 动作。从这一点可以看出,如果在 JSP 中使用 Struts Action ,这些 Action 必须事先在 struts-config.xml 文件中定义,否则, JSP 程序就无法正常访问。在这两个页面所使用的动作( saveProduct searchProduct )将会在下面的部分介绍。


五、通过模型类操作数据库

    在这一节我们来编写用于操作数据库的模型类。由于本例子是 Web 程序,因此,建议在连接数据库时使用数据库连接池。 <Tomcat 安装目录 >"conf"Catalina"localhost 目录中打开 samples.xml 文件(如果没有该文件,则建立一个 samples.xml 文件) <Tomcat7.0 安装目录 >"conf" 目录中打开context.xml,在 <Context> 节点中加入如下的内容:

配置连接池(用于连接数据库 struts

	<Resource name="jdbc/EmployeeDB"
            auth="Container"
            type="javax.sql.DataSource"
            username="root"
            password="123qwe"
            driverClassName="com.mysql.jdbc.Driver"
            url="jdbc:mysql://localhost:3306/struts?CharacterEncoding=GBK"
            maxActive="8"
            maxIdle="4"/>

  详细内容参见Tomcat里的DateSource配置说明

 

本例中提供了两个可以操作数据库的模型类: SaveProduct_model SearchProduct_model

其中 :1) SaveProduct_model用于验证由客户端提交的产品信息,并向 t_products表中写入这些信息。

       2) SearchProduct_model类用于对 t_products表的 product_name字段进行模糊查询,并返回查询到的产品信息(包括产品 ID、产品名称和产品价格)。

   由于 SaveProduct_model SearchProduct_model 都需要使用数据库连接池来连接数据库,因此,可以将连接数据库的工作提出来作为一个父类 (ConnDB ) 提供,代码如下:

package com.xxx.db;

import java.sql.Connection;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

import org.apache.log4j.Logger;

public class ConnDB {
	protected javax.naming.Context ctx;
	protected javax.sql.DataSource ds;
	protected Connection conn;

	Logger log = Logger.getLogger(ConnDB.class);
	
	public ConnDB() throws Exception {
		log.info("连接池初始化");
		Context initCtx = new InitialContext();
		Context envCtx = (Context) initCtx.lookup("java:comp/env");
		DataSource ds = (DataSource) envCtx.lookup("jdbc/EmployeeDB");
		conn = ds.getConnection();
		log.info("连接池完成");
	}
}

  <samples 工程目录 >"src 目录中的com.xxx.model包里建立一个 SaveProduct_model.java文件,代码所示:

package com.xxx.model;

import java.sql.PreparedStatement;
import com.xxx.actionform.Product_Form;
import com.xxx.db.ConnDB;
import org.apache.log4j.Logger;
public class SaveProduct_model extends ConnDB {
	private Product_Form form;

	Logger log = Logger.getLogger(SaveProduct_model.class);

	public SaveProduct_model(Product_Form form) throws Exception {
		super();
		this.form = form;
		log.info("数据检验开始");
		validate();
	}

	public void validate() throws Exception {
		if (form.getProductID().trim().equals(""))
			throw new Exception("产品ID不能为空!");
		if (form.getProductID().length() > 4)
			throw new Exception("产品ID最长为4位!");
		if (form.getProductName().trim().equals(""))
			throw new Exception("产品名称不能为空");
		if (Float.compare(form.getPrice(), 0) <= 0)
			throw new Exception("产品价格必须大于0");
	}

	public void save() throws Exception {
		try {
			log.info("进入保存");
			String productID = form.getProductID();
			String productName = form.getProductName();
			float price = form.getPrice();
			System.out.println(productID + " " + productName + " " + price);
			String sql = "INSERT INTO t_products VALUES('" + productID + "',"
					+ "'" + productName + "'," + String.valueOf(price) + ")";
			PreparedStatement pstmt = conn.prepareStatement(sql);
			log.info("执行保存中");
			pstmt.executeUpdate();
			pstmt.close();
			conn.close();
			log.info("关闭连接完成");
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}
	}
}

      在 Product类中使用了一个 ProductForm类,这个类是一个 ActionForm类,它的功能是保存客户端提交的数据。关于这个类将在下面详细介绍。

      Product类通过构造方法的 form参数将客户端提交的数据传入 Product类的对象实例中,并在构造方法中验证这些数据,如果发现数据不合法,就会抛出一个异常。当客户端提交的数据合法后,成功建立了一个 Product类的对象实例,然后可以通过简单地调用 save方法将数据保存到 t_products表中。    

      Product 类似,在 <samples 工程目录 >" src 目录中的com.xxx.model包里 建立一个 SearchProduct_model.java 文件,代码如下:

package com.xxx.model;

import java.sql.*;
import java.util.*;
import org.apache.log4j.Logger;
import com.xxx.actionform.Product_Form;
import com.xxx.db.ConnDB;
public class SearchProduct_model extends ConnDB {
	private Product_Form form;
	Logger log = Logger.getLogger(SearchProduct_model.class);
	
	public SearchProduct_model(Product_Form form) throws Exception {
		super();
		this.form = form;
	}
	public List<String[]> search() throws Exception {
		log.info("进入查询");
		List<String[]> result = new LinkedList<String[]>();
		String sql = "SELECT * FROM t_products WHERE product_name like '%"
				+ form.getProductName() + "%'";
		PreparedStatement pstmt = conn.prepareStatement(sql);
		log.info("执行查询");
		ResultSet rs = pstmt.executeQuery();
		while (rs.next()) {
			String[] row = new String[3];
			row[0] = rs.getString(1);
			row[1] = rs.getString(2);
			row[2] = rs.getString(3);
			result.add(row);
		}
		log.info("导出结果完成");
		rs.close();
		conn.close();
		log.info("关闭连接完成");
		return result;
	}
}

  SearchProduct_model类也使用了 Product_Form 类,但在 SearchProduct_model中并不会验证 Product_Form 对象实例中的数据,而只是 Product_Form 对象作为 传递查询请求信息 (实际上只需要产品名称)的工具而已。

六、实现控制器

   
在这一节要实现的控制器是基于 Struts Web 程序的核心部分之一:控制器实质上也是普通的 Java 类,但这个 Java 类一般要从 org.apache.struts.action.Action 类继承。

     控制器的主要功能是接受并处理从JSP页面提交的数据、通过模型(Model)和数据库交互以及forward到相应的页面(可以是任何页面,如 html、JSP和Servlet等)。在实现控制器之前,需要先实现一个ActionForm类, 这个类的作用是保存JSP页面提交的数据。

    在<samples工程目录>"src目录com.xxx.actionform中建立一个Product_Form.java文件,代码如下:

package com.xxx.actionform;

import org.apache.struts.action.ActionForm;

public class Product_Form extends ActionForm{
	private String productID;
	private String productName;
	private float price;
	public String getProductID() {
		return productID;
	}
	public void setProductID(String productID) {
		this.productID = productID;
	}
	public String getProductName() {
		return productName;
	}
	public void setProductName(String productName) {
		this.productName = productName;
	}
	public float getPrice() {
		return price;
	}
	public void setPrice(float price) {
		this.price = price;
	}
	
}

    从上面的代码可以看出, ActionForm类一般从 org.apache.struts.action.ActionForm 类继承,而且在类中需要按着需要保存的数据表字段添加属性。如产品ID的属性是productName。在MyEclipse中可以只定义三个private变量,然后使用MyEclipse的 Source > Generate Getters and Setters...】功能自动产生 getter setter方法。但在给这些属性取名时要注意, private变量的名子和数据表的字段名没有直接的关系,但必须和 JSP页面中的 <html>标签的 property属性值一致,如 <html:text property="productName" />表示输入产品名称的文本框,其中 property属性的值就是 ProductForm类中的 productName变量。如果不一致,将会抛出异常。其他和 ProductForm类的属性对应的 <html>标签可以查看上面的代码。
   
光有 ActionForm类还不够,还需要在 struts-config.xml中的 <struts-config>节点中添加如下的内容:

<form-beans>
     <form-bean name="saveProduct_Form" type=" mystruts.actionform.Product_Form" />
     <form-bean name="searchProduct_Form" type="mystruts.actionform.Product_Form" />
</form-beans>

 上面的代码所配置的两个 ActionForm 实际上指的是同一个 ProductForm 类,但这个 ProductForm 类在后面要讲的两个动作里都要使用,为了更容易理解,为这个 ProductForm 起了两个不同的别名( saveProductForm searchProductForm )。
   
下面来实现 saveProduct 动作的代码。 Struts Action 类必须一般从 org.apache.struts.action.Action 类继承。一般在 Struts Action 类需要覆盖 Action 类的 execute 方法。这个方法有每次客户端访问 Struts Action 时调用。我们可以在方法中处理客户端提交的数据,访问数据库等工作。这个方法返回一个 ActionForward 类型的值,表明在执行完 execute 后,要 forward 到的页面。描述 saveProduct 动作的类叫 SaveProduct_Action 。代码如下:

 package com.xxx.action;

import javax.servlet.http.*;

import org.apache.log4j.Logger;
import org.apache.struts.action.*;

import com.xxx.actionform.Product_Form;
import com.xxx.model.SaveProduct_model;

public class SaveProduct_Action extends Action {
	Logger log = Logger.getLogger(SaveProduct_Action.class);

	@Override
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		Product_Form saveProductForm = (Product_Form) form;
		try {
			log.info("进入保存控制器,传递数据中");
			SaveProduct_model product = new SaveProduct_model(saveProductForm);
			log.info("保存数据");
			product.save();
			log.info("保存完成");
			request.setAttribute("info", "保存成功!");
		} catch (Exception e) {
			request.setAttribute("info", e.getMessage());
		}
		log.info("跳转页面");
		return mapping.findForward("save");
	}

}

 
    SaveProductAction 类中使用了模型类 Product 验证并保存产品信息。并将操作结果信息保存在 request 的属性中, key 为“ info ”。在 execute 的最后,使用了 ActionMapping 类的 findForward 方法在 struts-config.xml 中寻找一个叫“ save ”的 forward 。这个 forward 是一个 JSP 页,用于显示是否将产品信息保存成功的信息。为了可以在 struts-config.xml 中查找这个 forward ,需要在 struts-config.xml <action-mappings> 节点中加入如下的内容。

<action name="saveProduct_Form" path="/saveProduct" scope="request" type="com.xxx.action.SaveProduct_Action">
  		<forward name="save" path="/mystruts/save.jsp"></forward>
  	</action>

   从上面的代码可以看出,那个用于显示保存状态信息的 JSP 页面叫 save.jsp 。在 <samples 工程目录 >"mystruts 目录中建立一个 save.jsp 文件,代码如下:

<%@ page pageEncoding="GBK"%>
  ${requestScope.info}

   IE中输入如下的 URL

    http://localhost:8080/samples/mystruts/newProduct.jsp

   
在文本框中输入相应的信息后,点“保存”按钮,如果输入的数据是合法的,就会将数据保存在 t_products中,否则会显示出错的原因。    searchProduct动作的实现和saveProduct差不多,也会为三步:实现动作类(SearchProductAction)、在 struts-config.xml中添加配置信息和实现用于显示查询结果的JSP文件。下面的代码分别显示了这三步所要编写的代码。

SearchProductAction.java

package com.xxx.action;
import java.util.List;
import javax.servlet.http.*;
import org.apache.log4j.Logger;
import org.apache.struts.action.*;
import com.xxx.actionform.Product_Form;
import com.xxx.model.SearchProduct_model;

public class SearchProduct_Action extends Action {
	Logger log = Logger.getLogger(SearchProduct_Action.class);
	@Override
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		Product_Form searchProductFrom = (Product_Form)form;
		try {
			log.info("进入查询控制器,传递数据中");
			SearchProduct_model searchProduct = new SearchProduct_model(searchProductFrom);
			log.info("执行查询数据");
			List<String[]> result = searchProduct.search();
			log.info("处理结果");
			if(result.size()>0)
			{
				request.setAttribute("result", result);
				request.setAttribute("info", "记录数"+String.valueOf(result.size()));
			}
			else
				request.setAttribute("info", "没有符合要求的纪录");
		} catch (Exception e) {
			request.setAttribute("info", e.getMessage());
		}
		log.info("跳转页面");
		return mapping.findForward("search");
	}
}

  struts-config.xml 中配置 searchProduct 动作

<action name="searchProduct_Form" path="/searchProduct" scope="request" type="com.xxx.action.SearchProduct_Action">
  		<forward name="search" path="/mystruts/search.jsp"></forward>
  	</action>

 

search.jsp

 <%@ page pageEncoding="GBK" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<body>
<c:set var="result" value="${requestScope.result }"/>
          <table width="100%">
              <tr align="center">
                  <td>
                      ${requestScope.info}
                  </td>
              </tr>
              <tr align="center">
                  <td>
                      <logic:present name="result">
                          <table border="1">
                              <tr align="center">
                                  <td> 产品ID </td>
                                  <td> 产品名称 </td>
                                  <td> 价格 </td>
                              </tr>
                              <logic:iterate id="row" name="result">
                                  <tr> <td> ${row[0]} </td>
                                      <td> ${row[1]} </td>
                                      <td> ${row[2]} </td>
                                  </tr>
                              </logic:iterate>
                          </table>
                      </logic:present>
                  </td>
              </tr>
          </table>

</body>
</html>

  IE中输入如下的 URL

    http://localhost:8080/samples/%20mystruts/searchProduct.jsp

   
在“产品名称”文本框中输入产品名称的一部分,程序就会查询出所有包含输入的产品名称的产品信息,并将结果显示出来。

 

 

七、解决 ActionForm 的乱码问题

  到现在为止,程序的功能部分已经全部实现完了。但还存在一个问题。当我们在产品名称中输入中文时,虽然将客户端提交的数据成功保存到数据库中,但是在 t_products表中的 product_name字段显示的都是乱码。产生这个问题的原因只有一个,就是客户端提交的数据的编码格式和数据库的编码格式不一致造成的。当然,解决这个问题的方法有很多,但笔者认为最容易的就是使用过滤器。所谓过滤器,就是在客户端提交数据后,在交由服务端处理之前所执行的一段服务端代码(一般为 Java代码)。一个过滤器是一个实现 javax.servlet.Filter接口的类。在本例中要使用的过滤器类叫 EncodingFilter,实现代码如下:

EncodingFilter.java

package com.xxx.db;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.log4j.Logger;
import org.omg.CORBA.Request;

import com.sun.net.httpserver.Filter.Chain;

public class EncodingFilter implements Filter {
	Logger log = Logger.getLogger(EncodingFilter.class);
	public void destroy() {
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
			log.info("转码设置");
			// 将客户端提交的数据设为GBK编码格式
			request.setCharacterEncoding("GBK");
			// 继续处理客户端提交的数据,如果不写这条语句,Servlet引擎将不会处理所过滤的页面
			chain.doFilter(request, response);
			log.info("转码完成");
	}

	public void init(FilterConfig arg0) throws ServletException {
	}

}

Filter接口的 doFilter方法是过滤器的核心方法。其中 FilterChain类的 doFilter方法允许继续处理客户端提交的数据。我们还可以使用这个方法来临时关闭 Web站点的某个或全部的页面(根据过滤器的设置而定)。由于本书的数据库使用的是 GBK编码格式,因此,需要使用 ServletRequest setCharacterEncoding方法将客户端提交的数据也设为 GBK编码格式。

    除了实现过滤器类,我们还需要在 web.xml中的 <web-app>节点加入如下的配置信息才能使过滤器生效:

web.xml 中配置过滤器

	<filter>
		<filter-name>EncodingFilter</filter-name>
		<filter-class>com.xxx.db.EncodingFilter</filter-class>
    </filter>
    <filter-mapping>
		<filter-name>EncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

 在重新启动 Tomcat 后,重新输入一条带中文的产品信息,看看是否可以将中文保存在数据库中?

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics