掌握Struts2框架核心jar包组件与实践

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Struts2是一个采用MVC设计模式的Java Web框架,由Apache维护,其核心jar包提供了处理用户请求、业务逻辑、数据传递及结果展示等功能。本文将深入探讨Struts2-jar中的关键组件,包括Action类、Interceptor、Result、ValueStack、OGNL表达式、模板引擎支持、插件机制、ActionContext、配置文件及生命周期管理。了解这些组件的工作原理和配置方法,能够帮助开发者高效构建出结构良好、易于维护的Web应用程序。同时,鉴于Struts2的安全问题,本文也强调了更新和安全的重要性。 strust2-jar

1. Struts2框架介绍与核心概念

1.1 Struts2框架概述

Struts2框架是一个用于构建Java Web应用的强大框架,它允许开发者以MVC(模型-视图-控制器)模式来组织代码。通过集中处理Web层的业务逻辑,Struts2极大地简化了Java EE的应用开发流程。该框架提供了丰富的组件,使得Web层的功能开发更加高效。

1.2 Struts2的核心组件

Struts2的核心组件包括Action、Interceptor(拦截器)、Result类型、ValueStack(值栈)等。这些组件共同工作,支持Web应用的请求处理、数据管理和视图交互等功能。接下来的章节将详细探讨这些核心组件的特性和配置方法,帮助您更好地理解和运用Struts2框架。

2. 深入理解Action类与注解配置

2.1 Action类的作用和特性

2.1.1 Action类的基本概念

在Struts2框架中,Action类扮演着将Web层请求转化为业务逻辑处理的角色。它是一个普通的Java类,遵循特定的编程规范,比如继承自 ActionSupport 类或实现 Action 接口。Action类封装了所有与特定请求相关的处理逻辑,并通过返回一个字符串类型的 result 值来指示框架下一步应该显示哪个视图。

Action类的职责通常包括:

  • 接收用户通过表单提交的数据。
  • 处理业务逻辑,包括调用服务层组件进行数据处理。
  • 返回一个操作结果给Struts2框架,指示下一步动作(如显示页面、返回错误消息等)。

2.1.2 Action类的继承与实现

Struts2中的Action类大多采用继承的方式,从一个基础类(如 ActionSupport )继承而来,这样可以复用一些常见的方法和属性。 ActionSupport 类提供了许多有用的默认方法,比如国际化支持、数据校验和默认的执行结果常量等。这使得开发者能够专注于特定业务逻辑的实现,而不需要重新编写通用的功能代码。

开发者可以根据需要实现 Action 接口,该接口定义了 execute() 方法。而继承 ActionSupport 类则自带了 execute() 方法的默认实现。但在实际开发中,通常推荐通过注解(如 @Action )来定义Action类,这样可以更灵活地配置Action行为,并且使得代码更加简洁。

. . . Action类的继承示例

public class MyAction extends ActionSupport {
    private String name;
    private int age;

    public String execute() {
        // 在这里实现业务逻辑
        // ...
        return SUCCESS;
    }

    // getter和setter方法
    // ...
}

2.2 Action类的注解配置方法

2.2.1 注解的引入与优势

Struts2框架支持通过注解来配置Action类,这种方式使代码更加清晰,并且易于维护。通过使用注解,可以将Action映射到特定的URL,定义结果类型以及执行结果等,而无需在XML配置文件中添加大量的配置信息。这种方式尤其适合小型到中型的项目,能够大大减少配置的复杂度。

例如,使用 @Action 注解可以直接指定一个Action类对应的URL,而 @Result 注解用于定义执行后的返回结果。这样的配置方式比XML更加直观且易于理解。

2.2.2 常见注解的使用场景和规则

在Struts2中,几个常用的注解包括:

  • @Action :用于定义一个Action类或方法的访问路径及默认操作。
  • @Results :用于定义一组返回结果的映射。
  • @Result :用于定义一个单一的返回结果。
  • @Exception :用于处理Action执行过程中抛出的异常。
@Action(value = "login", results = {
    @Result(name = "success", location = "/login_success.jsp"),
    @Result(name = "input", location = "/login.jsp")
})
public class LoginAction extends ActionSupport {
    private String username;
    private String password;

