struts1的整体复习讲解

Struts1的终极复习

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

2、  搭建环境

3、  actionForm的建立

4、  action的开发

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

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

<struts-config>

  <data-sources />

  <form-beans>

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

  </form-beans>

  <global-exceptions />

  <global-forwards />

  <action-mappings>

    <action path="/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-resources parameter="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开发的一个流程图

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

 

6、  struts中的各个组件

<1>actionServlet的讲解

注意:在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 ++;

           }

<3>actionMapping的讲解

其实actionMapping就相当于是一个actionaction有很多属性,在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的查找过程。

ActionForm的流程图

首先根据Actionname查找form,再根据作用范围查找,如果有就直接使用,如果不存在就创建一个。根据namescope去查找。如果找不到,就构造一个,首先调用的是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>

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

</global-forwards>

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

资源文件

7、  标签的讲解

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

Name:要查找的bean。

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

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

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

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

<Bean:define>的用法

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

<Bean:write >的用法

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

  ${ sessionScope.person1}

<bean:message>的用法

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

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

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

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

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

 

8、  逻辑标签

<logic:iterate id="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:iterate id="p" name="list3" scope="request">

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

           ${go.id}<bean:write name="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>

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

然后去hobby对应的值给value.

9、  动态form

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

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

<form-bean name="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的表单标签。

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

       System.out.println(userName);

       for (String string : hobby) {

           System.out.println(string);

       }

//EL表达式取值

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

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

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

动态formmap的用法

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

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

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

    for (Object object : sets) {

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

       }

10.异常

异常机制

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

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

插件Plugin

<plug-in className="com.plugin.PersonPlugin">

    <set-property value="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的讲解

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

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

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

 

 

 

              Formbean和国际化

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

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

解释Serializable这个问题

关于form中的validate的一些讲解

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方法,还需要在资源文件中写上相应的userNameErrorpasswordError的键值对。

    <form action="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><!-- 这是页面与loginuserName对应 -->

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

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

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

        <br><!-- 这是页面与loginpassword对应 -->

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

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

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

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

 

FormBeanvalidate方法

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不需要你管

       }

       return actionErrors;

    }

 

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

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

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

<bean:message>标签的国际化

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

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

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

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

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

<!-- 解决方法 -->

<html:submit><bean:message key='info.submit'/></html:submit>

  <message-resources      

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

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

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

例如:  <html:link action="#" 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>的讲解

ActionMessage messages = new ActionMessage("userNameError");

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

           actionErrors.add("userName",messages);

           actionErrors.add("userName",messages1);

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

 

业务逻辑验证

ActionErrors(已淘汰) ActionMessages

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

//业务逻辑的验证

       PersonForm personForm = (PersonForm)form;

//     ActionMessagesActionErrors的父类

       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 = new ActionMessage("userNameRepeate", this.getResources(request).getMessage(this.getLocale(request),"go"));

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

 

关于form的两种形式及区别

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

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

    <html:errors property="userNameCH" footer="" header=""/>

    <html:errors property="userName"/>

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

    <html:errors property="asd"/>

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

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

</form>

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

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

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

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

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

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

</html:form>

 

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

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

 

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

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

 

文件上传的讲解

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

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

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

</html:form>

 

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

 

解释:

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

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

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

 

 

Struts的核心基础

1、web.xml配置文件中拦截的是*.html的时候,那么struts-config配置文件的actionpath=/testtext后面的.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

如:

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

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

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

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

 

<action path="/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>

 

加强版

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

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

<action path="/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"%>

 

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

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

<html:link action="/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);

%>

    <a href="${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:form action="/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:form action="/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:redirect forward="go"></logic:redirect>这个是转到struts配置文件的全局action

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

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

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

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

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

<html:rewrite>的用法

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

"method="post">

    <input type="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>

关于用工具生成formactionjsp页面。可以用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-bean name="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>

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

 

 

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

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

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

 

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

Text/html这样的格式代表啥意思可以再tomcatconfigweb.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的插件来做注册转换器,插件的主要就是用来在还未加载actionServletinit方法之前进行一些处理。

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

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

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

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

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

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

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

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

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

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

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

initChain();

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

 

 

下面讲解的是actionServletrequestProcessorprocess方法

 

 

 

关于validator框架的讲解

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

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

Validator的原理图

Validator的用法流程:

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

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

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

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

           <set-property

           property="pathnames"

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

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

           <set-property value="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的验证。在strutsvalidator中有这个例子。dynaValidatorActionForm就是处理多个请求的动态form的请求。

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值