读书人

struts1的通体复习讲解

发布时间: 2012-09-04 14:19:30 作者: rapoo

struts1的整体复习讲解

Struts1的终极复习

1、 为什么要用strusts框架、struts.apache.org官方网站

struts1的通体复习讲解

2、 搭建环境

struts1的通体复习讲解

3、 actionForm的建立

struts1的通体复习讲解

4、 action的开发

struts1的通体复习讲解

5、struts首先是在导包,然后在web中配置actionServlet,最后书写struts-config文件

<1>这是开发struts的struts-config配置文件的书写

<struts-config>

<data-sources/>

<form-beans>

<form-beanname="loginForm"type="com.forms.PersonForm"></form-bean><!—-name表示formbean取得名字,type表示form的那个类 -->

</form-beans>

<global-exceptions/>

<global-forwards/>

<action-mappings>

<actionpath="/test"type="com.action.PersonAction"name="loginForm"><!—path表示来访问的路径,type表示action的那个类,name表示上面那个formbean的名字 -->

<forward name="loginSuccessful"path="/loginSuccessful.jsp"></forward><!—-name表示名字,path表示jsp页面的路径 -->

<forward name="loginFailed"path="/loginFailed.jsp"></forward>

</action>

</action-mappings>

<message-resourcesparameter="com.yourcompany.struts.ApplicationResources"/>

</struts-config>

<2>这是actionServlet的配置(在web.xml里面)

<servlet>

<servlet-name>caohuan</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>//这是struts配置文件的路径

</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>caohuan</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

Struts开发的一个流程图

struts1的通体复习讲解

关于页面的填充的数据不正确,但是也不会报错,这是因为,actionServlet的beanUtil对数据进行了处理(一般要对数据进行js(前天的验证)的验证,也可以在form中进行验证(后台的验证))不合法:加入写日期:1990-09-321也可以。

struts1的通体复习讲解

6、 struts中的各个组件

struts1的通体复习讲解

<1>actionServlet的讲解

struts1的通体复习讲解

注意:在web.xml中配置这个actionServlet的时候一定得配置

<init-param>

<param-name>config</param-name>

<param-value>/WEB-INF/struts-config.xml</param-value>

</init-param>

<2>action的讲解

注意:action必须要有一个无参数的构造函数

Action初始化是第一次发送请求的时候。

每个action只会初始化一次。(相当于每个人去访问,都是同一个action)

优点:资源可以重用。

缺点:可能会存在不安全问题。Action是线程不安全的,因为所有的请求共享同一个实例。

怎样实现安全性编程?

1、 不要用实例变量或者静态变量共享只是针对某一个请求的数据。

2、 注意资源操作的同步性。

解决办法:

Private Integer count = 0;

synchronized (count) {

count ++;

}

struts1的通体复习讲解

<3>actionMapping的讲解

struts1的通体复习讲解

其实actionMapping就相当于是一个action,action有很多属性,在action类中可以设置、修改这些属性

System.out.println(mapping.getName());

System.out.println(mapping.getPath());

System.out.println(mapping.getType());

System.out.println(mapping.getParameter());

String [] forwardNames = mapping.findForwards();

for (String name : forwardNames) {

ActionForward actionForward = mapping.findForward(name);

System.out.println(actionForward.getName());

System.out.println(actionForward.getPath());

}

<4>actionForward的讲解

<forward name="loginSuccessful"path="/loginSuccessful.jsp"></forward>

Path的属相在这种情况下,是相对于相对路径,所以需要有‘/’开头

<forward name="loginSuccessful" redirect="true" path="/loginSuccessful.jsp"></forward>

Redirect:如果为true,那么就为重定向,相当于,respose.sendRedirect();

Path的属相在这种情况下,是相对于绝对路径,所以不要以‘/’开头

Redirect:如果为false,那么就为转发,相当于,request.getRequestDispatcher().forward();

Path的属相在这种情况下,是相对于相对路径,所以需要有‘/’开头

<5>actionForm的讲解

Form的查找过程。

struts1的通体复习讲解

struts1的通体复习讲解

ActionForm的流程图

struts1的通体复习讲解

struts1的通体复习讲解

struts1的通体复习讲解

首先根据Action的name查找form,再根据作用范围查找,如果有就直接使用,如果不存在就创建一个。根据name和scope去查找。如果找不到,就构造一个,首先调用的是form的构造方法,然后在调用复位(reset)方法,然后在取页面的值填充form的属性(即调用setter方法),然后在进行验证(这是在action的属性validate=true的情况下。),然后在进入到action中。千万注意:formBean必须要有一个无参的构造函数。

<action path="/test" type="com.action.PersonAction"name="loginForm"scope="request">//根据作用于查找formBean,缺省值就是session。

要判断一个form是否真正建立,是否保存在request,session中,可以建立一个监听器进行监听。

这是从过程来监听的。

package com.lisenter;

import javax.servlet.ServletRequestAttributeEvent;

import javax.servlet.ServletRequestAttributeListener;

import javax.servlet.http.HttpSessionAttributeListener;

import javax.servlet.http.HttpSessionBindingEvent;

import com.forms.PersonForm;