    public String execute() {
        // 实现登录逻辑
        return SUCCESS;
    }

    // getter和setter方法
    // ...
}

. . . 注解配置示例分析

在上面的代码示例中, @Action 注解定义了访问路径 login 和两个返回结果 success input 。当Action执行成功时,用户会被重定向到 login_success.jsp 页面;如果执行失败(比如验证失败),则返回 login.jsp 页面,用户可以重新输入信息。

使用注解可以减少大量的XML配置,使得代码更加符合现代Java开发习惯,并能快速适应开发需求变化。

【内容到此结束,接下来是第三章内容】

3. 拦截器Interceptor的实践与重要性

在Struts2框架中,拦截器(Interceptor)是用于处理业务流程中特定任务的一系列组件,它们可以在请求处理前后执行特定的行为。拦截器类似于过滤器(Filter),但是拦截器是在框架内部使用,能够访问Action的上下文,而过滤器是在Web容器级别使用,无法直接访问框架内部上下文。拦截器在Struts2中扮演着至关重要的角色,因为它不仅提高了代码的复用性,还增强了系统的可维护性和扩展性。

3.1 拦截器的工作机制和生命周期

3.1.1 拦截器的执行流程

拦截器执行流程由一系列的步骤组成,其核心工作流程如下:

  1. 用户发出请求,请求到达Struts2框架的过滤器(FilterDispatcher或StrutsPrepareAndExecuteFilter)。
  2. 过滤器根据请求的URL查找对应的Action映射信息。
  3. 在Action映射信息中,检查是否存在拦截器栈(Interceptor Stack),如果存在,则按照预定义的顺序执行栈中的拦截器。
  4. 拦截器的 intercept 方法被调用。此方法接收一个 ActionInvocation 对象作为参数, ActionInvocation 对象封装了Action的调用过程。
  5. 如果拦截器决定继续执行链中的下一个拦截器或最终的Action,则调用 ActionInvocation invoke 方法。否则,流程到此结束。
  6. 执行完成后,请求响应返回给用户。

3.1.2 拦截器的优先级和顺序管理

在Struts2中,拦截器栈定义了拦截器执行的顺序,栈中的拦截器按照定义顺序从前到后执行。如果拦截器栈中包含多个拦截器,那么它们会按照栈中的顺序形成一个调用链。当一个拦截器完成自己的任务后,会调用链中的下一个拦截器,直至所有拦截器都执行完毕,最后执行Action本身。

拦截器的优先级和顺序是通过在 struts.xml 文件中配置拦截器栈来管理的。开发者可以通过以下配置来定义拦截器栈,并在其中指定拦截器的顺序:

<interceptors>
    <interceptor name="logger" class="com.example.interceptor.LoggerInterceptor"/>
    <interceptor name="timer" class="com.example.interceptor.TimerInterceptor"/>
    <!-- 更多拦截器定义 -->
</interceptors>

<interceptor-stacks>
    <interceptor-stack name="defaultStack">
        <interceptor-ref name="logger"/>
        <interceptor-ref name="timer"/>
        <!-- 添加其他拦截器或拦截器栈 -->
        <interceptor-ref name="defaultStack"/>
    </interceptor-stack>
</interceptor-stacks>

<action name="example" class="com.example.actions.ExampleAction">
    <interceptor-ref name="defaultStack"/>
    <!-- 其他配置 -->
</action>

上述配置文件中定义了两个拦截器 LoggerInterceptor TimerInterceptor ,并且通过一个名为 defaultStack 的拦截器栈组合它们。在具体的Action配置中,通过引用 defaultStack 来指定调用该Action时应该执行的拦截器栈。

3.2 自定义拦截器的创建与应用

3.2.1 自定义拦截器的编写步骤

创建一个自定义拦截器主要涉及以下步骤:

  1. 创建拦截器类 :继承 com.opensymphony.xwork2.interceptor.Interceptor 类,并重写 intercept 方法。
  2. 实现拦截逻辑 :在 intercept 方法中定义拦截器需要执行的任务。
  3. 注册拦截器 :在 struts.xml 文件中注册拦截器,使其可用。
  4. 配置拦截器栈 :如果需要,将自定义拦截器加入到拦截器栈中。
  5. 应用拦截器 :在Action映射中引用拦截器或拦截器栈。

