Struts2 基础笔记

简介:

  

    最近学习了一下Struts2,我又是一个不愿意背的人,所以写点东西留下来,方便以后自己用到时回忆。


    因为我比较喜欢在代码中对程序进行注视,所以乍一看代码感觉会多。

    注视当中有容易出错的地方的提醒,也有函数解释,所以会显得很罗嗦。

    为了让例子以后也可以正常运行,所以没有做DB操作.好吧,我承认我是因为懒得意


    涉及到的内容有:

  1. 通过xml配置文件来实现
  2. 数据校验validation
  3. 注解方式的实现
  4. 响应流程


    失败的地方:

              jsp 传 list 类型的数据到 action 的方法没有实现。


需要的lib有:

struts2版本:struts-2.3.1.2



源代码:

  1. 在 web.xml 中添加如下代码。作用是当url地址改变时就扫描struts.xml。

	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
		<!-- 这里会调用默认地址:/WEB-INF/classes下的struts.xml -->
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>


       2.   在WEB-INF/classes/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>
	<!--
		1. package name: 名字可以随便起
		2. namespace: 可删除。在这里jsp的action为"/Login/*.action"。添加原因为区分action
			如果删除了的话,那么action为"*.action"即可
		3. extends: 继承的父package名称
		4. action name:acntio的名字(2.中写的jsp的action中的*部分)
		5. class:执行该action的class文件路径
		6. result name:action的class返回的结果。根据返回结果跳到不同页面
		
		更加相信内容请看:http://hi.baidu.com/ehols/blog/item/1f15aa444a8fa481b3b7dcec.html
	 -->
	<package name="ASD" namespace="/Login" extends="struts-default">
		<action name="login" class="com.action.LoginAction">
			<result name="success">/WEB-INF/main.jsp</result>
			<result name="fail">/fail.jsp</result>
			<!-- input为Struts2自带表单验证validate(本例子中为LoginAction-validation.xml)验证失败后返回值 -->
			<result name="input">/index.jsp</result>
		</action>
	</package>
</struts>


关于这个部分更详细的解释可以看:点击打开链接


       3.   index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>登陆界面</title>
<!-- 定义CSS,使错误信息以红色进行显示 -->
<style type="text/css">
.label {
	font-style: italic;
}

.errorLabel {
	font-style: italic;
	color: red;
}

.errorMessage {
	font-weight: bold;
	color: red;
}
</style>
</head>

<body>
请输入以下信息:
<br />
<!-- 在这里不要写成 <s:form action="/Login/login" >  这样写运行时将会报一大堆警告 -->
<s:form name="loginForm" action="login" namespace="/Login" method="post">
	<s:textfield name="id" label="用户名" />
	<s:password name="pwd" label="密码" />
	<s:submit value="登陆" />
	<s:reset name="重置"></s:reset>
</s:form>
</body>
</html>



       4.   在com.action.LoginAction中

package com.action;
  
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.entity.User;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;
  
public class LoginAction extends ActionSupport implements Preparable{
	private static final long serialVersionUID = 8740491047560899431L;
	
	private String id;  //对应页面中的s:textfield name
	private String pwd; //对应页面中的s:textfield name
	ArrayList<User> userList; //所有的用户信息
	
	//该Action的业务的执行函数
    public String execute() throws Exception
    {
    	HttpServletRequest request = ServletActionContext.getRequest();  
    	 
    	if(id.equals("mizhiwu") &&
    			pwd.equals("123")){
    		
    		String str = "2012-2-20";
    		request.setAttribute("date", str);
    		return "success";
    	}
    	else{
    		return "fail";
    	}
    }
    
    //自定义的特殊校验类在validate.xml中写不了的话就在这写,自动加载
    //validate.xml讲解请看下面    
    public void validate(){
    	if(!id.equals("mizhiwu")){
    		this.addFieldError("id","用户名请输入 mizhiwu");
    	}
    	if(!pwd.equals("123")){
    		this.addFieldError("pwd","密码请输入 123");
    	}
    }
    
    //在表单验证(validate)中需要用到get方法
	public String getId() {
		return id;
	}

	public String getPwd() {
		return pwd;
	}