publicclass PersonLisenter implements HttpSessionAttributeListener, ServletRequestAttributeListener {

publicvoid attributeAdded(HttpSessionBindingEvent event) {

String name = event.getName();

if(event.getValue()instanceof PersonForm)

{

System.out.println("这是session监听");

System.out.println(event.getValue());

}

}

publicvoid attributeRemoved(HttpSessionBindingEvent event) {

//TODO Auto-generated method stub

}

publicvoid attributeReplaced(HttpSessionBindingEvent event) {

System.out.println("这是session监听replace");

}

publicvoid attributeAdded(ServletRequestAttributeEvent event) {

if(event.getValue()instanceof PersonForm)

{

System.out.println("这是request监听");

System.out.println(event.getValue());

}

}

publicvoid attributeRemoved(ServletRequestAttributeEvent event) {

}

publicvoid attributeReplaced(ServletRequestAttributeEvent event) {

System.out.println("这是request监听replace");

}

}

还可以从过程来判断。

PersonForm personForm = null;

if(mapping.getScope().equals("request"))

{

personForm = (PersonForm) request.getAttribute("loginForm");

}

if(mapping.getScope().equals("session"))

{

personForm = (PersonForm) request.getSession().getAttribute("loginForm");

}

if(personForm == form)

{

System.out.println("personForm == form");//说明它们指向的是同一个地址

}

//参数form和控制器放进去的那个form是同一个对象

从页面传过来的值填充form主要看是否有对应的标准set方法,而不是看是否有这个属性名字。

reset()方法(复位)用于将form的各个属性恢复到默认的状态。最常用的是:当页面的有一个复选框的时候,需要初始的时候就有选择的想,就可以用reset()进行设置。

validate的解释

如果设置action中的属性validate = true而校验方法什么都没干,那么就返回空。

如果设置validate = false那么就不会调用validate这个方法。

public ActionErrors validate(ActionMapping mapping,

HttpServletRequest request) {

System.out.println("这是验证方法");

returnnull;

}

Attribute:是form的关键字,如果你设置了它。那么你要得到该form的时候,那么应该使用attribute的属性值,而不是name的值了,默认情况下它的值就是name的值。

<action path="/test" type="com.action.PersonAction"name="loginForm"scope="request"validate="true"attribute="loginFormBean">

input:如果validate设置为真,而且验证的时候出现错误,那么就会转向input指向的那个页面,一般而言,input属相指向的相对路径,一般以‘/’开头。

<action path="/test" type="com.action.PersonAction" name="loginForm" scope="request" validate="true" input="/error.jsp">

全局跳转:表示任何一个action都可以调用

<global-forwards>

<forwardname="error"path="/error.jsp"></forward>

</global-forwards>

在action调用:return mapping.findForward("error");

资源文件

struts1的通体复习讲解

7、 标签的讲解

struts1的通体复习讲解

从一个叫person的bean(保存在scope的作用域)中查找一个叫name的属性保存到person1(保存到toScope的作用域中)中。

Name:要查找的bean。

Id:给bean一个唯一的命名。

Property:从bean中查找某一个属性。

Scope:到哪个作用域中去查找。

ToScope:将这个bean保存到哪个作用域去。

<Bean:define>的用法

<bean:defineid="person1"name="person"property="name" scope="request"toScope="session"></bean:define>

<Bean:write >的用法

<bean:write name="person1" scope="request"/>

${ sessionScope.person1}

<bean:message>的用法

struts1的通体复习讲解

首先应该src目录下写资源文件,然后在配置文件中注册

注册:<message-resourceskey="myKey"parameter="com.yourcompany.struts.ApplicationResources"/>

Key是一个关键字,为每一个设置一个唯一值,parameter是资源文件的基文件。然后在资源文件中写一些键值对。

<bean:message bundle="myKey" key="username"/>

Bundle是制定去哪个资源文件(就是资源文件里面的key),key是资源文件里写的键值对的键,输出的是键对应的值。

8、 逻辑标签

struts1的通体复习讲解

<logic:iterateid="p"name="list"scope="request"indexId="i"offset="0"length="2">

${i}<bean:write name="p" property="i"/>用红色的部分不能输出,会报错

<bean:write name="p"property="name"/><br/>

</logic:iterate>

Id:唯一标示符

Name:保存在作用域中的bean property: bean中的某一个属性 scope:从作用域中去取 offset从哪个开始输出 length:输出的长度 indexed:把每一个的下标保存在它中,千万记得用<bean:write name="p" property="i"/>不能输出来,需要用${i}才能输出来。记住:该标签必须要有集合出现,才能用它输出,否则会出现异常。

双重的使用

<logic:iterateid="p"name="list3"scope="request">

<logic:iterate id="go"name="p">

${go.id}<bean:writename="go"property="name"/>

</logic:iterate><br/>

</logic:iterate>

注意:有时候不能用<bean:write name="go" property="name"/>输出,就用${go.id}

具体原因不是很清楚。

<html:checkbox>

篮球:<html:checkbox name="loginFormBean" property="hobby" value="hobby[0]"></html:checkbox>

这是从一个叫loginFormBean的formBean中取它的一个叫hobby的属性付给property,