下面是一个简单的自定义拦截器示例代码:

package com.example.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class LoggerInterceptor implements Interceptor {

    @Override
    public void destroy() {
        // 清理资源
    }

    @Override
    public void init() throws Exception {
        // 初始化拦截器资源
    }

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        long startTime = System.currentTimeMillis();
        try {
            return invocation.invoke();
        } finally {
            long endTime = System.currentTimeMillis();
            System.out.println("Time taken to execute the Action was " + (endTime - startTime) + "ms");
        }
    }
}

注册和配置拦截器的 struts.xml 配置:

<interceptors>
    <interceptor name="logger" class="com.example.interceptor.LoggerInterceptor"/>
</interceptors>

<interceptor-stacks>
    <interceptor-stack name="defaultStack">
        <interceptor-ref name="logger"/>
        <!-- 其他预定义的拦截器 -->
    </interceptor-stack>
</interceptor-stacks>

<action name="example" class="com.example.actions.ExampleAction">
    <interceptor-ref name="defaultStack"/>
    <!-- 其他配置 -->
</action>

通过上述步骤,自定义拦截器 LoggerInterceptor 被创建并应用于名为 example 的Action。每当这个Action被调用时, LoggerInterceptor 都会记录执行时间。

3.2.2 拦截器在实际项目中的应用案例

拦截器在实际项目中非常有用,它可以用于日志记录、权限检查、性能监控、数据校验等场景。下面是一个使用拦截器进行权限检查的案例。

首先,创建一个检查用户权限的拦截器:

public class AuthInterceptor extends AbstractInterceptor {

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        HttpServletRequest request = (HttpServletRequest) invocation.getInvocationContext().get(ServletActionContext.HTTP_REQUEST);
        HttpSession session = request.getSession(false);
        User user = (session != null && session.getAttribute("currentUser") != null) ? (User) session.getAttribute("currentUser") : null;

        // 检查用户是否登录
        if (user != null && "admin".equals(user.getRole())) {
            return invocation.invoke();
        } else {
            // 用户未登录或登录的角色不符合要求
            return "login"; // 返回登录页面的逻辑视图名
        }
    }
}

然后,在 struts.xml 中注册并配置拦截器:

<interceptors>
    <interceptor name="auth" class="com.example.interceptor.AuthInterceptor"/>
</interceptors>

<interceptor-stacks>
    <interceptor-stack name="defaultStack">
        <interceptor-ref name="auth"/>
        <!-- 其他拦截器 -->
    </interceptor-stack>
</interceptor-stacks>

<action name="securedAction" class="com.example.actions.SecuredAction">
    <interceptor-ref name="defaultStack"/>
</action>

在上面的配置中,每当 securedAction 被执行时,都会先经过 AuthInterceptor 拦截器。拦截器会检查用户是否已登录,并且角色是否为管理员。如果不是,则用户会被重定向到登录页面。

通过这种方式,拦截器可以帮助开发者维护安全的Web应用,实现各种业务逻辑的控制和数据访问的管理。

4. Result类型与视图层交互的原理与实践

4.1 Result类型的基本使用

4.1.1 Result类型的分类和功能

在Struts2框架中,Result类型是用于控制视图层响应的组件。它负责将Action处理的结果反馈给用户。Result类型可以根据其作用和返回内容的不同进行分类。主要的Result类型包括:

  • dispatcher : 将处理后的数据转发到JSP页面或其他资源。这是最常用的Result类型,适用于服务器端渲染页面的场景。
  • redirect : 使用HTTP重定向方式将请求转发到外部URL或内部资源。这种方式不会保留之前请求范围内的数据。
  • chain : 用于链式调用其他Action。它可以传递数据到下一个Action,并将流程控制权交出。
  • stream : 用于将数据以流的形式直接发送给客户端,适用于文件下载或大文件处理。

每种Result类型都有其特定的使用场景,开发者可以根据需要选择合适的类型。例如,在处理需要用户登录验证的页面时,通常会使用 chain Result来将用户导向登录Action。

<result name="success" type="chain">login</result>

上述XML配置表示当Action执行结果为"success"时,将会调用名为"login"的Action继续处理请求。

