Struts学习(二)

Struts学习(二)

1.前言

今天写了一个简单的项目,就是用Struts框架进行表单的校验,防止表单的重复提交,外加用原来的过滤器技术处理全局乱码问题.深刻体会到了框架带来的便捷!

2.步骤

2.1 定义3个Enum枚举类

为了程序的可扩展性,定义3个Enum枚举类,Gender类表示用户性别,Preference表示用户偏好,City表示用户所在城市,这样在注册页面编码时就不用硬编码了,迭代枚举类添加相应的标签即可.枚举类(Preference)程序如下:

package cn.itcast.web.global;

public enum Preference {

	SING("sing","唱歌"),DANCE("dance","舞蹈"),FOOTBALL("football","足球"),BASKETBALL("basketball","篮球");
	private String name;
	private String value;
	private Preference(String name,String value){
		this.name = name;
		this.value = value;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	
	
	
	
}


2.2 编写JSP注册表单

JSP注册表单中使用了HTML标签库,这是Apache提供的Stuts标签库,其中的form标签会自动添加提交方式为post,而且当Session域中有随机数时,他会自动添加一个包含有随机数的hidden标签提交.在该表单中使用了枚举类的values()方法用于获得枚举类中的所有元素,在使用Jstl的foreach标签进行迭代,动态创建出所需的标签.JSP注册页面程序如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@page import="cn.itcast.web.global.Gender" %>
<%@page import="cn.itcast.web.global.City" %>
<%@page import="cn.itcast.web.global.Preference" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>注册</title>
  </head>
  
  <body style="text-align: center">
   	<html:form action="/Register">
   		<table border="1" width="60%">
   			<tr>
   				<td>用户名</td>
   				<td>
   					<html:text property="username" />
   				</td>
   				<td>
   					<html:errors property="username"/>
   				</td>
   			</tr>
   			
   			<tr>	
   				<td>密码</td>
   				<td>
   					<html:password property="password" redisplay="false"/>
   				</td>
   				<td>
   					<html:errors property="password"/>
   				</td>
   			</tr>
   			
   			
   			<tr>	
   				<td>确认密码</td>
   				<td>
   					<html:password property="password2" redisplay="false"/>
   				</td>
   				<td>
   					<html:errors property="password2"/>
   				</td>
   			</tr>
   			
   			<tr>
   				<td>性别</td>
   				<td>
   				<!--
   					<c:forEach var="g" items="<%=Gender.values() %>">
   						<input type="radio" name="gender" value="${g.name }"/>${g.value }
   					</c:forEach>
   				-->
   				<c:forEach var="g" items="<%=Gender.values() %>">
   					<html:radio property="gender" value="${g.name }">${g.value }</html:radio>
   				</c:forEach>
   				</td>
   				<td>
   					<html:errors property="gender"/>
   				</td>
   			</tr>
   			
   			<tr>
   				<td>生日</td>
   				<td>
   					<html:text property="birthday" />
   				</td>
   				<td>
   					<html:errors property="birthday"/>
   				</td>
   			</tr>
   			
   			
   			<tr>	
   				<td>城市</td>
   				<td>
   				<!-- 
   					<select name="city">
   						<c:forEach var="city" items="<%=City.values() %>">
   							<option value="${city.name }">${city.value }</option>   						
   						</c:forEach>
   					</select>
   				 -->
   					<html:select property="city">
   						<c:forEach var="city" items="<%=City.values() %>">
   							<html:option value="${city.name }">${city.value }</html:option>				
   						</c:forEach>
   					</html:select>
   				</td>
   				<td>
   					<html:errors property="city"/>
   				</td>
   			</tr>
   			
   			<tr>
   				<td>爱好</td>
   				<td>
   				<!-- 
   					<c:forEach var="pre" items="<%=Preference.values() %>">
   						<input type="checkbox" name="preference" value="${pre.name }"/>${pre.value }
   					</c:forEach>
   				 -->
   					<c:forEach var="pre" items="<%=Preference.values() %>">
   						<html:multibox property="preference" value="${pre.name }"/>${pre.value }
   					</c:forEach>
   				</td>
   				<td>
   					<html:errors property="preference"/>
   				</td>
   			</tr>
   			