然后去hobby对应的值给value.

9、 动态form

form-bean:name表示给这个form取一个名字,type表示动态form这个类。

form-property:name表示给这个form添加一个属性名字,type表示该属性的类型,千万记得得写上包名、类名。

<form-beanname="loginForm"type="org.apache.struts.action.DynaActionForm">

<form-property name="userName"type="java.lang.String"></form-property>

<form-property name="password"type="java.lang.String"></form-property>

<form-property name="date"type="java.sql.Date"></form-property>

<form-property name="hobby"type="java.lang.String[]"></form-property>//类型是字符窜数组

</form-bean>

在action的测试:

DynaActionForm dynaActionForm = (DynaActionForm) form;

String userName = (String) dynaActionForm.get("userName");

String [] hobby = dynaActionForm.getStrings("hobby");

//得到数组的第几个元素,有时候可能得不到,是因为要在jsp页面的控件名字上取名字hobby[0]、hobby[1]-->不过我测试的时候没有出现这种情况,我页面用的是struts的标签,不是用的html的表单标签。

struts1的通体复习讲解

String hobby = (String) dynaActionForm.get("hobby", 0);

System.out.println(userName);

for (Stringstring : hobby) {

System.out.println(string);

}

//用EL表达式取值

${loginFormBean.userName}//这是不是动态form时到formBean里取值的方法

${loginFormBean.map.userName}//这是动态form时到formBean里取值的方法

${loginFormBean.map.hobby[0]}//这种是输出数组的第一个值

动态form的map的用法

得到的是form中的(属性 =值)这样的键值对保存在map中。

Map<Object, Object> map = dynaActionForm.getMap();

Set<Object> sets = map.keySet();

for (Object object : sets) {

System.out.println(map.get(object));

}

10.异常

struts1的通体复习讲解

异常机制

struts1的通体复习讲解

struts1的通体复习讲解

<exception key="error"path="/error.jsp"type="com.exception.PersonException"></exception>

Key是资源文件中的key,根据key可以得到值,path是要转向的错误页面,type是处理异常的类。在错误页面用<html:errors/>打印出错误

插件Plugin

struts1的通体复习讲解

<plug-inclassName="com.plugin.PersonPlugin">

<set-propertyvalue="classpath:hibernate.cfg.xml"property="hibernateConfigFileasd"/>

</plug-in>

className:是插件类 property:是插件类中的一个属性 value:是属性的值。

Struts插件读取hibernate的配置文件

package com.plugin;

import hibernateUtil.HibernateSessionFactory;

import javax.servlet.ServletException;

import org.apache.struts.action.ActionServlet;

import org.apache.struts.action.PlugIn;

import org.apache.struts.config.ModuleConfig;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

public class PersonPlugin implements PlugIn {

private String hibernateConfigFileasd;

public void destroy() {

System.out.println("这是关闭session");

HibernateSessionFactory.closeSession();

}

public void init(ActionServlet arg0, ModuleConfig arg1)

throws ServletException {

System.out.println("这是打开session");

Session session = HibernateSessionFactory.getSession();

}

public String getHibernateConfigFileasd() {

return hibernateConfigFileasd;

}

public void setHibernateConfigFileasd(String hibernateConfigFileasd) {

this.hibernateConfigFileasd = hibernateConfigFileasd;

}

}

ForwardAction的讲解

struts1的通体复习讲解

<actionpath="/go"type="org.apache.struts.actions.ForwardAction" parameter="/regist2.jsp"></action>

<actionpath="/go"include="/index.jsp"></action>

与上面那写的功能差不多。在使用功能与案例中有讲解。

Formbean和国际化

Session的序列化问题:举一个例子:假如你想在你的tomcat关闭后把你的类的内容写入你的电脑,那么你的这个类必须实现Serializable这个接口。因为java编译器会用序列化流进行一些处理。

假如几个人做项目,有几台服务器(服务器集群),有一个人买了一个水杯(在某一个服务器上),然后买了另外一件东西(在另外一个服务器上),如果你想看到你之前买的那个东西,那么你需要把之前的那件东西写入服务器的session之中,那么这个类对象就必须实现Serializable这个借口。

解释Serializable这个问题

struts1的通体复习讲解

关于form中的validate的一些讲解

struts1的通体复习讲解

FormBean是保存在request或session中,而validate的errors是保存在request中,request.setAttribute(“Globals.ERROR_KEY”, errors);这个保存的过程被struts进行的封装。

public ActionErrors validate(ActionMapping mapping,

HttpServletRequest request) {

ActionErrors actionErrors =new ActionErrors();

if(login.getUserName() ==null ||"".equals(login.getUserName().trim()))

{

actionErrors.add("error",new ActionMessage("用户名为空",false));//new ActionMessage("用户名为空",false)中的false不需要你管

}

return actionErrors;

}

登录的一个例子(包括出错后有提示值,有出错的显示):

以下的红色部分,表示如果出现错误,返回该页面,那么原来填写的值依然存在。

除了页面要做的处理外,还需要在formBean中重写validate方法,还需要在资源文件中写上相应的userNameError、passwordError的键值对。

