struts2初学小结

刚开始学习struts2的相关内容,小结一下。

首先说下环境的配置:

1.下载struts2.3.15.1,解压出apps/blank.war,这里面就是一个完整的实例,我们找到struts-2.3.15.1\apps\struts2-blank\WEB-INF\lib,把里面的jar文件都复制到你的web project工程的WebRoot\WEB-INF\lib里面,然后在struts2-blank\WEB-INF\classes里找到struts.xml,复制到src里就行了,这样基本的环境就配置好了。

看下我的:



    画了一个struts2的工作流程图:


以一个helloworld的例子来看。


struts2是一个控制流程的指挥者,Client 访问http://a.com/xxx/hello,Client的访问首先被tomcat接手,tomcat从URL中发现Client想访问xxx,那就找到xxx目录,定位到hello前看下xxx/WEB-INF/web.xml,在里面发现了过滤器,贴下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">

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

	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
	</filter>

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

</web-app>

既然有过滤器,而且过滤器<url-pattern>/*</url-pattern>,即所有访问都要先经过struts2这个过滤器,那就把Client的request交给struts2filter,它会在struts.xml里依次查找namespace、action,看下struts.xml代码:

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

<struts>
	<constant name="struts.devMode" value="true" /> <!-- 开发模式 这样的话每次修改都会在浏览器立刻体现,而不用重启服务器 -->
	<package name="default" namespace="/" extends="struts-default">

		<action name="*">
			<result name="success">
				/hello.jsp
            </result>
		</action>
	</package>

	<include file="example.xml" />

	<!-- Add packages here -->

</struts>

这里namespace为/,这个“/”对应xxx/目录,action name为* ,即所有访问都返回它对应result,一般写成
<result>
/hello.jsp
</result>

就可以使访问XXX/目录下所有的请求都返回hello.jsp,不过此时我写成

<result name="success">也可以,因为默认值就是success。

看下结果:


这是最简单的一个过程,中间没有经过action,正在学,学会了再加吧



-------------------------------------------------分割线----------------------------------------------

刚尝试写了一个简单的验证系统,login.jsp填写登陆表单,提交到userlogin这个action,struts.xml将这个请求提交给login.java这个action,并在提交的同时将username password 通过set方法传给action(甚至直接可以访问userlogin?username=123&password=123来传参),action判断用户名密码是否正确,然后将结果返回成一个string返回给xml,xml再根据配置返回对应的jsp。


(除此之外,还可以使用domain model传参,方法是这样:1建立一个user.java的model类,2.在action中不要写username password了,写一个User user = null;和他的setget方法,然后可以通过:userlogin?user.username=123&password=456传参 )

传参方面的知识介绍:

-----------------------细节分割线 开始-----------------------------

三种传参的方式:1.用action属性(get set) 2.用domain model 3.用model driver


传参包含中文的问题:要想传参包含的中文不成为乱码,应该这样:1.提交表单的JSP页面中设置提交方式为POST 2.在struts.xml里增加:

<constant name="struts.i18n.encoding" value="GBK"/>  这句话其实就是把action中的reuqest的字符集设置成了gbk      完毕。

-----------------------细节分割线 结束-----------------------------

login.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
    <title>Sign On</title>
</head>

<body>
<s:form action="userlogin">
    <s:textfield key="username"/>
    <s:password key="password" />
    <s:submit/>
</s:form>
</body>
</html>


struts.xml

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

<struts>

	<!--
		<constant name="struts.enable.DynamicMethodInvocation" value="false"
		/> <constant name="struts.devMode" value="true" /> <package
		name="default" namespace="/" extends="struts-default">

		<default-action-ref name="index" /> <global-results> <result
		name="error">/error.jsp</result> </global-results>

		<global-exception-mappings> <exception-mapping
		exception="java.lang.Exception" result="error"/>
		</global-exception-mappings> <action name="index"> <result
		type="redirectAction"> <param name="actionName">HelloWorld</param>
		<param name="namespace">/example</param> </result> </action>
		</package>
	-->
	<constant name="struts.devMode" value="true" /> <!-- 开发模式 这样的话每次修改都会在浏览器立刻体现 -->
	<package name="default" namespace="/" extends="struts-default">
		<default-action-ref name="index" />
		<action name="index">	<!-- 默认 -->
			<result>/hello.jsp</result>
		</action>
		
		<action name="userlogin" class="action.login">
			<result name="success">
				/loginsuccess.jsp
            </result>
			<result name="error">
				/error.jsp
            </result>
		</action>



	</package>

	<include file="example.xml" />

	<!-- Add packages here -->

</struts>

login.java

package action;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class login extends ActionSupport {
	private String username = null;
	private String password = null;
	String FORWARD = null;
	private HttpServletRequest request = ServletActionContext.getRequest(); // 获取request

	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 execute() throws Exception {
		request.setAttribute("username", username);
		if (username.equals("123")) {
			FORWARD = "success";
		} else {
			FORWARD = "error";
		}
		return FORWARD;
	}
}

loginsuccess.jsp

<%@ page language="java" import="java.util.*" pageEncoding="gbk"%>  
  <body>
    用户:<%=request.getAttribute("username") %>登陆成功. <br>
  </body>
</html>

------------------------------------------------继续深入学习--------------------------------------------------



0.struts.xml学习方法

(1)当我们不知道如何配置的时候可以打开struts-2.3.15.1\docs\WW\docs\home.html查询文档

(2)关于常量的默认配置我们可以打开struts2-core-2.3.15.1.jar\org.apache.struts2\default.properties这个文件,里面保存着xml里所有变量的默认属性 比如struts.i18n.encoding 我们可以修改哦

1.sturts.xml的package包配置

<package name="default" namespace="/" extends="struts-default">
		<default-action-ref name="index" />
		<action name="index">	<!-- 默认 -->
			<result>/hello.jsp</result>
		</action>

		<action name="userlogin" class="action.login">
			<result name="success">
				/loginsuccess.jsp
            </result>
			<result name="error">
				/error.jsp
            </result>
		</action>
	</package>

如上,package有三个属性,name:必须的,包的名字,随便写,默认是default, extends:可选属性,指定包的父包,默认是struts-default,继承了这个包才能用Struts2的核心功能哦,namespace:可选,命名空间,默认是/ ,若为/或空,当无法精确定位到别的namespace时,都将访问这里的action。如果为/123 那么在原来的目录后加/123/即可访问

struts.xml的一些常量

 <!-- 该属性指定需要Struts2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts2处理。
        如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。 -->
    <constant name="struts.action.extension" value="do" />
    <!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 -->
    <constant name="struts.serve.static.browserCache" value="false" />
    <!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 -->
    <constant name="struts.configuration.xml.reload" value="true" />
    <!-- 开发模式下使用,这样可以打印出更详细的错误信息 -->
    <constant name="struts.devMode" value="true" />
    <!-- 默认的视图主题 -->
    <constant name="struts.ui.theme" value="simple" />
    <!--<constant name="struts.objectFactory" value="spring" />-->
    <!--解决乱码    -->
    <constant name="struts.i18n.encoding" value="UTF-8" />
    <!-- 指定允许上传的文件最大字节数。默认值是2097152(2M) -->
    <constant name="struts.multipart.maxSize" value="10701096"/>
    <!-- 设置上传文件的临时文件夹,默认使用javax.servlet.context.tempdir -->
    <constant name="struts.multipart.saveDir " value="d:/tmp" />


2.Action类文件

struts2的action不需要继承任何类和接口,比如struts1借用ActionForm获取表单数据,但struts2可以利用setter getter获得。虽然不是必须要实现接口或继承父类,但一般需要继承ActionSupport类或实现Action接口,重写execute()方法,因为action被调用时默认会调用这个方法。

(1)method属性

<action name="userlogin" class="action.login" method="login">

这时struts不再调用默认的execute方法,而是调用指定的login方法。

<action name="user_*" class="action.login" method="{1}">

这个更好用,当请求user_为前缀的action时,都将访问这个action文件,然后将后面的通配符作为方法名去调用,比如请求user_login,则会调用login.java的login方法

(2)action内获取request session的方法 

private HttpServletRequest request;
	public String execute() throws Exception {
		request = ServletActionContext.getRequest();
		return "success";
	}


3.简单数据验证

流程:login.jsp提交一个含有username的表单给 userlogin.java这个action,action判断用户名不是123时返回一个错误,并跳转回login.jsp

贴代码

login.jsp

<%@ page contentType="text/html; charset=gbk"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
	<head>
		<title>Sign On</title>
	</head>

	<body>
		<s:form action="userlogin">
			<s:fielderror name="user"/><!-- 这个标签可以用来显示错误信息 -->
			
			用户名<input type="text" name="username"/>
			<s:fielderror name="pwd"/><!-- 这个标签可以用来显示错误信息 -->
			密码<input type="text" name="password"/>
			<input type="submit" value="提交"/>
		</s:form>
	</body>
</html>

struts.xml

		<action name="userlogin" class="action.userlogin">
			<result name="loginsuccess">
				/loginsuccess.jsp
            </result>
			<result name="input">
				/login.jsp
            </result>
		</action>

userlogin.java

package action;

import javax.servlet.http.HttpServletRequest;

import model.User;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class userlogin extends ActionSupport {
	String username = null;
	String password = null;
	String FORWARD = null;
	private HttpServletRequest request = ServletActionContext.getRequest(); // 获取request

	
	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 execute() throws Exception {
		
		if (getUsername().equals("123")) {
			FORWARD = "loginsuccess";
		} else {
			this.addFieldError("user", "username error!");	//添加错误信息,前台jsp可以用 <s:fielderror fieldName="user"></s:fielderror>接受并显示
			FORWARD = "input";
		}
		return FORWARD;
	}
}

3.2关于现实错误信息的细节:如果使用s:fielderror标签,jsp会为这个错误信息提供一个样式显示,如果jsp页面只想单纯的得到错误信息字符串的话,可以使用<s:property value="errors"/>,我们先在JSP页面中添加<s:debug></s:debug>,打开页面后会看到debug信息,在value stack中可以看到 error 对应的value即为错误信息"{user=[username error!], pwd=[pwd error!]} ",所以我们可以使用<s:property value="user"/>直接取到错误信息的值。另外,这个error是一个MAP,我们可以使用<s:property value="errors.user"/>直接显示[username error!],然后呢,这个信息是被方括号包含的 所以他是一个数组元素,那么我们如果写<s:property value="errors.user[0]"/>就会显示"username error!"


4.拦截器

这部分我是看http://www.blogjava.net/max/archive/2006/12/06/85925.html 学习的,详情看这里吧。

另外 可以通过  HttpServletRequest request = ServletActionContext.getRequest();获取request的参数


4.转换器

   当action的参数不是String 比如是Date的时候,我们无法直接给action提交参数(其实我觉得是可以给set方法写代码转换的),就可以使用转换器。

   转换器由转换类+properties文件构成,这里模拟一个转换Date的小程序:jsp提交date字符串给action包里的convertTest,DateConvert是转换类,xwork-conversion.properties是全局转换器的配置文件,里面的内容:需要转换的类途径=转换他的类途径,在这里就是:java.util.Date=action.DateConvert。


converttest.jsp

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>

<html>
	<body>
		<form action="convertTest" method="get">
			<input type="text" name="date">
			<input type="submit" value="submit date">
		</form>
	</body>
</html>

convertTest.java

package action;

import java.util.Date;

import com.opensymphony.xwork2.ActionSupport;

public class convertTest extends ActionSupport {
	Date date = null;

	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}
	
	public String execute() throws Exception {
		System.out.println(getDate());
		return "success";
	}
}

DateConvert.java

package action;

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

import ognl.DefaultTypeConverter;

public class DateConvert extends DefaultTypeConverter {
	public Object convertValue(Map context, Object value, Class toType) {
		System.out.println("转化器被执行");
		if (toType == Date.class) {
			String[] str = (String[]) value;
			Date date = new Date(str[0]);
			return date;
		} else if (toType == String.class) {
			Date date = (Date) value;
			return date.toString();
		}
		return null;
	}
}

xwork-conversion.properties 这个文件放到src目录下

xwork-conversion.properties


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值