Struts 回顾

1.Struts2简介和Struts1对比

    Struts2是在WebWork2基础发展而来的。和struts1一样, Struts2也属于MVC框架。不过有一点大家需要注意的是:尽管Struts2和struts1在名字上的差别不是很大,但Struts2和struts1在代码编写风格上几乎是不一样的。那么既然有了struts1,为何还要推出struts2。主要是因为struts2有以下优点:

    1 > 在软件设计上Struts2没有像struts1那样跟Servlet API和struts API有着紧密的耦合,Struts2的应用可以不依赖于 ServletAPI和strutsAPI。 Struts2的这种设计属于无侵入式设计,而Struts1却属于侵入式设计。

public class OrderListActionextends Action {

   publicActionForwardexecute(ActionMappingmapping,ActionFormform,

   HttpServletRequestrequest, HttpServletResponseresponse)

   throwsException {

   }

}

    2> Struts2提供了拦截器,利用拦截器可以进行AOP编程,实现如权限拦截等功能。

    3> Strut2提供了类型转换器,我们可以把特殊的请求参数转换成需要的类型。在Struts1中,如果我们要实现同样的功能,就        必须向Struts1的底层实现BeanUtil注册类型转换器才行。

    4> Struts2提供支持多种表现层技术,如:JSP、freeMarker、Velocity等

    5> Struts2的输入校验可以对指定方法进行校验,解决了Struts1长久之痛。

    6> 提供了全局范围、包范围和Action范围的国际化资源文件管理实现

2.搭建环境

    下面是开发Struts2程序最少需要的JAR,以及每个jar的用途。

struts2-core-2.x.x.jar:Struts2框架的核心类库

xwork-core-2.x.x.jar:XWork类库,Struts 2在其上构建

ognl-2.6.x.jar:对象图导航语言(ObjectGraph Navigation Language),struts2框架通过其读写对象的属性

freemarker-2.3.x.jar:Struts2的UI标签的模板使用FreeMarker编写

commons-logging-1.x.x.jar:ASF出品的日志包,Struts2框架使用这个日志包来支持Log4J和JDK 1.4+的日志记录。

commons-fileupload-1.2.1.jar文件上传组件,2.1.6版本后必须加入此文件

    Struts2默认的配置文件为struts.xml,该文件需要存放在WEB-INF/classes下,注意:此文件在开发的时候是放到src目下,程序编译后会自动拷贝到WEB-INF/classes目录下。此文件我们可以不用自己手写直接到Struts框架的例子程序中拷贝过来稍稍修改一下即可该文件的配置模版如下:

<struts>

    <includefile="struts-user.xml"/>

   <includefile="struts-order.xml"/>

</struts>

     struts1.x中,struts框架是通过Servlet启动。在struts2中,struts框架是通过Filter启动。他在web.xml中的配置如下:

<filter>

    <filter-name>struts2</filter-name>

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

  <!-- 自从Struts2.1.3以后,下面的FilterDispatcher已经标注为过时

     <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>-->

</filter>