<formaction="test.do?p=login"method="post">

<br>userName:<input type="text"name="login.userName"value="${loginFormBean.login.userName }">//处理出错后回到页面仍然有提示值的问题

<html:errors property="userNameError"/>//处理出错的提示

<!-- 这里的property里的名字不是资源文件里的那个文件,而是对应的给actionError的那个名字 -->

<br><!--这是页面与login的userName对应 -->

password: <input type="password"name="login.password"value="${loginFormBean.login.password }">//处理出错后回到页面仍然有提示值的

<html:errors property="passwordError"/>//处理出错的提示

<!-- 这里的property里的名字不是资源文件里的那个文件,而是对应的给actionError的那个名字 -->

<br><!--这是页面与login的password对应 -->

password2: <input type="password"name="password2"value="${loginFormBean.password2 }"><br>//处理出错后回到页面仍然有提示值的

<input type="submit"value="提交"><inputtype="reset"value="重置">

</form> ${requestScope['org.apache.struts.action.ERROR'] }//这句代码能够写出保存的错误信息,不过一般不这样写,而是用struts的标签。

Globals.ERROR_KEY就是org.apache.struts.action.ERROR类的一种常量代表。

FormBean的validate方法

public ActionErrors validate(ActionMapping mapping,

HttpServletRequest request) {

ActionErrors actionErrors = new ActionErrors();

if(login.getUserName() ==null ||"".equals(login.getUserName().trim()))

{

//actionErrors.add("userNameError", new ActionMessage("用户名为空",false));//new ActionMessage("用户名为空",false)中的false不需要你管

//这个false表示在页面读取错误信息的时候,不是从资源问价里面读的,而是从这里直接读取。

//如果想要从资源文件里里面读取,userNameError是资源文件里面的一个键

actionErrors.add("userName",new ActionMessage("userNameError"));//new ActionMessage("用户名为空",false)中的false不需要你管

}

if(login.getPassword() !="caohuan")

{

//actionErrors.add("password", new ActionMessage("密码出错",false));//new ActionMessage("用户名为空",false)中的false不需要你管

actionErrors.add("password",new ActionMessage("passwordError"));//new ActionMessage("用户名为空",false)中的false不需要你管

}

returnactionErrors;

}

//如果找不到相应的国际化语言的文件,首先不会默认就去找默认文件,而是找与操作系统语言类似的语言,然后再找默认的国际化文件。

资源文件:关于中国资源文件的一个常错点。

struts1的通体复习讲解

在src下的文件,如果是.Java编译器就会翻译成classes下的.class文件,如果是其他的文件,就会原封不动的直接放到classes下。不会翻译。

<bean:message>标签的国际化

<bean:messagekey='info.submit'/>//这里的可以就是资源文件的键值对的某个键

<html:linkaction="#"titleKey="info.submit">等等</html:link>

//这里的titleKey就是资源文件里的键值对的键,还有一个title标签,但是那不能实现国际化。

<html:submitvalue="<bean:messagekey='info.submit'/>"></html:submit>

<!-- 千万记得在struts的标签里不能再嵌套标签,否则达不到你所想的效果 -->

<!-- 解决方法 -->

<html:submit><bean:messagekey='info.submit'/></html:submit>

<message-resources

Key = “” parameter="com.yourcompany.struts.ApplicationResources" />

Key是资源文件的不同的一个标示符。千万记得写资源文件的时候只写资源文件的基名。

不同的基名,那么在页面用struts标签进行取值时,那么一定得写上bundle来得到这个资源文件。

例如: <html:linkaction="#"bundle="xxx"titleKey="info.submit">等等</html:link>

//浏览器用哪种语言,首先是从session(第一次访问的时候的那种语言存储在session中)中去查找这种语言来解析浏览器,如果没有就按照浏览器—>工具栏—->中的语言项的那种语言来解析浏览器。

实现国际化的语言转换。

String language = request.getParameter("language");

HttpSession session = request.getSession();

Locale local = getLocale(request);

local = new Locale(language);

session.setAttribute(Globals.LOCALE_KEY,local);

returnnew ActionForward("/login.jsp");

前台的页面:

<a href="test.do?p=login&language=zh_CN">中文</a>

<a href="test.do?p=login&language=en_US">英文</a>

<html:errors>的讲解

struts1的通体复习讲解

ActionMessage messages = new ActionMessage("userNameError");

ActionMessage messages1 = new ActionMessage("userNameError",false);

actionErrors.add("userName",messages);

actionErrors.add("userName",messages1);

errors中的每个key可以对应几个消息。

业务逻辑验证

ActionErrors(已淘汰) ActionMessages

为什么要淘汰,淘汰了,为什么actionForm中还在使用

struts1的通体复习讲解

//业务逻辑的验证

PersonForm personForm = (PersonForm)form;

// ActionMessages是ActionErrors的父类

ActionMessages errors = new ActionMessages();

//ActionErrors errors =new ActionErrors();//这种方法已淘汰

if(personForm.getPerson().getUserName().equals("caohuan"))