4.1.2 Result配置与页面跳转实例

在Struts2配置文件 struts.xml 中,每个Action都可以配置多个Result类型。以下是一个基本的配置示例:

<action name="viewUser" class="com.example.UserAction">
    <result name="success">/pages/success.jsp</result>
    <result name="error">/pages/error.jsp</result>
</action>

在这个例子中,我们定义了一个名为 viewUser 的Action。根据执行结果的不同,它将跳转到不同的JSP页面:

  • viewUser Action执行成功时,会跳转到 success.jsp 页面。
  • 如果执行失败,则会跳转到 error.jsp 页面。

Result配置的灵活性让开发者可以对视图层进行精细的控制。当然,Result也可以在Action内部使用Java代码直接指定。

4.2 视图层交互的深入探索

4.2.1 JSP/FreeMarker/Velocity的集成方式

Struts2支持多种视图层技术,主要包括JSP、FreeMarker和Velocity等。集成这些技术到Struts2项目中的步骤大体如下:

  1. 添加依赖 :在项目的 pom.xml 文件中添加所选模板引擎的依赖。 xml <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.31</version> </dependency>

  2. 配置Struts2 :在 struts.xml 中指定使用的视图技术。 xml <package name="default" extends="struts-default"> <result-types> <result-type name="ftl" class="freemarker.template.Configuration" default="true"/> </result-types> <!-- ... --> </package>

  3. 创建模板文件 :在项目中的指定目录下创建模板文件。例如,对于FreeMarker模板,你可以创建一个名为 success.ftl 的文件。

  4. 编写Action逻辑 :在Action类中准备模板所需的数据。

  5. 配置Result :在Action标签中配置返回的Result类型,指定使用的模板文件。 xml <result name="success" type="ftl">/pages/success.ftl</result>

通过以上步骤,开发者可以将JSP、FreeMarker或Velocity等视图技术与Struts2框架集成在一起,构建出功能丰富的Web应用。

4.2.2 视图层数据传递与展示技巧

在使用Struts2进行Web应用开发时,有效地在视图层和后端逻辑之间传递数据是关键。以下是几种常见的数据传递和展示技巧:

  1. 使用ValueStack传递数据 :Action中的属性值会自动推送到ValueStack中,视图层可以直接访问这些值。

  2. 使用ognl表达式 :在JSP页面中,可以使用OGNL表达式访问ValueStack中的值。 ```jsp

    用户姓名: ${user.name}

```

  1. 使用Struts2标签库 :Struts2提供了丰富的标签库,便于开发中实现数据展示和表单处理等。 jsp <s:property value="user.name" />

  2. 数据封装 :将多个数据封装到一个对象中,然后将该对象放入ValueStack中,便于管理和传递。 ```java public class UserData { private String name; private String email; // getters and setters }

// 在Action中 UserData userData = new UserData(); userData.setName("John Doe"); userData.setEmail("john.***"); valueStack.push(userData); ```

  1. 使用DynaActionForm动态表单 :当表单字段很多且不经常改变时,使用DynaActionForm动态表单可以简化Action的编写。 xml <form-bean name="myForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="username" type="java.lang.String"/> <form-property name="password" type="java.lang.String"/> </form-bean>

通过这些技巧,开发者可以构建出清晰、高效且易于维护的视图层代码。这不仅有助于提高开发效率,还可以确保Web应用的性能和可扩展性。

5. ValueStack与数据传递的机制

5.1 ValueStack的作用与原理

5.1.1 ValueStack在Struts2中的角色

ValueStack是Struts2框架中一个核心组件,它是用于存放数据的对象栈,这些数据通常与用户交互有关。ValueStack作为数据传递的载体,在Action与视图层之间起到了桥梁的作用。开发者可以将业务对象或者临时数据存放在ValueStack中,视图层通过OGNL表达式可以直接访问这些数据,这样就实现了MVC架构中的Model部分。

ValueStack还是实现Struts2框架中动态类型转换和类型安全特性的一个重要基础。例如,它可以存储从请求参数到Action属性的映射结果。当Action中的属性类型和请求参数的类型不完全匹配时,Struts2框架会尝试使用内置的或自定义的类型转换器来转换数据类型,以满足Action属性的需要。