<filter-mapping>

   <filter-name>struts2</filter-name>

    <url-pattern>/*</url-pattern>

</filter-mapping>

     StrutsPrepareAndExecuteFilter是Struts 2框架的核心控制器,它负责拦截由<url-pattern>/*</url-pattern>指定的所有用户请求,当用户请求到达时,该Filter会过滤用户的请求。默认情况下,如果用户请求的路径不带后缀或者后缀以.action结尾,这时请求将被转入Struts2框架处理,否则Struts2框架将略过该请求的处理。当请求转入Struts2框架处理时会先经过一系列的拦截器,然后再到Action。与Struts1不同,Struts2对用户的每一次请求都会创建一个Action,所以Struts2中的Action是线程安全的。

    在StrutsPrepareAndExecuteFilter的init()方法中将会读取类路径下默认的配置文件struts.xml完成初始化操作。

注意:struts2读取到struts.xml的内容后,以javabean形式存放在内存中,以后struts2对用户的每次请求处理将使用内存中的数据,而不是每次都读取struts.xml文件

3.Struts.xml介绍 

    在struts2框架中使用包来管理Action,包的作用和java中的类包是非常类似的,它主要用于管理一组业务功能相关的action。在实际应用中,我们应该把一组业务功能相关的Action放在同一个包下。

<package name="itcast" namespace="/test" extends="struts-default">

<action name="helloworld" class="cn.itcast.action.HelloWorldAction" method="execute" >

<result name="success">/WEB-INF/page/hello.jsp</result>

</action>

  </package>

    配置包时必须指定name属性,该name属性值可以任意取名,但必须唯一,他不对应java的类包,如果其他包要继承该包,必须通过该属性进行引用。包的namespace属性用于定义该包的命名空间,命名空间作为访问该包下Action的路径的一部分,如访问上面例子的Action,访问路径为:/test/helloworld.action。 namespace属性可以不配置,对本例而言,如果不指定该属性,默认的命名空间为“”(空字符串)。

    通常每个包都应该继承struts-default包, 因为Struts2很多核心的功能都是拦截器来实现。如:从请求中把请求参数封装到action、文件上传和数据验证等等都是通过拦截器实现的。 struts-default定义了这些拦截器和Result类型。可以这么说:当包继承了struts-default才能使用struts2提供的核心功能。 struts-default包是在struts2-core-2.x.x.jar文件中的struts-default.xml中定义。 struts-default.xml也是Struts2默认配置文件。 Struts2每次都会自动加载 struts-default.xml文件。

    包还可以通过abstract=“true”定义为抽象包,抽象包中不能包含action。

4.Action名称搜索顺序和各项配置默认值

    1.获得请求路径的URI,例如url是:http://server/struts2/path1/path2/path3/test.action

    2.首先寻找namespace为/path1/path2/path3的package,如果不存在这个package则执行步骤3;如果存在这个package,则在这个package中寻找名字为test的action,当在该package下寻找不到action 时就会直接跑到默认namaspace的package里面去寻找action(默认的命名空间为空字符串“” ) ,如果在默认namaspace的package里面还寻找不到该action,页面提示找不到action

    3.寻找namespace为/path1/path2的package,如果不存在这个package,则转至步骤4;如果存在这个package,则在这个package中寻找名字为test的action,当在该package中寻找不到action 时就会直接跑到默认namaspace的package里面去找名字为test的action ,在默认namaspace的package里面还寻找不到该action,页面提示找不到action 

    4.寻找namespace为/path1的package,如果不存在这个package则执行步骤5;如果存在这个package,则在这个package中寻找名字为test的action,当在该package中寻找不到action 时就会直接跑到默认namaspace的package里面去找名字为test的action ,在默认namaspace的package里面还寻找不到该action,页面提示找不到action

    5.寻找namespace为/的package,如果存在这个package,则在这个package中寻找名字为test的action,当在package中寻找不到action或者不存在这个package时,都会去默认namaspace的package里面寻找action,如果还是找不到,页面提示找不到action。

 

    默认配置:

1>如果没有为action指定class,默认是ActionSupport。

2>如果没有为action指定method,默认执行action中的execute() 方法。

3>如果没有指定result的name属性,默认值为success。

5.Action中result的转发类型

    常用的类型有:dispatcher(默认值)、redirect、redirectAction、plainText。默认时可以访问web-inf,因为还在服务器中,但是重定向到页面时不能。

    在result中还可以使用${属性名}表达式访问action中的属性,表达式里的属性名对应action中的属性。如下:

    <result type="redirect">/view.jsp?id=${id}</result>

    下面是redirectAction 结果类型的例子,如果重定向的action中同一个包下: 

      <result type="redirectAction">helloworld</result>

     如果重定向的action在别的命名空间下:

      <result type="redirectAction">

<param name="actionName">helloworld</param>

<param name="namespace">/test</param>

      </result>

     plaintext:显示原始文件内容,例如:当我们需要原样显示jsp文件源代码 的时候,我们可以使用此类型。

<result name="source" type="plainText ">

<param name="location">/xxx.jsp</param>

<param name="charSet">UTF-8</param><!-- 指定读取文件的编码 -->

</result>

6.多个Action共享一个试图

     当多个action中都使用到了相同视图,这时我们应该把result定义为全局视图。

<package ....>

<global-results>

<result name="message">/message.jsp</result>

</global-results>

</package>

7.Action的属性注入

     Struts2为Action中的属性提供了依赖注入功能,在struts2的配置文件中,我们可以很方便地为Action中的属性注入值。注意:属性必须提供setter方法。下面通过<param>节点为action的savePath属性注入“/images”

public class HelloWorldAction{

private String savePath;

public String getSavePath() {

return savePath;

}

public void setSavePath(String savePath) {

this.savePath = savePath;

}

}

<package name="itcast" namespace="/test" extends="struts-default">

<action name="helloworld" class="cn.itcast.action.HelloWorldAction" >

<param name="savePath">/images</param>

<result name="success">/WEB-INF/page/hello.jsp</result>

</action>

</package>

8.Action处理请求后缀

    前面我们都是默认使用.action后缀访问Action。其实默认后缀是可以通过常量”struts.action.extension“进行修改的,例如:我们可以配置Struts 2只处理以.do为后缀的请求路径或是指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。如:

<struts>

    <constant name="struts.action.extension" value="do"/>

<constant name="struts.action.extension" value="do,go"/>

</struts> 

9.Struts常量定义

   常量可以在struts.xml或struts.properties中配置,建议在struts.xml中配置,xml方式如上,struts.properties中如下:

struts.action.extension=do

   因为常量可以在下面多个配置文件中进行定义,所以我们需要了解struts2加载常量的搜索顺序:

struts-default.xml

struts-plugin.xml

struts.xml

struts.properties

web.xml

    如果在多个文件中配置了同一个常量,则后一个文件中配置的常量值会覆盖前面文件中配置的常量值.

    <!-- 指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法 和freemarker 、velocity的输出 -->

    <constant name="struts.i18n.encoding" value="UTF-8"/>

    <!-- 该属性指定需要Struts 2处理的请求后缀,该属性的默认值是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" />

    <!– 与spring集成时,指定由spring负责action对象的创建 -->

    <constant name="struts.objectFactory" value="spring" />

    <!–设置Struts2是否支持动态方法调用,默认值是true。如果需要关闭动态方法调用,则可设置该属性为false。 -->

    <constant name="struts.enable.DynamicMethodInvocation" value="false"/>

    <!--上传文件的大小限制-->

    <constant name="struts.multipart.maxSize" value=“10701096"/>

10.action通配符

    要访问other()方法,可以通过这样的URL访问:/test/helloworld_other.action

<package name="itcast" namespace="/test" extends="struts-default">

<action name="helloworld_*" class="cn.itcast.action.HelloWorldAction" method="{1}">

<result name="success">/WEB-INF/page/hello.jsp</result>

</action>

</package>

public class HelloWorldAction{

private String message;

public String other() throws Exception{

this.message = "第二个方法";

return "success";

}

}

11.动态方法调用

    如果Action中存在多个方法时,我们可以使用!+方法名调用指定方法。如下:已经不推荐使用,一般用通配符。

     假设访问下面action的URL路径为: /struts/test/helloworld.action要访问action的other()方法,我们可以这样调用:

/struts/test/helloworld!other.action,如果不想使用动态方法调用,可以通过常量struts.enable.DynamicMethodInvocation关闭动态方法调用。<constant name="struts.enable.DynamicMethodInvocation" value="false"/>

public class HelloWorldAction{

private String message;

public String other() throws Exception{

this.message = "第二个方法";

return "success";

}

}

12.请求参数

    采用基本类型接收请求参数(get/post),在Action类中定义与请求参数同名的属性,struts2便能自动接收请求参数并赋予给同名属性。请求路径: http://localhost:8080/test/view.action?id=78

public class ProductAction {

      private Integer id;

      public void setId(Integer id) {//struts2通过反射技术调用与请求参数同名的属性的setter方法来获取请求参数值

             this.id = id;

      }

      public Integer getId() {return id;}

  }

    采用复合类型接收请求参数。Struts2首先通过反射技术调用Product的默认构造器创建product对象,然后再通过反射技术调用product中与请求参数同名的属性的setter方法来获取请求参数值。请求路径: http://localhost:8080/test/view.action?product.id=78

  public class ProductAction {

    private Product product;

   public void setProduct(Product product) {  this.product = product;  }

   public Product getProduct() {return product;}

}

13.乱码问题

    struts2.1.6版本中存在一个Bug,即接收到的中文请求参数为乱码(以post方式提交),原因是struts2.1.6在获取并使用了请求参数后才调用HttpServletRequest的setCharacterEncoding()方法进行编码设置 ,导致应用使用的就是乱码请求参数。这个bug在struts2.1.8中已经被解决,如果你使用的是struts2.1.6,要解决这个问题,你可以这样做:新建一个Filter,把这个Filter放置在Struts2的Filter之前,然后在doFilter()方法里添加以下代码

public void doFilter(...){

HttpServletRequest req = (HttpServletRequest) request;

req.setCharacterEncoding("UTF-8");//应根据你使用的编码替换UTF-8

filterchain.doFilter(request, response);

}

14.访问或添加request/session/application属性

public String scope() throws Exception{

   ActionContext ctx = ActionContext.getContext();

   ctx.getApplication().put("app", "应用范围");//往ServletContext里放入app

   ctx.getSession().put("ses", "session范围");//往session里放入ses

   ctx.put("req", "request范围");//往request里放入req

   return "scope";

}

JSP:

 <body>

    ${applicationScope.app} <br>

    ${sessionScope.ses}<br>

    ${requestScope.req}<br>

 </body>

获取HttpServletRequest / HttpSession / ServletContext / HttpServletResponse对象

方法一,通过ServletActionContext.类直接获取:

public String rsa() throws Exception{

HttpServletRequest request = ServletActionContext.getRequest();

ServletContext servletContext = ServletActionContext.getServletContext();

request.getSession()

HttpServletResponse response = ServletActionContext.getResponse();

return "scope";

}

方法二,实现指定接口,由struts框架运行时注入:

public class HelloWorldAction implements ServletRequestAware, ServletResponseAware, ServletContextAware{

private HttpServletRequest request;

private ServletContext servletContext;

private HttpServletResponse response;

public void setServletRequest(HttpServletRequest req) {

this.request=req;

}

public void setServletResponse(HttpServletResponse res) {

this.response=res;

}

public void setServletContext(ServletContext ser) {

this.servletContext=ser;

}

}

15.拦截器   

    要自定义拦截器需要实现com.opensymphony.xwork2.interceptor.Interceptor接口:

    因为struts2中如文件上传,数据验证,封装请求参数到action等功能都是由系统默认的defaultStack中的拦截器实现的,所以我们定义的拦截器需要引用系统默认的defaultStack,这样应用才可以使用struts2框架提供的众多功能。如果希望包下的所有action都使用自定义的拦截器,可以通过<default-interceptor-ref name=“permissionStack”/>把拦截器定义为默认拦截器。注意:每个包只能指定一个默认拦截器。另外,一旦我们为该包中的某个action显式指定了某个拦截器,则默认拦截器不会起作用。

public class PermissionInterceptor implements Interceptor {

   public String intercept(ActionInvocation invocation) throws Exception {

  System.out.println("进入拦截器");

if(session里存在用户){

String result = invocation.invoke();

}else{

return “logon”;

}

return result;

    }

}

<package name="itcast" namespace="/test" extends="struts-default">

<interceptors>

          <interceptor name=“permission" class="cn.itcast.aop.PermissionInterceptor" />

          <interceptor-stack name="permissionStack">

  <interceptor-ref name="defaultStack" />

  <interceptor-ref name=" permission " />

           </interceptor-stack>

  </interceptors>

<action name="helloworld_*" class="cn.itcast.action.HelloWorldAction" method="{1}">

<result name="success">/WEB-INF/page/hello.jsp</result>

<interceptor-ref name="permissionStack"/>

</action>

</package>

16.<s:token />标签防止重复提交

<s:token />标签防止重复提交,用法如下:

第一步:在表单中加入<s:token />

<s:form action="helloworld_other" method="post" namespace="/test">

  <s:textfield name="person.name"/><s:token/><s:submit/>

  </s:form>

第二步:

<action name="helloworld_*" class="cn.itcast.action.HelloWorldAction" method="{1}">

       <interceptor-ref name="defaultStack" />

        <interceptor-ref name="token" />

        <result name="invalid.token">/WEB-INF/page/message.jsp</result>  

        <result>/WEB-INF/page/result.jsp</result>

</action>

以上配置加入了“token”拦截器和“invalid.token”结果,因为“token”拦截器在会话的token与请求的token不一致时,将会直接返回“invalid.token”结果。

在debug状态,控制台出现下面信息,是因为Action中并没有struts.token和struts.token.name属性,我们不用关心这个错误:

严重: ParametersInterceptor - [setParameters]: Unexpected Exception caught setting 'struts.token' on 'class xxx: Error setting expression 'struts.token' with value '[Ljava.lang.String;@39f16f'

严重: ParametersInterceptor - [setParameters]: Unexpected Exception caught setting 'struts.token.name'

17.Action参数校验

18.国际化

19.OGNL

20.Struts标签

21.转换器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
水资源是人类社会的宝贵财富,在生活、工农业生产中是不可缺少的。随着世界人口的增长及工农业生产的发展,需水量也在日益增长,水已经变得比以往任何时候都要珍贵。但是,由于人类的生产和生活,导致水体的污染,水质恶化,使有限的水资源更加紧张。长期以来,油类物质(石油类物质和动植物油)一直是水和土壤中的重要污染源。它不仅对人的身体健康带来极大危害,而且使水质恶化,严重破坏水体生态平衡。因此各国都加强了油类物质对水体和土壤的污染的治理。对于水中油含量的检测,我国处于落后阶段,与国际先进水平存在差距,所以难以满足当今技术水平的要求。为了取得具有代表性的正确数据,使分析数据具有与现代测试技术水平相应的准确性和先进性,不断提高分析成果的可比性和应用效果,检测的方法和仪器是非常重要的。只有保证了这两方面才能保证快速和准确地测量出水中油类污染物含量,以达到保护和治理水污染的目的。开展水中油污染检测方法、技术和检测设备的研究,是提高水污染检测的一条重要措施。通过本课题的研究,探索出一套适合我国国情的水质污染现场检测技术和检测设备,具有广泛的应用前景和科学研究价值。 本课题针对我国水体的油污染,探索一套检测油污染的可行方案和方法,利用非分散红外光度法技术,开发研制具有自主知识产权的适合国情的适于野外便携式的测油仪。利用此仪器,可以检测出被测水样中亚甲基、甲基物质和动植物油脂的污染物含量,为我国众多的环境检测站点监测水体的油污染状况提供依据。
### 内容概要 《计算机试卷1》是一份综合性的计算机基础和应用测试卷,涵盖了计算机硬件、软件、操作系统、网络、多媒体技术等多个领域的知识点。试卷包括单选题和操作应用两大类,单选题部分测试学生对计算机基础知识的掌握,操作应用部分则评估学生对计算机应用软件的实际操作能力。 ### 适用人群 本试卷适用于: - 计算机专业或信息技术相关专业的学生,用于课程学习或考试复习。 - 准备计算机等级考试或职业资格认证的人士,作为实战演练材料。 - 对计算机操作有兴趣的自学者,用于提升个人计算机应用技能。 - 计算机基础教育工作者,作为教学资源或出题参考。 ### 使用场景及目标 1. **学习评估**:作为学校或教育机构对学生计算机基础知识和应用技能的评估工具。 2. **自学测试**:供个人自学者检验自己对计算机知识的掌握程度和操作熟练度。 3. **职业发展**:帮助职场人士通过实际操作练习,提升计算机应用能力,增强工作竞争力。 4. **教学资源**:教师可以用于课堂教学,作为教学内容的补充或学生的课后练习。 5. **竞赛准备**:适合准备计算机相关竞赛的学生,作为强化训练和技能检测的材料。 试卷的目标是通过系统性的题目设计,帮助学生全面复习和巩固计算机基础知识,同时通过实际操作题目,提高学生解决实际问题的能力。通过本试卷的学习与练习,学生将能够更加深入地理解计算机的工作原理,掌握常用软件的使用方法,为未来的学术或职业生涯打下坚实的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值