{

ActionMessage actionMessage =new ActionMessage("userNameRepeate");

errors.add("userNameCH", actionMessage);

//第一种方法

// request.setAttribute(Globals.ERROR_KEY, errors);

// return mapping.findForward("go");

//第二种方法

this.saveErrors(request, errors);

//return new ActionForward(mapping.getInput());或

return mapping.getInputForward();

}

//实现资源文件中出现参数,并且可以实现国际化的

ActionMessage actionMessage =newActionMessage("userNameRepeate",this.getResources(request).getMessage(this.getLocale(request),"go"));

第一个参数是资源文件的错误提示的参数, 第二个参数是使用哪种语言的国际化。里面的go参数是用该参数来查找参数值。(视频33)

关于form的两种形式及区别

<formaction="${pageContext.request.contextPath}/test.do?p=login"method="post">

用户名:<inputtype="text"name="person.userName"value="${personForm.person.userName }">

<html:errorsproperty="userNameCH"footer=""header=""/>

<html:errorsproperty="userName"/>

密码:<inputtype="text"name="person.password"value="${personForm.person.password }">

<html:errorsproperty="asd"/>

验证密码:<inputtype="text"name="password2"value="${personForm.password2 }">

<inputtype="submit"value="提交"><inputtype="reset"value="重置">

</form>

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

<!--form中的action是提交按钮,/test?p=login、/test.do?p=login、test?p=login三种写法都可以,因为struts会自动加上前面的'/'和末尾的'.do' -->

<html:formaction="/test?p=login" focus=” person.userName”><!—-一进入这个界面焦点就会在person.userName文本框上-->

用户名:<html:textproperty="person.userName"></html:text><!--不需要加上value,因为struts标签会自动加上 -->

密码:<html:password property="person.password"/>

<html:submittitleKey=""value="提交"></html:submit>

</html:form>

<html:checkboxproperty="autoLogon"></html:checkbox><!--一旦它被选中一次后,那么就会保存它的checked为true在session中,如果你以后不选择它,就会传一个null过去,当以后你再回到这个界面时,它还是会选中。也就是只要选中一次后,以后不管你选不选,它都会自动选中 -->

<!-- 要解决这样的问题,就需要在formBean中调用reset方法,设置autoLogon =false-->

<!—<html:form>的讲解 -->

struts1的通体复习讲解

当你第一次访问这个jsp页面的时候,formBean并不会被actionServlet创建,那么这时候谁会创建这个formBean呢?这个formBean会被struts的<html: form>创建

struts1的通体复习讲解

文件上传的讲解

<html:formaction="/test?p=upload"method="post"enctype="multipart/form-data">//千万记得要用这种方式提交,否则会出错。在formBean中有一个formFile对应,把上传的文件放入它中。

上传文件:<html:fileonfocus="go(this)"property="formFile"></html:file>

<html:submitvalue="提交"></html:submit>

</html:form>

关于当文件上传的内容大于制定的大小的时候(struts的配置默认的文件内容的大小为250M)

struts1的通体复习讲解

解释:

首先从页面传进来的一个表单(也就是传进来一个原始的request),原始的request进入到actionServlet(第一个action),然后第一个action对这个原始的request进行包装(第二个图解释了如何包装request),包装过后再交给第2个action,当第二个action返回actionForward的时候,就会处理进过包装的request,返回给页面原始的request.,但是如果第二个action返回的不是actionForward,而是由于出错返回的input指向的页面,那么这时候返回的还是包装的request,不会进行处理。

进行request包装的详细解释----à重点

首先第一个action会对文件上传的大小进行判断,如果超过指定的大小,就不会将参数保存到map中,那么当进入到formBean的时候,那些参数就不会填充值,这时候验证的时候最容易出现空指针异常。

Struts的核心基础

1、当web.xml配置文件中拦截的是*.html的时候,那么struts-config配置文件的action的path=‘/test’text后面的.html struts会自动加上。

2、Struts的配置文件里面的action过多的处理方法。

<1>可以在读取配置文件的时候读取多个

<init-param>

<param-name>config</param-name>

<param-value>/WEB-INF/struts-configTest.xml</param-value>

<param-value>/WEB-INF/struts-configGo.xml</param-value>

</init-param>

但是千万记得不能<param-value>/WEB-INF/struts-config*.xml</param-value>以为加个*就是读取所有的struts的配置文件,不出错的。

<2>

具体的例子,看struts的核心基础的怎么处理action配置文件过多的问题。

Path中的*表示拦截任何以test开头的访问形式,但是千万记得,当页面访问的时候,*部分的内容就是填充那个{1}的内容,也就是进入到相应的action。

如:

<ahref="${pageContext.request.contextPath}/testGo0.do?p=go">去go界面</a>

其实这里的Go0就是去填充{1}的

<ahref="${pageContext.request.contextPath}/testGo1.do?p=go">点go1界面</a>

其实这里的Go1就是去填充{1}的

<actionpath="/test*"name="testForm"validate="true"type="com.actions.Test{1}Action"input=""parameter="p">

<forward name="go"path="/go.jsp"></forward>

<forward name="go1"path="/go1.jsp"></forward>

</action>

加强版

<ahref="${pageContext.request.contextPath}/testGoGo0.do?p=go">去go界面</a>