5.1.2 ValueStack与OGNL的关系

ValueStack与OGNL(Object-Graph Navigation Language)紧密相关。OGNL是一种功能强大的表达式语言,用于获取和设置Java对象的属性。Struts2框架利用OGNL可以方便地在ValueStack上进行数据的存取操作,不必再编写繁琐的getter和setter方法。

当在Action类中使用OGNL表达式时,框架会自动通过ValueStack来解析这些表达式。例如, ${user.name} 表达式可以通过OGNL从ValueStack中获取名为"user"的对象,然后访问其"name"属性。这种机制极大地简化了数据的传递和页面的表达。

5.2 ValueStack在实际应用中的技巧

5.2.1 数据封装与传递的最佳实践

在实际开发中,合理地使用ValueStack可以简化代码并提升程序的可维护性。以下是一些推荐的最佳实践:

  • 使用ValueStack传递复杂对象 :ValueStack可以存储任意类型的对象,因此可以用来传递包含复杂业务逻辑的对象。例如,在处理表单提交时,可以创建一个业务对象,将其添加到ValueStack中,然后在JSP页面中通过OGNL表达式访问其属性。

  • 利用ValueStack进行数据回显 :在表单验证失败后,可以将表单对象重新放入ValueStack中,利用Struts2的 <s:fielderror> 标签回显错误信息,而无需额外处理错误信息的存储与传递。

  • ValueStack的栈操作 :ValueStack提供了栈操作的方法,例如 push pop 等,可以用来临时存放数据。在处理复杂逻辑时,可以利用栈的操作来存储中间状态,方便后续处理。

5.2.2 解决ValueStack相关问题的方法

尽管ValueStack为开发者提供了便利,但有时候也会遇到一些问题,以下是一些解决问题的建议:

  • 避免ValueStack中的数据污染 :由于ValueStack具有全局访问性,当多个Action共享同一个ValueStack时可能会引起数据污染。可以通过为每个Action操作创建一个新的ValueStack实例来避免这个问题。

  • 合理控制ValueStack中的数据量 :过多的数据存放在ValueStack中会增加内存的消耗,并且可能会引起性能问题。应该在不需要时,及时清理不再使用的数据,或者使用值栈的浅拷贝来减少数据量。

  • 了解ValueStack的执行顺序 :ValueStack的数据存取顺序需要开发者深入了解。当执行多个拦截器和数据处理逻辑时,需要明确数据是如何被存入和取出的,以免出现数据读取错误。

  • 利用ValueStack实现数据类型转换 :当Action类中的属性类型与请求中的数据类型不匹配时,可以利用ValueStack和OGNL的强大组合来进行动态类型转换,从而避免了编写繁琐的类型转换代码。

代码块与逻辑分析

在Struts2框架中,ValueStack的管理是自动进行的。但有时我们需要在Action中直接操作ValueStack来实现特定的业务逻辑。以下是一个示例代码,展示了如何在Action中直接操作ValueStack。

public class MyAction extends ActionSupport {
    private User user;
    public String execute() {
        // 获取ValueStack对象
        ValueStack stack = ActionContext.getContext().getValueStack();
        // 向ValueStack中推送数据
        stack.push(user);
        // 通过OGNL表达式获取数据
        User resultUser = (User) stack.findValue("user");
        // 输出结果
        System.out.println(resultUser.getName());
        return SUCCESS;
    }
}

在这段代码中,首先通过 ActionContext.getContext().getValueStack() 获取当前的ValueStack对象。接着,使用 push 方法将一个名为user的User对象推入ValueStack中。之后,利用OGNL表达式 findValue 从ValueStack中检索出名为"user"的对象,并将其转换为User类型。最后,通过控制台输出了该对象的"name"属性。

从这个例子中可以看出,ValueStack的使用与OGNL表达式相结合,为数据操作提供了极大的灵活性和便利。但需要注意的是,ValueStack是线程不安全的,因此在多线程环境下操作ValueStack时应格外小心。

6. OGNL表达式的深入理解和应用