   			<tr>
   				<td>
   					<input type="reset" value="重置"/>
   				</td>
   				
   				<td>
   					<input type="submit" value="注册"/>
   				</td>
   			</tr>
   		</table>
  </html:form>
  </body>
</html>


2.3 配置struts-config.xml 和 web.xml文件

struts-config.xml文件没有太大的变化,定义一个FormBean对象,一个用于转发的Action对象,一个用于处理表单的Action对象和一个资源文件对象.配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
        "http://struts.apache.org/dtds/struts-config_1_3.dtd">
        
        
<struts-config>
	<form-beans>
		<form-bean name="UserFormBean" type="cn.itcast.web.formBean.UserFormBean"></form-bean>
	</form-beans>

	<action-mappings>
		
		<action path="/Register" 
					 type="cn.itcast.web.action.Register" 
					 scope="request"
					 input="/WEB-INF/jsp/register.jsp"
					 name="UserFormBean"
					 validate="true"
					 >
			<forward name="success" path="/success.jsp"></forward>
			<forward name="message" path="/message.jsp"></forward>
		</action>
		
		<action path="/RegisterUI" type="cn.itcast.web.action.RegisterUIAction">
			<forward name="register" path="/WEB-INF/jsp/register.jsp"></forward>
		</action>
	</action-mappings>
	<!-- 配置文件,用ActionMessage可以用到里面的数据 -->
	<message-resources parameter="config"></message-resources>
</struts-config>


web.xml文件定义了一个全局乱码过滤器CharacterEncodingFilter,一个处理全局类型转换的监听器WebInitListener,和一个Apache提供的一个核心类ActionServlet.配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>struts13</display-name>
  
  <listener>
  	<listener-class>cn.itcast.web.listener.WebInitListener</listener-class>
  </listener>
  
  
  <filter>
  	<filter-name>CharacterEncodingFilter</filter-name>
  	<filter-class>cn.itcast.web.filter.CharacterEncodingFilter</filter-class>
  </filter>
  