<ahref="${pageContext.request.contextPath}/testGoGo1.do?p=go">点go1界面</a>

<actionpath="/testG*G*"name="testForm"validate="true"type="com.actions.TestG{1}G{2}Action"input=""parameter="p">

<forward name="go"path="/go.jsp"></forward>

<forward name="go1"path="/go1.jsp"></forward>

</action>

所有的请求首先要经过ActionServlet处理,其实真正处理的不是它自己本身,而是RequestProcessor这个实体类。

//面试题

3、写工程名的时候得用${pageContext.request.contextPath}注意,这样的还是一般般啦,当你这样写的时候,在web.xml的头文件中如果配置的是2.2那么最好改成2.5

因为如果是2.2,最还在每个页面写上

2.5的文件头

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

//是EL表达式的功能失去

<%@page isELIgnored="true"language="java"import="java.util.*"pageEncoding="utf-8"%>

<ahref="${pageContext.request.contextPath}/testGoGo1.do?p=go">点go1界面</a>一般般 要是后面我不用struts1了,那就不是拦截以.do结尾的,而是拦截以.htm结尾的,j就得改源代码

<ahref="/CoreBasic/testGoGo1.do?p=go">点go1界面</a>很差 要是别人的工程名改了,那不亏大了

<html:linkaction="/testGoGo1"></html:link>很好 可以自动拦截以任何东西结尾的,action就是在struts中的配置文件中action中的path的路劲

<html:link>的好处

第二点好处的讲解<这是视频12讲的>

浏览器第一次访问后台的时候,该标签里面没有cookie,因为cookie是服务器传过来给浏览器的,但是当浏览器去访问的时候,服务器就会把一个cookie传递给浏览器。第二次访问的时候如果浏览器支持cookie,那么服务器就不会再传cookie到这个标签里面,如果浏览器不支持cookie,那么第二次访问后,服务器又会把cookie传过来。

啥叫url编码:

<%

request.setAttribute("name","曹欢操");

Date date = new Date();

request.setAttribute("date", date);

Person person1 =new Person();

person1.setId(1);

person1.setName("a");

Person person2 =new Person();

person2.setId(1);

person2.setName("a");

Person person3 =new Person();

person3.setId(1);

person3.setName("a");

Go go = new Go();

Map map = go.getMap();

map.put("x",person1);

map.put("y",person2);

map.put("z",person3);

request.setAttribute("go", go);

%>

<html:link>这种方式最大的功能就是能对传到后台的数据进行url编码,也就是我们经常在地址栏传参数过去,看到一些乱码的一些东西,其实那是用url进行编码的功能

在D:\终极复习版\struts\struts的核心基础\关于url编码有关于url编码的解释

<%

//如果不进行编码的的在后台得到的id的值就是asd,但是如果通过编码的话就是asd&go

String s = URLEncoder.encode("asd&go","utf-8");

request.setAttribute("s",s);

%>

<ahref="${pageContext.request.contextPath}/testGoGo1.htm?p=go&id=${s}">点击</a>;

<!-- 这是将保存在request中的name的值赋值给paramId中的userName -->

<html:link action="/testGoGo1.htm?p=go"paramId="userName"paramName="name">点击</html:link>很好 可以自动拦截以任何东西结尾的

<!-- 这是将保存在request中的name对象的time属性赋值给paramId中的now -->

<html:link action="/testGoGo1.htm?p=go"paramId="now"paramName="date"paramProperty="time">点击</html:link>

<!--这是将go对象的map属性(脸面包含喝多对象) -->

<html:link action="/testGoGo1.htm?p=go" name="go"property="map">点击</html:link>

<html:optionsCollection>的用法name表示的是一个集合,value的值就是option中的value的值,label表示的是option中的

<select>

<option value="id">label</option>

</select>

<html:formaction="/testGoGo1.htm?p=go">

<html:select property="name">

<html:optionsCollection name="list"value="id"label="name"/>

</html:select>

</html:form>

5、在struts的核心基础中讲叙了<html:checkbox>和<html:multibox>的区别

<html:checkbox>自动选中在basicCore工程中

Jsp页面

<html:formaction="/testGoGo1.htm?p=go">

<html:multibox value="吃"property="arr"/>吃

<html:multibox value="喝"property="arr"/>喝

<html:multibox value="玩"property="arr"/>玩

<html:multibox value="乐"property="arr"/>乐

<html:select property="name">

<html:optionsCollection name="list"value="id"label="name"/>

</html:select>

</html:form>

<logic:forward>的讲解

假如你想要在地址栏中不打太多的东西,只想打一个工程名就跳到某个界面,那么你可以再

Index.jsp页面使用<logic:forward>标签下面是例子

<logic:forward name="go"/>需要配合和struts配置文件的一个全局action一起使用<global-forwards>

<forward name="go"path="/index.jsp"></forward>

</global-forwards>

该标签的name值必须与forward中的那么值相同。

<logic:redirect>三种不同属性的用法

<logic:redirectforward="go"></logic:redirect>这个是转到struts配置文件的全局action

<logic:redirectpage="/index.jsp"></logic:redirect>这是转到工程下的某一个页面