	//jsp页面跳到这里后,set方法首先自动调用,加载jsp页面的值
    //即使标签为<input type="text" name="id" >标签的也可以通过这样获得
	public void setId(String id) {
		this.id = id;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	//可以使该Action跳转后的页面可以通过<s:iterator value="userList" var="var">直接获得
	public ArrayList<User> getUserList() {
		return userList;
	}

	public void setUserList(ArrayList<User> userList) {
		this.userList = userList;
	}

	//继承Preparable后必须实现的函数
	//prepare函数先于validate实现
	//实现理由是:保存原数据,有益于用户体验
	//不适用的后果:如果validation验证失败,那么返回登陆页面时,
	//      之前的用户名,密码等数据将全部丢失,用户必须重新填写
	//函数内要做的内容:首先get数据,并重新set一下。并把页面加载时都要做的事放在该函数中
	public void prepare() throws Exception {
		
		//该页面加载时总是要做的事--获得所有用户信息(模拟)
		ArrayList<User> userList = new ArrayList<User>();
		User user1 = new User("id1","123");
		User user2 = new User("id2","123");
		userList.add(user1);
		userList.add(user2);
		setUserList(userList);
		
		//get数据
		String tempId = getId();
		//set数据,以免validation返回时数据丢失
		setId(tempId);
	}
}

       5.   在com.action下,也就是与LoginAction同一个位置中,新建LoginAction-validation.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
	<!-- 详细部分请看:http://hi.baidu.com/cnkarl/blog/item/389d5a176c9e2412962b43a5.html -->
	<field name="id">
		<field-validator type="requiredstring">
			<param name="trim">true</param>
			<message>请填写用户名</message>
		</field-validator>

		<field-validator type="stringlength">
			<param name="minLength">4</param>
			<param name="maxLength">10</param>
			<message>用户名长度应在4到10个字符间</message>
		</field-validator>
	</field>

	<field name="pwd">
		<field-validator type="requiredstring">
			<message>请填写密码</message>
		</field-validator>

		<field-validator type="stringlength">
			<param name="minLength">2</param>
			<param name="maxLength">10</param>
			<message>为了您账号的安全,请设置2个字母以上的密码(最长可设置10个字母)</message>
		</field-validator>

	</field>
</validators>

这是Struts2自带的validation.起好名字后将会自动调用。

正确的位置是:需要验证的Action类同一个位置。

正确的名字是:Action名字-validation.xml。

更详细的看:点击打开链接


错误提示效果:




       6.   WEB-INF/main.jsp中


<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>主界面</title>
<style type="text/css">
.label {
	font-style: italic;
}

.errorLabel {
	font-style: italic;
	color: red;
}

.errorMessage {
	font-weight: bold;
	color: red;
}
</style>
</head>

<body>
<!-- 在跳到该页面前的action(LoginAction)中,有get,set方法,就可以以"${变量名}"形式获得 -->
Hello ${id}
<br>
<br>

输出所有用户(用 s:iterator):
<br>
<!-- 获得action传来的值并利用s:iterator来输出 -->
<s:iterator value="userList" var="var">
	<li>用户名:<s:property value="#var.id" /></li>
	<li>密码:<s:property value="#var.pwd" /></li>
	<br>
</s:iterator>


<s:form name="mainList" action="addOneUser" namespace="/AboutUser"
	method="post">
	<!-- 下面这样是错误的! -->
	<!-- <s:hidden name="hidUserList" value="%{userList}"></s:hidden> -->
	<!-- 通过hidden的传值  -->
	<s:hidden name="hidID" value="%{id}"></s:hidden>
	<s:textfield name="nowTime" label="当前时间" value="%{#request.date}" />
			当前登录用户:<input type="text" name="test1"
		value='<s:property value="id" />' />
	<s:submit value="添加用户" />
</s:form>
</body>
</html>


OK,如果只是想简单了解一下的话,那么到这里就可以了。你可以尝试着运行了。

到这里我们实现了最基础的部分(用户登陆以及显示主页面信息操作。其中包括传值,跳转),而且附带个页面验证功能。


到这部分,我们需要注意的一点就是validation验证失败后返回的部分。

也就是LoginAction-validation.xml验证失败后会返回登陆页面,但默认情况下,我们之前输入的用户名等数据将全部丢失。

换句话说用户一旦输入不符合规范,那么倒霉的用户就需要重新全部填写信息,重新登陆。

如果登陆不恐怖的话,想想如果这是一个申请页面,就因为身份证号少输入一位,你就要重新填写一大堆的数据,重新申请发火

为了避免这种情况,所以我们在LoginAction中实现Preparable接口的prepare函数,在该函数中把我们想要保存的值get,set一下。


也许是我刚学习的原因吧,感觉Struts2的validation很鸡肋。在这里只是学习一下。

实际应用中觉得还是使用ajax会更好更容易一些。ajax部分我会在Spring MVC 部分进行说明。


接下来我们通过annotation(注解)的方式来实现数据校验和Action管理。抛弃繁琐的xml设置。