  <filter-mapping>
  	<filter-name>CharacterEncodingFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
  
  
  <servlet>
  	<servlet-name>ActionServlet</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>
  	<load-on-startup>2</load-on-startup>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>ActionServlet</servlet-name>
  	<url-pattern>*.do</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>


2.4 监听器和过滤器

监听器WebInitListener用于处理类型转换问题,该监听器实现ServletContextListener接口.并在配置时用于处理全局,所以当服务器开启时,监听器就开始工作了,当有类型转化的时候,监听器就会工作.程序如下:

package cn.itcast.web.listener;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;

import cn.itcast.web.global.City;
import cn.itcast.web.global.Gender;
import cn.itcast.web.global.Preference;

public class WebInitListener implements ServletContextListener {

	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void contextInitialized(ServletContextEvent arg0) {
		ConvertUtils.register(new Converter(){
			@Override
			public Object convert(Class type, Object obj) {
				if(obj == null){
					return null;
				}
				if(obj instanceof String){
					String str = (String)obj;
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
					try {
						return sdf.parse(str);
					} catch (ParseException e) {
						e.printStackTrace();
						throw new RuntimeException("输入的格式不正确");
					}
				}else{
					throw new RuntimeException("输入的不是String类型");
				}
			}
		}, Date.class);

		
		
		ConvertUtils.register(new Converter(){
			public Object convert(Class type, Object obj) {
				if(obj == null){
					return null;
				}
				if(obj instanceof String){
					String str = (String)obj;
					return Gender.valueOf(str.toUpperCase());
				}
				return null;
			}
		}, Gender.class);

		ConvertUtils.register(new Converter(){
			public Object convert(Class type, Object obj) {
				if(obj == null){
					return null;
				}
				if(obj instanceof String){
					String str = (String)obj;
					return City.valueOf(str.toUpperCase());
				}
				return null;
			}
		}, City.class);


		ConvertUtils.register(new Converter(){
			public Object convert(Class type, Object obj) {
				if(obj == null){
					return null;
				}
				String[] params = (String[])obj;
				Preference[] pres = new Preference[params.length];
				int index = 0;
				for(String str : params){
					pres[index++] = Preference.valueOf(str.toUpperCase());
				}
				return pres;
			}
		}, Preference[].class);
	}

}


过滤器没什么好说的,实现Filter接口,在dofilter方法中处理乱码就可以了.程序如下:

package cn.itcast.web.filter;
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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class CharacterEncodingFilter implements Filter {

	@Override
	public void destroy() {

	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		response.setHeader("text/html", "charset=UTF-8");
		
		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {

	}

}

2.5 FormBean对象处理表单校验

在这里定义一个UserFormBean类处理表单校验,该类继承ActionForm类,在struts-config.xml中映射一个Action是将其validate属性设置为true是,就会执行FormBean中的validate方法.当返回值为null是,说明表单没问题,提交.当返回值为ActionErrors对象是,说明表单提交失败,并且该对象中封装了错误信息,当然了,这些数据是自己加进去的.程序如下:

package cn.itcast.web.formBean;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

import cn.itcast.web.global.City;
import cn.itcast.web.global.Gender;
import cn.itcast.web.global.Preference;

public class UserFormBean extends ActionForm{
	
	private String id;
	private String username;
	private String password;
	private String password2;
	private String gender;
	private String birthday;
	private String city;
	private String[] preference;
	
	@Override
	public ActionErrors validate(ActionMapping mapping,
			HttpServletRequest request) {
		ActionErrors errors = new ActionErrors();
		
		if(isEmpty(username)){
			errors.add("username",new ActionMessage("errors.username.isempty"));
		}else{
			if(!username.matches("\\w{3,9}")){
				errors.add("username",new ActionMessage("errors.username.notmatch"));
			}
		}
		
		if(isEmpty(password)){
			errors.add("password",new ActionMessage("errors.password.isempty"));
		}else{
			if(!password.matches("\\w{3,9}")){
				errors.add("password",new ActionMessage("errors.password.notmatch"));
			}
		}
		
		if(!isEmpty(password2) && !password2.equals(password)){
			errors.add("password2",new ActionMessage("errors.password2.notmatch"));
		}
		
		if(!isEmpty(birthday)){
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			try {
				sdf.parse(birthday);
			} catch (ParseException e) {
				errors.add("birthday",new ActionMessage("errors.birthday.notmatch"));
			}
		}
		
		
		if(isEmpty(gender)){
			errors.add("gender",new ActionMessage("errors.gender.isempty"));
		}else{
			try{
				Gender.valueOf(gender.toUpperCase());
			}catch(Exception e){
				errors.add("gender",new ActionMessage("errors.gender.notmatch"));
			}
		}
		
		if(isEmpty(city)){
			errors.add("city",new ActionMessage("errors.city.isempty"));
		}else{
			try{
				City.valueOf(city.toUpperCase());
			}catch(Exception e){
				errors.add("city",new ActionMessage("errors.city.notmatch"));
			}
		}
		
		if(preference != null && preference.length>0){
			try{
				for(String pre : preference){
					Preference.valueOf(pre.toUpperCase());
				}
			}catch(Exception e){
				errors.add("preference",new ActionMessage("errors.preference.notexist"));
			}
		}
		return errors;
	}
	
	public boolean isEmpty(String name){
		if(name == null || name.trim().equals("")){
			return true;
		}
		return false;
	}
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	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 String getPassword2() {
		return password2;
	}
	public void setPassword2(String password2) {
		this.password2 = password2;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public String getBirthday() {
		return birthday;
	}
	public void setBirthday(String birthday) {
		this.birthday = birthday;
	}
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	public String[] getPreference() {
		return preference;
	}
	public void setPreference(String[] preference) {
		this.preference = preference;
	}
}


3.总结

struts这种框架还是要实践啊!表单校验方面确实比以前简单,明天继续!大笑

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值