在Struts2框架中,OGNL(Object-Graph Navigation Language)扮演着至关重要的角色,它为开发者提供了一种强大而灵活的方式来访问和操作对象属性。本章节将深入探讨OGNL的基础知识、高级特性以及在Struts2中的具体应用。

6.1 OGNL的基本语法和功能

6.1.1 OGNL表达式的构成

OGNL表达式是一种简洁而强大的查询和操作语言,它允许我们访问Java对象的属性和方法。在Struts2中,OGNL通常与ActionContext一起使用,可以操作Action类的实例以及其他上下文数据。

表达式由若干个部分组成,主要包括:属性访问、方法调用、静态字段/方法访问和集合操作等。下面是OGNL表达式的一些基本构成元素:

  • 属性访问: 通过点符号访问对象的属性,例如: user.name
  • 方法调用: 通过括号调用对象的方法,例如: user.getName()
  • 静态成员访问: 通过 # 符号访问类的静态字段或方法,例如: #Math.PI
  • 集合操作: 访问集合中的元素或执行集合相关的方法,例如: list[0] , collection.size()

6.1.2 OGNL的运算符和表达式示例

OGNL提供了丰富的运算符,例如赋值运算符 = 、算术运算符、比较运算符和逻辑运算符等。这些运算符可以帮助我们在OGNL表达式中执行复杂的操作。

示例1:简单OGNL表达式
// 假设有一个对象user,拥有属性name和age
String expression = "user.name + ' is ' + user.age + ' years old'";
Object result = Ognl.getValue(expression, actionContext);
// 结果:如果user.name为"John"且user.age为30,则result为"John is 30 years old"
示例2:集合操作
// 假设有一个列表books,需要获取第一个元素的标题
String expression = "books[0].title";
Object result = Ognl.getValue(expression, actionContext);
// 结果:获取列表books的第一个书籍对象的title属性值
示例3:静态字段访问
// 获取Math类中的PI常量值
String expression = "#Math.PI";
Object result = Ognl.getValue(expression, actionContext);
// 结果:PI的值3.***

6.2 OGNL在Struts2中的高级应用

6.2.1 OGNL与ActionContext的交互

在Struts2中,ActionContext是OGNL操作的一个重要对象。OGNL允许我们直接从ActionContext中访问和操作值栈(ValueStack)中的数据,这使得在Struts2中进行数据处理和操作变得非常便捷。

示例4:OGNL与ActionContext的交互
// 在OGNL表达式中访问ActionContext的属性
String expression = "#actionContext['user'].name";
Object result = Ognl.getValue(expression, actionContext);
// 结果:从ActionContext获取user对象的name属性值

6.2.2 OGNL在页面表达和数据处理中的应用

在JSP等视图层中,OGNL同样发挥着重要作用。开发者可以在JSP页面中使用OGNL表达式直接访问和展示Action中的数据,以及进行数据的动态绑定。

示例5:OGNL在JSP页面中的应用
<!-- 假设有一个Action名为MyAction,其ActionContext中包含user对象 -->
<p>Name: ${user.name}</p>
<p>Age: ${user.age}</p>
<p>Full Name: ${user.firstName + ' ' + user.lastName}</p>

表格:OGNL表达式与对应的解释

| OGNL表达式 | 解释 | |-------------|------| | user.name | 访问user对象的name属性 | | user.getName() | 通过get方法访问user对象的name属性 | | #Math.PI | 访问Math类中的PI静态常量 | | books[0].title | 访问books列表中第一个元素的title属性 | | #actionContext['user'].name | 访问ActionContext中的user对象的name属性 | | ${user.name} | 在JSP页面中直接展示user对象的name属性 |

流程图:OGNL表达式解析流程

graph LR
A[OGNL表达式输入] --> B[解析表达式]
B --> C{表达式类型判断}
C -->|属性访问| D[属性访问处理]
C -->|方法调用| E[方法调用处理]
C -->|静态成员访问| F[静态成员访问处理]
C -->|集合操作| G[集合操作处理]
D --> H[返回属性值]
E --> H
F --> H
G --> H
H --> I[OGNL表达式结果输出]

通过本章节的介绍,我们已经对OGNL有了一个全面的理解,并掌握了一些OGNL在Struts2中的高级应用。OGNL不仅简化了Java对象的访问,而且大大提高了Web应用开发的效率。接下来的章节中,我们将探索Struts2的模板技术与插件机制,进一步提升我们的开发技能。