<logic:redirecthref="/CoreBasic/index.jsp"></logic:redirect>

这个必须写工程名,否则会报错

Struts1是单实例,struts2不是单实例

单实例就是每个人访问action时都会创建一个action,如果action中有一个变量 i = 0;i++;当每个人访问一次的时候,i都会自加。但是struts2不是单实例,当就不会发生在这种情况。

<html:rewrite>的用法

<formaction="<html:rewriteaction="/testGoGo1?p=go"/>

"method="post">

<inputtype="submit"value="提交">

</form>

<html:rewriteaction="/testGoGo1?p=go"/>和<html:link action="/testGoGo1?p=go"/>的区别在于第一个action的生成的是一个网址,而后面一个生成的是一个完整的<a>标签

注意:

String name = request.getParameter("name");

response.getWriter().print(name);

returnnew ActionForward("/index.jsp");

这样输出时输出值不出的,因为new ActionForward("/index.jsp")会清空你输出的内容,需要最会return null才能输出东西。

<html:form>的用法

防止表单重复提交:首先当你访问第一个action的时候,保存一个token,然后回到有表单的页面,当你进入到第二个action的时候,判断该token是否合法,如果合法就进行操作,然后删除该token,当你再次进行刚才的表单重复提交的时候,你判断该token是否合法,因为上次提交到时候你删除了token,所以这次提交时不合法的。所以就不会进行操作,回到表单页面。在使用案例功能与案例中有这个的例子

第一个action的设置标志

this.saveToken(request);

第二个action判断是否有这个标志

ActionMessages actionMessages =new ActionMessages();

//这是得到表单的数据,对表单进行判断是否重复提交

if(!isTokenValid(request))

{

actionMessages.add("formRepeat",new ActionMessage("error"));

saveErrors(request, actionMessages);

return mapping.findForward("index");

}

//这是将那个标志删除,防止表单重复提交

resetToken(request);

<!-- 可以防止表单重复提交 -->

<forward name="hh"path="/MyJsp.jsp"redirect="true"></forward>

关于用工具生成form、action、jsp页面。可以用myEclipse工具生成。在使用功能与案例的49个视频。超有用。可以很简单啊。

MappingDispatchAction的讲解。

引出这个action的主要原因是,因为要显示一个部门的所有部门到一个注册界面,那么首先必须先经过第一次进入action去数据库里面找部门,然后回到注册页面,当点击注册的时候,在第二次进入action。这时候,问题就来了,因为是注册界面,那么必须要有form,如果经过第一次action的时候,因为第一次进入action不需要form,那么会以为formBean为空,如果是保存在作用域session中,那么从注册界面第二次进入到action就会以为form也为空。那么会出现很到的问题。所以解决这个问题必须首先第一次去查找部门的时候,必须是一个action,第二次去注册的时候又需要一个action这样肯呢过有冗余。所以就有了MappingDispatchAction的存在,因为你每次放问一次就是一次请求,但是他们的方法却可以共用一个action。详细见struts使用功能与案例的关于MappingDispatchAction的案例

五种action的讲解

forwardAction dispatchAction includeAction mapingDispatchAction

downLoadAction localeAction lookUpAction

downLoadAction:这是一个关于下载文件的类,在struts的使用功能与案例的关于一个文件的下载的类的案例

localeAction是用于进行国际化的一个action。

<form-beanname="userForm"type="org.apache.struts.action.DynaActionForm">

<form-property name="language"type="java.lang.String"></form-property>

<form-property name="country"type="java.lang.String"></form-property>

<form-property name="page"type="java.lang.String"></form-property>

</form-bean>

<actionpath="/test"name="userForm"type="org.apache.struts.actions.LocaleAction"></action>在struts的功能与案例中有这个案例,记得看看localeAction的源代码,这样发现其实就是以前自己写的那种国际化的一个封装。

<actionpath="/hello"forward="/fail.jsp"></action>

<actionpath="/hello"type="org.apache.struts.IncludeAction"include="/fail.jsp"></action>

上序两个action的功能基本差不多,只不过第一个forwardAction是request.getRequestDispatcher()的封装,第二个是request.getRequestDispatcher().include().

一个小的知识点:像response.setContentType("text/html;charset=utf-8");

Text/html这样的格式代表啥意思可以再tomcat的config的web.xml中可以找得到。

response.setHeader("Content-Disposition","attachment;filename=asd/txt");

<html:submit property="xxx"/>没有formBean对应也不会出错,但是

<html:textproperty="xxx"/>没有formBean肯定会出错,这说明struts考虑问题很细。

lookupDispatchAction可以解决表单提交要提交到某个方法不需要再action=""中不需要写上p=‘某个方法’,但是这个其实不是很好,因为dispatchAction可以解决这个问题,在struts的功能与案例中有这个例子

Struts的高级应用与源代码分析

页面的数据传到formBean中都是字符串,但是到formBean中却能得到相应的类型,是因为用到了beanUtils这个工具包。