       7.  在com.action.AddUserAction中

package com.action;

import java.util.ArrayList;

import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;

import com.entity.User;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;
import com.opensymphony.xwork2.validator.annotations.Validations;
import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator;
import com.opensymphony.xwork2.validator.annotations.ValidatorType;

//注解方式的数据校验
@Validations(requiredStrings ={
		@RequiredStringValidator(type = ValidatorType.FIELD,
				fieldName = "nowTime", message = "当前时间不能为空")})
//@InterceptorRefs({
//    @InterceptorRef("prepare"),
//    //@InterceptorRefs("defaultStack")
//})
@Namespace("/AboutUser")     //指定名称空间
public class AddUserAction extends ActionSupport implements Preparable{
	private static final long serialVersionUID = -3354842689160304136L;
	
	private String nowTime;
	private String hidID;
	ArrayList<User> userList; //所有的用户信息
	
	HttpServletRequest request = ServletActionContext.getRequest();  
	
	//注解方式的Action
	@Action(value = "/addOneUser", results = {
			@Result(name = "success", location = "/WEB-INF/addUser.jsp"),
			@Result(name = "fail", location = "../../fail.jsp"),
			@Result(name = "input",location = "../main.jsp")
			}
	)
	public String execute()
    {
		System.out.println("******************");
		System.out.println(hidID);
		System.out.println("******************");
	
    	return "success";
    }

	public String getHidID() {
		return hidID;
	}


	public void setHidID(String hidID) {
		this.hidID = hidID;
	}


	public String getNowTime() {
		return nowTime;
	}

	public void setNowTime(String nowTime) {
		this.nowTime = nowTime;
	}

	public ArrayList<User> getUserList() {
		return userList;
	}

	public void setUserList(ArrayList<User> userList) {
		this.userList = userList;
	}

	public void prepare() throws Exception {
		//无奈的办法。。。。。不然不填写当前日期的话,validation验证失败后,main.jsp页面将没有所有用户信息。
		ArrayList<User> userList = new ArrayList<User>();
		User user1 = new User("id1","123");
		User user2 = new User("id2","123");
		userList.add(user1);
		userList.add(user2);
		setUserList(userList);
	}
}

如果想验证一下这个注解方式的数据校验的话,只需要将当前时间框的数据去掉就可以了。


       8.  在WEB-INF/addUser.jsp中

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

<html>
<head>
	<title>这是注解方式实现的</title>
</head>

<body>
	这是注解方式实现的<br>
</body>
</html>


至此,所有代码全部完成。

在这里可以看出,如果我们通过注解的方式来编写代码的话,我们可以不用写struts.xml,不用写validation.xml。非常的方便。


快哭了美中不足的是我在这里没有实现当添加用户时校验失败,返回到main.jsp的话,我唯一的办法就是再一次的连接数据库(模拟),

然后取出所有用户信息,进行显示。否则main.jsp显示所有用户信息界面中,将没有任何数据。

正常的话应该是AddUserAction中的prepare()函数获得main.jsp页面中的userList后重新set一下。

可是我无法实现jsp传list属性值到action当中。

可怜如果有哪位能告诉我解决方法的话在下将感激不尽。


值得说明的是,在Struts2中页面间传值通常用<s:hidden>标签传递数据。


源程序的话大家可以到: 点击打开链接  下载。

导入该程序的用户需要重新导入servlet-api包(在Tomcat的安装路径下的lib文件夹下面有)。



呼~,下面说一下响应流程。与其说是响应流程,不如说是java怎么找到的正确代码执行方式。反正我也不知道叫什么才确切。


响应流程:

  1. 首先是Index.jsp页面。并当点击登录按钮时发送“/Login/login”地址。
  2. 这时首先启动的是web.xml
  3. web.xml通过<filter-name>struts2</filter-name> 找到了/WEB-INF/classes下的struts.xml
  4. struts.xml中在第17行中找到了"/Login",在第18行找到了"login",并且找到了处理该Action的class地址“com.action.LoginAction”。
  5. LoginAction.class中执行了prepare()函数和validation校验。如果没有问题执行了execute()函数,执行业务逻辑部分。
  6. 之后LoginAction.class返回结果(如"success")。
  7. 返回到struts.xml中,在19行找到了对应的返回结果对应的页面(/WEB-INF/main.jsp).
  8. 显示/WEB-INF/main.jsp页面。


大功告成~~~~



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值