7. Struts2模板技术与插件机制的优势

Struts2框架不仅仅提供了一套完整的MVC实现,还拥有强大的模板技术和插件机制,这些特性极大地增强了Struts2的灵活性和扩展性。本章将深入探讨Struts2中的模板技术以及插件机制的优势和实际应用。

7.1 Freemarker和Velocity模板技术的应用

7.1.1 模板技术的基本概念和优势

模板技术可以将数据与表示逻辑分离,使得页面设计和后端逻辑之间的耦合度大大降低。在Web开发中,模板引擎的作用是将数据模型渲染到特定的视图中。Struts2提供了对多种模板引擎的支持,其中最常用的有Freemarker和Velocity。

Freemarker 是一个Java类库,它用于生成文本输出,它基于模板和指定的数据模型来渲染输出。它的优势在于性能高效、与Web框架解耦以及易于集成。

Velocity 是一个模板引擎,它为Web应用提供了一种模板语言,这些模板在HTML的结构中嵌入了Java代码。Velocity的主要优势是执行效率高,而且语言简洁直观。

7.1.2 Struts2中模板的配置与使用方法

在Struts2中配置和使用模板技术非常简单。首先,需要在项目的 struts.xml 配置文件中指定使用模板技术。

<package name="default" extends="struts-default" namespace="/example">
    <result-types>
        <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
        <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
    </result-types>

    <action name="example" class="com.example.ExampleAction">
        <result name="success" type="freemarker">/success.ftl</result>
    </action>
</package>

在上面的配置中,指定了当 example 动作成功时,使用FreeMarker模板 success.ftl 来渲染结果。

在FreeMarker模板中,你可以通过OGNL访问Action中的属性:

<html>
<head>
    <title>Example Page</title>
</head>
<body>
    <h1>${message}</h1>
</body>
</html>

ExampleAction 类中,我们可以定义如下属性:

public class ExampleAction extends ActionSupport {
    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    // ...
}

7.2 插件机制的优势与应用实践

7.2.1 Struts2插件的工作原理

Struts2的插件机制允许开发者和第三方开发者扩展核心框架的功能。插件可以提供额外的拦截器、结果类型、拦截器栈等。当Struts2应用启动时,它会扫描配置文件中声明的插件,并加载它们。每个插件都可以有自己的配置信息,这样就能在不影响主应用配置的情况下,引入新的功能。

7.2.2 常见插件的使用和自定义插件的方法

Struts2社区提供了许多实用的插件,如 struts2-convention-plugin struts2-spring-plugin 等。使用这些插件能够使开发更加便捷,例如 struts2-convention-plugin 提供了一种约定优于配置的开发方式。

要使用一个Struts2插件,只需要在 struts.xml 中声明该插件即可:

<struts>
    <constant name="struts.convention.action.packages" value="com.example.actions"/>
    <constant name="struts.convention.default.parent.package" value="struts2"/>
    <package name="myapp" extends="struts-default, struts-convention">
        <!-- actions -->
    </package>
</struts>

若要自定义一个插件,需要实现 com.opensymphony.xwork2.plugin.Plugin 接口,然后在插件类中配置必要的拦截器和拦截器栈。

public class MyPlugin implements Plugin {
    public void init(org.apache.struts2.StrutsConstants strutsConstants) throws Exception {
        // 初始化插件逻辑
    }

    public void destroy() {
        // 销毁插件逻辑
    }
}

struts.xml 中声明自定义插件:

<constant name="struts.plugin.myplugin" value="com.example.MyPlugin"/>