转化器:加入页面有一个日期要传到formBean,在这个传的过程,其实页面传过来的都是字符窜,那么是怎么转换成的日期的呢?那是因为struts有一个BeanUtils里面有很多的转换器,把字符窜转换成对应的类型,但是如果页面穿过来的日期是转换成formBean中的java.util.Date这样是不行的,因为只有java.sql.Date这个转换器,没有java.util.Date的转换器,那么就必须自己写一个转换器。这个例子在struts的高级应用于源代码的转换器的例子里面。但是struts1有一个缺陷,因为它是单项转换器,所以在回到页面的时候,那么显示的日期还是不好看。可以用高级应用于源代码的双向转换器器有这个例子。但是struts2是双向转换器。这就是struts2的优点。自定义标签里面不能定义自定义标签。但是模拟做了一个双向转换器。

看看actionServlet的源代码,如果你在web-xml的配置文件中初始化了convertNUll,这个在双向转换器器有这个例子有这个的讲解。

关于下拉框,千万记得如果是用枚举类型做的下拉框,那么千万记得不能用<html:optionsCollection>这个标签。

会出错,在struts的高级应用与源代码的用枚举类型做的select下拉框讲到了这个例子

用struts的插件来做注册转换器,插件的主要就是用来在还未加载actionServlet的init方法之前进行一些处理。

requestProcessor其实就是相当于一个校长的秘书,当校长接到任务的时候,不是自己亲自去干,而是叫秘书去干。actionAservlet就是校长,requestProcessor就是秘书。

异常:运行时的异常和非运行时的异常的区别。runtimeException运行时的异常不需要声明(即不需要throws抛出)简称系统异常,非运行期的异常必须要抛出(throws)

关于异常的另外一种处理方式,在web.xml里面配置。在struts的高级应用与源代码的源代码里面有这个例子。还有关于在struts的配置文件里面进行处理的例子。

异常的一个设计模式。在struts的高级应用与源代码的源代码里面有这个例子。

对于异常在业务层抛出,在表现层处理它,don't throw it , catch it ;

怎么样将xml文件里面的数据读到javaBean中,可以用degister框架

张祥的高级应用于源代码的69个视频,70个视频讲的都是源代码的一些讲解。

actionServlet的init方法:首先去看看源代码(在张祥的高级应用于源代码的69个视频)

initInternal();这个方法主要是读取信息资源包(也就是在控制台打印出来的那些信息),在org.apache.struts.action线面有四个资源包。

initOther();主要就是进行转换器的一些操作。

initServlet();主要就是用digester去读取web.xml里面的actionServlet的配置文件

initChain();

moduleConfig就是用digester去读取struts的配置文件里面的东西。

下面讲解的是actionServlet的requestProcessor的process方法

关于validator框架的讲解

如何把一个中文的properties的配置文件转换成十六进制的(因为在properties文件中不支持中文格式,只支持十六进制),首先你必须将你的jdk的path、classpath、java_home的三个路径配置好,然后用native2ascii -encoding utf-8(编码格式) applicationResource_zh.properties((这是要转换的文件)如果这里面是用中文写的) applicationResource_zh_CN.properties(这是转换后的文件名) (则转换成的这个配置文件就是十六进制写的啦)

这里有一个关于在form中验证的代码,比较完整,在struts的validator的在form中进行国际化验证,而且实现传递参数的国际化

Validator的原理图

Validator的用法流程:

首先在WEB-INF下面拷贝validator-rules.xml(这是校验的一些规则),validation.xml(用于配置一些校验的信息),然后在struts-config的配置文件中读取这两个配置文件,就是用插件配置器读取。---->

//这些信息都可以在struts的官方文档的validator的校验器中去查找

<plug-inclassName="org.apache.struts.validator.ValidatorPlugIn">

//property是固定的名字,value是要读取的配置文件

<set-property

property="pathnames"

value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>

//下面两个参数都是固定的

<set-propertyvalue="false"property="stopOnFirstError"/>

</plug-in>

有一点千万注意,在form中不需要写validate方法了,但是form必须继承validatorForm

提出一个问题,加入有一个注册页面需要验证密码1是否与密码2相等,但是一个修改密码不需要验证密码1是否等于密码2。这时候就需要form继承validatorActionForm这个,这是后在validation.xml中配置的form的名字就是struts-config中每个action的path的值。这个例子其实很简单,在struts的validator中有这个例子。

动态form的验证:本来dynaActionForm是不能进行验证,但是dynaVlidatorForm能进行form的验证。在struts的validator中有这个例子。dynaValidatorActionForm就是处理多个请求的动态form的请求。

可以用validator实现javascript的功能。(对页面进行验证)--->这样可以进行后台验证,可能会影响性能,但是安全性更高。

在做validator的时候,如果有不懂的就去看struts包下的common-validator下的org.apache.commons.validator.resources下的validator_1_1_3.dtd下面的那些配置文件,就可以了解,再不行就看张孝祥的validator的第十一个视频,那里面有一些配置的详细讲解。

我们开发者都是去调用框架,但是我们不知道怎么自己去做validator的那些调用的一些方法,这个可以看张孝祥的validator的低十二个视频,里面有详细的讲解。

自己写一个校验器,然后给别人去调用,是一个关于验证身份证的例子。

读书人网 >软件架构设计

热点推荐