通过这种方式,你可以为Struts2添加自定义的拦截器、结果类型等组件,进一步提升应用的灵活性和功能性。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Struts2是一个采用MVC设计模式的Java Web框架,由Apache维护,其核心jar包提供了处理用户请求、业务逻辑、数据传递及结果展示等功能。本文将深入探讨Struts2-jar中的关键组件,包括Action类、Interceptor、Result、ValueStack、OGNL表达式、模板引擎支持、插件机制、ActionContext、配置文件及生命周期管理。了解这些组件的工作原理和配置方法,能够帮助开发者高效构建出结构良好、易于维护的Web应用程序。同时,鉴于Struts2的安全问题,本文也强调了更新和安全的重要性。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 目标检测的定义 目标检测(Object Detection)的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,是计算机视觉领域的核心问题之一。由于各类物体有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具有挑战性的问题。 目标检测任务可分为两个关键的子任务,目标定位和目标分类。首先检测图像中目标的位置(目标定位),然后给出每个目标的具体类别(目标分类)。输出结果是一个边界框(称为Bounding-box,一般形式为(x1,y1,x2,y2),表示框的左上角坐标和右下角坐标),一个置信度分数(Confidence Score),表示边界框中是否包含检测对象的概率和各个类别的概率(首先得到类别概率,经过Softmax可得到类别标签)。 1.1 Two stage方法 目前主流的基于深度学习的目标检测算法主要分为两类:Two stage和One stage。Two stage方法将目标检测过程分为两个阶段。第一个阶段是 Region Proposal 生成阶段,主要用于生成潜在的目标候选框(Bounding-box proposals)。这个阶段通常使用卷积神经网络(CNN)从输入图像中提取特征,然后通过一些技巧(如选择性搜索)来生成候选框。第二个阶段是分类和位置精修阶段,将第一个阶段生成的候选框输入到另一个 CNN 中进行分类,并根据分类结果对候选框的位置进行微调。Two stage 方法的优点是准确度较高,缺点是速度相对较慢。 常见Tow stage目标检测算法有:R-CNN系列、SPPNet等。 1.2 One stage方法 One stage方法直接利用模型提取特征值,并利用这些特征值进行目标的分类和定位,不需要生成Region Proposal。这种方法的优点是速度快,因为省略了Region Proposal生成的过程。One stage方法的缺点是准确度相对较低,因为它没有对潜在的目标进行预先筛选。 常见的One stage目标检测算法有:YOLO系列、SSD系列和RetinaNet等。 2 常见名词解释 2.1 NMS(Non-Maximum Suppression) 目标检测模型一般会给出目标的多个预测边界框,对成百上千的预测边界框都进行调整肯定是不可行的,需要对这些结果先进行一个大体的挑选。NMS称为非极大值抑制,作用是从众多预测边界框中挑选出最具代表性的结果,这样可以加快算法效率,其主要流程如下: 设定一个置信度分数阈值,将置信度分数小于阈值的直接过滤掉 将剩下框的置信度分数从大到小排序,选中值最大的框 遍历其余的框,如果和当前框的重叠面积(IOU)大于设定的阈值(一般为0.7),就将框删除(超过设定阈值,认为两个框的里面的物体属于同一个类别) 从未处理的框中继续选一个置信度分数最大的,重复上述过程,直至所有框处理完毕 2.2 IoU(Intersection over Union) 定义了两个边界框的重叠度,当预测边界框和真实边界框差异很小时,或重叠度很大时,表示模型产生的预测边界框很准确。边界框A、B的IOU计算公式为: 2.3 mAP(mean Average Precision) mAP即均值平均精度,是评估目标检测模型效果的最重要指标,这个值介于0到1之间,且越大越好。mAP是AP(Average Precision)的平均值,那么首先需要了解AP的概念。想要了解AP的概念,还要首先了解目标检测中Precision和Recall的概念。 首先我们设置置信度阈值(Confidence Threshold)和IoU阈值(一般设置为0.5,也会衡量0.75以及0.9的mAP值): 当一个预测边界框被认为是True Positive(TP)时,需要同时满足下面三个条件: Confidence Score > Confidence Threshold 预测类别匹配真实值(Ground truth)的类别 预测边界框的IoU大于设定的IoU阈值 不满足条件2或条件3,则认为是False Positive(FP)。当对应同一个真值有多个预测结果时,只有最高置信度分数的预测结果被认为是True Positive,其余被认为是False Positive。 Precision和Recall的概念如下图所示: Precision表示TP与预测边界框数量的比值 Recall表示TP与真实边界框数量的比值 改变不同的置信度阈值,可以获得多组Precision和Recall,Recall放X轴,Precision放Y轴,可以画出一个Precision-Recall曲线,简称P-R
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值