Struts2

1.Struts2入门

1.1 入门案例

  1. 添加struts2相关依赖
  2. 添加web.xml,加载struts2配置
  3. 编写index.jsp页面
  4. 编写Action控制器
  5. 编写struts.xml文件

1.1.1 添加struts2相关依赖

在pom.xml文件中加入struts2的依赖代码

<dependency>
  <groupId>org.apache.strutsgroupId>
  <artifactId>struts2-coreartifactId>
  <version>2.5.22version>
dependency>

1.1.2 添加web.xml,加载struts2配置


<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <filter>
        <filter-name>struts2filter-name>
        <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilterfilter-class>
    filter>

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

web-app>

1.1.3 编写index.jsp页面

<%--
  Created by IntelliJ IDEA.
  User: ZhuZhengbin
  Date: 2021/4/2
  Time: 12:57
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


1.1.4 编写Action控制器

​ 控制器要去实现Action接口,属性驱动机制的属性名要和表单的name属性一致

package cn.zhengbin.action;

import com.opensymphony.xwork2.Action;

public class HelloAction implements Action {
     

    public String getUsername() {
     
        return username;
    }

    public void setUsername(String username) {
     
        this.username = username;
    }

    /**
     * 定义变量,接受页面的用户名username
     * 要求:属性名必须与input标签的name属性一直
     * 提供getter/setter方法
     */
    private String username;

    @Override
    public String execute() throws Exception {
     
        System.out.println("username:" + username);
        return SUCCESS;
    }
}

1.1.5 编写struts.xml文件





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

        

        <action name="hello" class="cn.zhengbin.action.HelloAction">

            

            <result name="success">/show.jspresult>
        action>
    package>
struts>

1.2 Struts初体验

1.2.1 使用Struts2开发程序的基本步骤

  1. 加载Struts2类库
  2. 配置web.xml文件
  3. 开发视图层页面
  4. 开发控制器层Action
  5. 配置struts.xml文件
  6. 部署、运行项目

1.2.2 Struts2类库

如果用的不是maven项目,必须把这些包全部加到项目中才能用,否则用不了,xxx表示版本号

文件名 说明
struts2-core-xxx.jar Struts2框架的核心类库
xword-core-xxx.jar XWork类库,Struts2的构建基础
ognl-xxx.jar Struts2使用的一种表达式语言类库
freemarker-xxx.jar Struts2的标签模板使用类库
javassist.xxx.GA.jar 对字节码进行处理
commons-fileupload-xxx.jar 文件上传时需要使用
commons-io-xxx.jar Java IO扩展
commons-lang-xxx.jar 包含的一些数据类型的工具类

1.2.3 接受表单数据

定义变量,接受页面的用户名username,要求属性名必须与input标签的name属性一致,必须提供getter/setter方法,省去了request.getParameter()的步骤

/**
 * 定义变量,接受页面的用户名username
 * 要求:属性名必须与input标签的name属性一致
 * 提供getter/setter方法
 */
private String username;

public String getUsername() {
     
    return username;
}

public void setUsername(String username) {
     
    this.username = username;
}

1.2.4 输出结果

在JSP页面中输出结果的方式有两种,分别是:

  1. EL表达式,例如:${username}
  2. struts2标签,例如

注意:

  1. struts2标签不能使用其他表达式,如:在struts2标签中使用EL表达式,会报错
  2. 使用struts2标签输出结果,必须在页面中映入相应的标签库<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>
<body>
<p>用户名:${username}p>
<p>用户名:<s:property value="username" />p>
body>
html>

1.3 Struts2 配置文件(struts.xml)

1.3.1 struts.xml

  1. struts.xml配置文件是struts2框架的核心配置文件,主要负责管理Action
  2. 通常放在WEB-INF/classes目录下,也可以在resource资源目录下,在该目录下的struts.xml文件可以被自动加载
<struts>
    <constant name="" value=""/>
    <package name="" extends="" namespace="">
        <action name="" class="">
            <result name="">result>
        action>
    package>
struts>

1.3.2==< constand>==标签

  1. 配置常量,可以改变Struts2框架的一些行为
  2. name属性表示常量名称,value属性表示常量值

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

1.3.3 ==< package>==标签

  1. 包的作用:简化维护工作,提高重用性
  2. 包可以“继承”已定义的包,并可以添加自己包的配置
  3. name属性位必须且唯一,用于指定包的名称




<struts>
    
    <constant name="struts.enable.DynamicMethodInvocation" value="true"/>
    
    <package name="default" extends="struts-default">
        
        <global-allowed-methods>regex:.*global-allowed-methods>
    package>

    <package name="user1" extends="default" namespace="/">
        <action name="login" class="cn.zhengbin.actions.UserAction">
            <result>/success.jspresult>
        action>
    package>

    <package name="user2" extends="default" namespace="/user">
        <action name="user" class="cn.zhengbin.actions.UserAction">
            <result>/success.jspresult>
        action>
    package>

    <package name="user3" extends="default" namespace="/">
        <action name="*" class="cn.zhengbin.actions.UserAction" method="{1}">
            <result>success.jspresult>
        action>
    package>
struts>

1.3.4 struts配置文件加载顺序

  • struts-default.xml
    • struts2默认配置文件,会自动加载
    • struts-default包在struts-default.xml文件中定义
  • struts-plugin.xml
    • strust2插件使用的配置文件
  • 加载顺序
    • struts-default.xml–>struts-plugin.xml–>struts.xml

1.3.5 拆分配置文件

项目开发中,随着业务功能下新增,struts.xml配置文件的配置也会随之增加,可读性和维护性就会下降,为了增强后期的可维护性,可通过拆分配置文件的方式解决问题,只需要将struts.xml业务模块的配置拆分成若干个struts-xxx.xm文件,最后在struts.xml主配置中通过标签引入即可,代码如下:

<include file="struts-house">include>
<include file="struts-user">include>

1.4 Struts2开发小结

1.4.1 开发Struts2应用的基本环节

  • 确定环境
    • 是否添加了Struts2框架的支持文件
    • 是否配置了Filter
  • 编写视图
  • 功能实现
    • 编写Action类
  • 配置struts.xml文件
  • 部署,运行

1.5 使用Struts2实现用户登录

1.5.1 开发思路

1. 编写login.jsp页面(用于登录)
2. 编写一个登录的Action控制器(LoginAction)
 * 获取登录表单的用户名和密码(属性驱动机制,成员变量,提供getter/setter方法
 * 重写execute()方法
3. 编写struts.xml配置文件

1.5.2 编写登录页面(login1.jsp)

<%--
  Created by IntelliJ IDEA.
  User: ZhuZheng bin
  Date: 2021/4/2
  Time: 12:57
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


1.5.3 编写一个登录的Action控制器(LoginAction)

package cn.zhengbin.action;

import com.opensymphony.xwork2.Action;
/**
* 获取登录表单的用户名和密码(属性驱动机制,成员变量,提供getter/setter方法
* 重写execute()方法
*/
public class LoginAction implements Action {
     

    // 与input标签的name属性一致,提供getter/setter方法
    private String username; // 用户名
    private String password; // 密码

    public String getUsername() {
     
        return username;
    }

    public void setUsername(String username) {
     
        this.username = username;
    }

    public String getPassword() {
     
        return password;
    }

    public void setPassword(String password) {
     
        this.password = password;
    }

    // 重写execute()方法 验证成功返回SUCCESS,失败返回ERROR
    @Override
    public String execute() throws Exception {
     
        return ("admin666".equals(username) && "admin888".equals(password)) ? SUCCESS : ERROR;
    }
}

1.5.4 编写struts.xml配置文件





<struts>
    <package name="default" extends="struts-default" namespace="/">
        
        
        <action name="login" class="cn.zhengbin.action.LoginAction">
            
            <result name="success" type="redirect">/success.jspresult>
            
            <result name="error">/login1.jspresult>
        action>
    package>
struts>

1.6 Action接口

actions是struts2框架的核心,因为它们适用于任何MVC(Model View Controller)框架,每个URL映射到特定的action,其提供处理来自用户的请求所需的处理逻辑

但action还有另外两个重要的功能。首先,action在将数据从请求传递到视图(无论是JSP还是其他类型的结果)方面起着重要作用。第二,action必须协助框架确定哪个结果应该是呈现在响应请求的视图中。

struts2中actions的唯一要求是必须有一个无参数方法返回String或Result对象,并且必须是POJO(类)。如果没有指定no-argument无参方法,则默认是使用execute()方法。

Action接口源码:

public interface Action {
     
    String SUCCESS = "success"; // 成功
    String NONE = "none";       // 无
    String ERROR = "error";     // 错误
    String INPUT = "input";     // 未输入数据
    String LOGIN = "login";		// 登录

    String execute() throws Exception;
}

1.6 Struts2访问Servlet API

在struts中使用Servlet提供的方法的方式有两种,分别是:

1. 与Servlet API 解耦 的访问方式
2. 与Servlet API 耦合 的访问方式

解耦:组件框架之间相互独立,能够独自正常运行,不进行依赖操作

耦合:组件框架之间相互依赖,不能够独自正常运行,缺少其中一个组件则可能无法正常运行

1.6.1 与Servlet API 解耦 的访问方式

//            使用解耦的方式获取session,将当前登录的用户信息保存到session
            Map<String, Object> session = ActionContext.getContext().getSession();
//            将当前登录的用户信息保存到session
            session.put("loginUser",username);

1.6.2 与Servlet API 耦合 的访问方式

javax.servlet.ServletContext servletContext = ServletActionContext.getServletContext();

1.7 数据校验

1.7.1 概述

1.7.2 数据校验步骤

  1. 控制器Action继承 ActionSupport
  2. 控制器Action重写 validate() 方法
  3. 在页面中使用 ==< s:fielderror>==标签显示验证信息
  4. 在struts.xml文件的action标签中配置input返回结果

1.7.3 实现数据校验

Actionsupport这个工具类在实现了Action接口的基础上还定义了一个validate()方法,重写该方法,它会在execute()方法之前执行,如校验失败,会转入input处,必须在配置该Action时配置input属性。

1.7.3.1 控制器Action继承 ActionSupport

package cn.zhengbin.action;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;


public class LoginAction extends ActionSupport {
     

    private String username;
    private String password;

    @Override
    public String execute() throws Exception {
     
//        比较用户名和密码是否一致
        if (username.equals("admin666") && password.equals("admin888")) {
     
            Map<String, Object> session = ActionContext.getContext().getSession();
            session.put("username", username);
            return SUCCESS;
        }
        return ERROR;
    }

    public String getUsername() {
     
        return username;
    }

    public void setUsername(String username) {
     
        this.username = username;
    }

    public String getPassword() {
     
        return password;
    }

    public void setPassword(String password) {
     
        this.password = password;
    }

}

1.7.3.2 控制器Action重写==validate()==方法

@Override
public void validate() {
     
    if (StringUtils.isEmpty(username)) {
     
        /*
             参数1:key 自定义
             参数2:value
         */
        addFieldError("userName", "用户名不能为空");
    }
    if (StringUtils.isEmpty(password)) {
     
        addFieldError("password", "密码不能为空");
    }
}

1.7.3.3 在页面中使用 < s:fielderror> 标签显示验证信息

<%@ taglib prefix="s" uri="/struts-tags" %>
<%--
  Created by IntelliJ IDEA.
  User: ZhuZheng bin
  Date: 2021/4/2
  Time: 12:57
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


1.7.3.4 在struts.xml文件的action标签中配置input返回结果

<action name="login" class="cn.zhengbin.action.LoginAction">
    
    <result name="success" type="redirect">/success.jspresult>
    
    <result name="error">/login1.jspresult>
    
    <result name="input">/login1.jspresult>
action>

1.7.4 基于的XML配置方式的输入校验

Struts2常用内置校验器

内置校验器类型 说明
required 不允许为空。用于非字符串类型
requiredstring 不允许为空。仅用于非字符串类型
int 必须是合法的int类型
long 必须是合法的long类型
double 必须是合法的double类型
date 必须是合法的日期类型
email 必须是合法的email类型
url 必须是合法的url类型
stringlength 判断字符串的长度是否合法
regex 使用正则表达式进行校验

1.7.5 案例:使用XML的方式校验用户登录

任务实现步骤

  • 编写Action类
  • 配置struts.xml
  • 编写login.jsp
  • 编写Action-actionName-validation.xml

技巧:关于校验配置xml文件的两点注意事项

  • 校验配置xml文件要与被校验的Action在同一个包中。
  • 校验配置文件的名称应该为:被校验的Action类名-struts.xml文件中的action的name属性值-validation.xml
  • 注意:“-validation.xml”部分是固定不变的

1.7.5.1 编写Action类

package cn.zhengbin.action;

import com.opensymphony.xwork2.ActionSupport;

public class ValidateLoginAction extends ActionSupport {
     

    private String account;
    private String password;


    @Override
    public String execute() throws Exception {
     
        return SUCCESS;
    }

    //	@Override
    //	public void validate() {
     
    //		if(account.length() < 6) {
     
    //			addFieldError("account", "用户名长度不能小于六位");
    //		}
    //		if(password.length() < 6) {
     
    //			addFieldError("password", "用户密码长度不能小于六位");
    //		}
    //		if(account.contains(" ")) {
     
    //			addFieldError("account", "用户名中不能出现空格");
    //		}
    //		if(password.contains(" ")) {
     
    //			addFieldError("password", "密码中不能出现空格");
    //		}
    //		if(StringUtils.isEmpty(account)) {
     
    //			addFieldError("account", "请输入用户名");
    //		}
    //		if(StringUtils.isEmpty(password)) {
     
    //			addFieldError("password", "请输入密码");
    //		}
    //	}

    public String getAccount() {
     
        return account;
    }

    public void setAccount(String account) {
     
        this.account = account;
    }

    public String getPassword() {
     
        return password;
    }

    public void setPassword(String password) {
     
        this.password = password;
    }
}

1.7.5.2 配置struts.xml



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

	<package name="login" namespace="/" extends="struts-default">
		<action name="fieldValidate_login" class="cn.zhengbin.action.ValidateLoginAction">
			<result name="input">/login.jspresult>
			<result name="success">/main.jspresult>
		action>
	package>
struts>   

1.7.5.3 编写login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%@taglib  prefix="s" uri="/struts-tags"%>


      
    用户登陆
    
  
  
  
      

1.7.5.4 小结

  • struts2提供了两种方式的输入校验,一种基于手动的输入校验。一种是基于配置方式的输入校验
  • 如果需要对Action类中的execute()方法进行输入定义,需要定义validate()方法
  • 如果需要对Action类红的Xxx()方法进行输入定义,需要定义validateXxx()方法
  • 对于校验配置文,需要注意以下几点
    • 被校验的Action要与该Action的校验配置文件在同一个包下
    • 配置校验文件的名称应该为Action类名-struts.xml文件中的action的name属性值-validation.xml。后面高亮的内容是固定不变的

1.8 Struts2标签

1.8.1 概述

struts2有丰富的tag(标签)可以使用,Struts2的标签库(taglib),如能灵活运用,则能大大提高开发效率,struts2标签分为UI标签和通用标签,使用前需要引入struts2的标签库

<%@ taglib prefix="s" uri="/struts-tags" %>

1.8.2 UI标签

UI标签分为:表单标签,非表单标签,Ajax标签

1.8.2.1 常用表单标签

标签 说明
< s:form>< /s:form> 表单标签
< s:textfield>< /s:textfield> 文本输入框
< s:password>< /s:password> 密码输入框
< s:textarea>< /s:textarea> 文本域输入框
< s:radio>< /s:radio> 单选按钮
< s:checkbox>< /s:checkbox> 多选框
< s:submit>< /s:submit> 提交标签
< s:reset>< /s:reset> 重置标签
< s:hidden>< /s:hidden> 隐藏域标签

1.8.2.2 常用表单标签注意事项

使用struts2表单标签时会struts2会加入一些html结构,会破坏页面结构,在struts.xml的struts标签类加入如下配置:


<constant name="struts.ui.theme" value="simple"/>

1.8.2.3 非表单标签

标签 说明
< s:actionerror>< /s:actionerror> 显示Action错误
< s:actionmessage>< /s:actionmessage> 显示Action消息
< s:fielderror>< /s:fielderror> 显示字段错误

1.8.3 通用标签

名称 标签 说明
条件标签 < s:if>< /s:if> 根据表达式的值,判断要执行的内容
< s:elseif>< /s:elseif>
< s:else>< /s:else>
迭代 < s:iterator>< /s:iterator> 用于遍历集合

1.9 综合案例——查询用户列表

1.9.1 编写User实体类

package cn.zhengbin.entity;

public class User {
     

    private Integer id;
    private String username;
    private String sex;
    private String phone;

    public User(Integer id, String username, String sex, String phone) {
     
        this.id = id;
        this.username = username;
        this.sex = sex;
        this.phone = phone;
    }

    public Integer getId() {
     
        return id;
    }

    public void setId(Integer id) {
     
        this.id = id;
    }

    public String getUsername() {
     
        return username;
    }

    public void setUsername(String username) {
     
        this.username = username;
    }

    public String getSex() {
     
        return sex;
    }

    public void setSex(String sex) {
     
        this.sex = sex;
    }

    public String getPhone() {
     
        return phone;
    }

    public void setPhone(String phone) {
     
        this.phone = phone;
    }
}

1.9.2 编写UserAction控制类

注意:该控制器继承ActionSupport自定义userlist()方法

package cn.zhengbin.action;

import cn.zhengbin.entity.User;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

import java.util.ArrayList;
import java.util.List;

public class UserAction extends ActionSupport {
     
    // 定义成员变量,保存用户列表
    // 值栈:类似于request.getParameter()和 xxx.getParameter()的组合
    List<User> userList;

    public String userlist() throws Exception {
     
        userList = new ArrayList<>();
        userList.add(new User(1, "zhangsan", "男", "123456"));
        userList.add(new User(2, "lisi", "女", "456798"));
        userList.add(new User(3, "wangwu", "女", "123789"));
        userList.add(new User(4, "zhaoliu", "男", "147258"));
        return SUCCESS;
    }

    public List<User> getUserList() {
     
        return userList;
    }

    public void setUserList(List<User> userList) {
     
        this.userList = userList;
    }
}

1.9.3 编写struts.xml文件

注意:由于控制器没有重写execute()方法,而是自定义了userlist()方法,所以需要在标签中通过method属性指定方法名称


<action name="findUserList" class="cn.zhengbin.action.UserAction" method="userlist">
    
    <result>/userList.jspresult>
action>

1.9.4 编写userList.jsp页面

<%@ taglib prefix="s" uri="/struts-tags" %>
<%--
  Created by IntelliJ IDEA.
  User: ZhuZheng bin
  Date: 2021/4/2
  Time: 21:22
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>



    
    
    
    Document



    <%--  循环标签,value属性:循环的集合或数组  --%>

    
        
编号 姓名 性别 电话

2 Struts2配置

2.1 Action配置

  1. Action控制器由两部分组成,分别是:
    • 核心控制器(Filter):用于拦截用户请求,对请求进行处理
    • 业务控制器(Action):调用相应模型Model类实现业务处理,返回结果
  2. 自定义的Action控制器可以实现Action接口或继承ActionSupport类

2.1.1 Action的作用

  1. 封装工作单元
  2. 数据转移的场所
  3. 返回结果字符串

2.2.1 访问Action的三种方式

2.2.1.1 method属性访问Action

通过method属性实现在Action中不同方法的调用,该方法可以避免动态方法调用的隐患,但会导致大量的Action配置

<action name="login" class="cn.zhengbin.actions.UserAction" method="login">
    ...
action>

2.2.1.2 动态方法访问Action

  • 作用:减少Action数量
  • 使用:actionName!methodName.action
  • 禁用:将常量struts.enable.DynamicMethodInvocation设置为false

使用动态方法调用,需要开启动态方法调用配置,以及设置白名单(struts2.5版本开始需要设置白名单)

第一步:开启动态方法调用

<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
第二步:在< package>标签内设置白名单

<global-allowed-methods>regex:.*global-allowed-methods>

完整配置代码如下:





<struts>
    
    <constant name="struts.enable.DynamicMethodInvocation" value="true"/>
    
    <package name="default" extends="struts-default">
        
        <global-allowed-methods>regex:.*global-allowed-methods>
    package>

    <package name="user2" extends="default" namespace="/user">
        <action name="user" class="cn.zhengbin.actions.UserAction">
            <result>/success.jspresult>
        action>
    package>
struts>

2.3.1 配置默认的Action

当struts2没有Action匹配请求时,默认Action将被执行

通过====元素配置默认Action


<package name="default" extends="struts-default">
    
    <default-action-ref name="defaultAction" />
    
    <global-allowed-methods>regex:.*global-allowed-methods>
    
    <action name="defaultAction">
        <result>/default.jspresult>
    action>
package>

2.2 Result配置

2.2.1 常用的结果类型(type)

  • dispatcher类型:默认结果类型,后台使用RequestDispatcher请求转发

  • redirect类型:后台使用的==sendRedirect()==将请求重定向到指定的URL

  • redirectAction类型:主要用于重定向到Action,控制器跳控制器

<package name="user1" extends="default" namespace="/">
    <action name="login" class="cn.zhengbin.actions.UserAction" method="login">
        
        <result type="dispatcher">/success.jspresult>
    action>
    <action name="login" class="cn.zhengbin.actions.UserAction" method="register">
        
        <result type="redirect">/success.jspresult>
    action>
    <action name="login" class="cn.zhengbin.actions.UserAction" method="update">
        
        <result type="redirectAction">user/user!login.actionresult>
    action>
package>

2.2.2 全局结果配置

概述:通过标签配置全局结果,注意标签的顺序。

作用:定义公共result返回页面,为了减少====标签配置的冗余

注意:当全局结果与局部结果配置冲突时,有限使用局部结果


<package name="default" extends="struts-default">
    
    <default-action-ref name="defaultAction"/>
    
    <global-results>
        <result name="login">/login.jspresult>
        <result name="error">/error.jspresult>
    global-results>
    
    <global-allowed-methods>regex:.*global-allowed-methods>
    
    <action name="defaultAction">
        <result>/default.jspresult>
    action>
package>

2.3 Struts2封装获取表单数据方式

在struts2获取表单数据或提交路径的参数值的方式有4种,分别是

  • 原始Servlet方式
  • 属性封装
  • 表达式封装
  • 模型驱动封装

2.3.1 原始Servlet方式

使用Servlet的方式获取页面的数据,需要加入Servlet相关依赖

<dependency>
  <groupId>javax.servletgroupId>
  <artifactId>javax.servlet-apiartifactId>
  <version>4.0.1version>
  <scope>providedscope>
dependency>

使用原始Servlet封装的不足之处

  1. 获取到所有的数据都是字符串类型,需要类型转换
  2. 获取数据的代码复杂,啰嗦
package cn.zhengbin.actions;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;
import javax.servlet.http.HttpServletRequest;

/**
* 原始封装:原生Servlet方式,获取到所有的数据都是String类型,需要类型转换
*/
public class UserAction1 extends ActionSupport {
     
    public String regsiter(){
     
        //获取Servlet对象
        HttpServletRequest request = ServletActionContext.getRequest();
        //获取用户名
        String userName = request.getParameter("userName");
        String password = request.getParameter("password");
        return SUCCESS;
    }
}

2.3.2 属性封装

2.3.2.1 概述

在类中定义成员变量,提供get、set方法

注意:必须保证成员变量名称与input表单中的name属性值、提交路径中的参数名称一致

该方法获取数据的方式比较简单,但会造成属性过多,Action控制器代码冗余

2.3.2.2 控制器Action

package cn.zhengbin.actions;

import com.opensymphony.xwork2.ActionSupport;

public class UserAction2 extends ActionSupport {
     

    //    必须与input标签的name属性值一致,或者与提交路径的参数名称一致
    private String userName;
    private String password;
    private Integer sex;
    private Integer age;
    private String phone;

    public String register() {
     
        System.out.println("用户名:" + userName);
        System.out.println("密码:" + password);
        System.out.println("性别:" + sex);
        System.out.println("年龄:" + age);
        System.out.println("电话:" + phone);
        return SUCCESS;
    }

    public String getUserName() {
     
        return userName;
    }

    public void setUserName(String userName) {
     
        this.userName = userName;
    }

    public String getPassword() {
     
        return password;
    }

    public void setPassword(String password) {
     
        this.password = password;
    }

    public Integer getSex() {
     
        return sex;
    }

    public void setSex(Integer sex) {
     
        this.sex = sex;
    }

    public Integer getAge() {
     
        return age;
    }

    public void setAge(Integer age) {
     
        this.age = age;
    }

    public String getPhone() {
     
        return phone;
    }

    public void setPhone(String phone) {
     
        this.phone = phone;
    }
}

2.3.3 模型驱动封装

2.3.3.1 概述

使用模型驱动封装步骤如下

  • 第一步:控制器实现ModelDriven接口
  • 第二步:重写getModel()方法

2.3.3.2 User

package cn.zhengbin.entity;

public class User {
     
    private String userName;
    private String password;
    private Integer sex;
    private Integer age;
    private String phone;

    public String getUserName() {
     
        return userName;
    }

    public void setUserName(String userName) {
     
        this.userName = userName;
    }

    public String getPassword() {
     
        return password;
    }

    public void setPassword(String password) {
     
        this.password = password;
    }

    public Integer getSex() {
     
        return sex;
    }

    public void setSex(Integer sex) {
     
        this.sex = sex;
    }

    public Integer getAge() {
     
        return age;
    }

    public void setAge(Integer age) {
     
        this.age = age;
    }

    public String getPhone() {
     
        return phone;
    }

    public void setPhone(String phone) {
     
        this.phone = phone;
    }

    @Override
    public String toString() {
     
        return "User{" +
                "userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                ", sex=" + sex +
                ", age=" + age +
                ", phone='" + phone + '\'' +
                '}';
    }
}

2.3.3.3 控制器Action代码

package cn.zhengbin.actions;

import cn.zhengbin.entity.User;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

/**
 * 模型驱动封装
 */
public class UserAction3 extends ActionSupport implements ModelDriven<User> {
     
    
    //    创建用户对象
    private User user = new User();

    @Override
    public User getModel() {
     
        return user;
    }

    /**
     * 注册
     */
    public String register(){
     
        System.out.println(user);
        return SUCCESS;
    }
}

2.3.3.4 页面代码

<%--
  Created by IntelliJ IDEA.
  User: Zhu Zhengbin
  Date: 2021/4/7
  Time: 19:21
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>



    
    
    
    Document


2.3.3.5 注意

  1. input标签的name属性值、提交路径的参数名称必须与实体类的属性名相同(严格区分大小写),控制器不需要提供模型对象的get、set方法
  2. 模型驱动封装与属性封装一起使用时,同名优先使用模型驱动封装,属性封装无法获取数据

2.3.4 表达式封装

2.3.4.1 概述

使用表达式封装的方法获取表单数据,步骤如下:

  • 第一步:在控制器中定义类类型的成员变量,提供get、set方法。如:private User user
  • 第二部:页面使用对象名.实体类属性名,如:

2.3.4.2 控制器Action

<%--
  Created by IntelliJ IDEA.
  User: Zhu Zhengbin
  Date: 2021/4/7
  Time: 19:31
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>



    
    
    
    用户注册


2.3.5 比较表达式封装和模型驱动封装

2.3.5.1 公共点

​ 使用表达式封装和模型驱动封装都可以把数据封装到实体类对象里面

2.3.5.2 不同点

  1. 使用模型驱动只能把数据封装到一个实体类对象里面

    注意:在一个action里面不能使用模型驱动把数据封装到不同的实体类对象里面

    1. 使用表达式封装可以把数据封装到不同的实体类对象里面

1.Struts2拦截器

1.1 基于类范围的连接器的自定义和使用

  • Struts2连接器的体系结构
  • Struts2内建连接器
  • 自定义基于类范围的连接器
  • 案例:通过自定义连接器实现日志记录

1.2 任务实现思路

如何自定义和使用拦截器?

  • 编写拦截器组件类,该类可以实现Intereptor接口,或者继承AbstractInterceptor,MethodFilterInteceptor
  • 声明自定义的拦截器组件类
<interceptors>
			<interceptor name="show" class="cn.zhengbin.interceptor.MyInterceptor" />
interceptors>
  • 开启动态方法调用
<action name="message" class="cn.zhengbin.action.ValidateLoginAction" method="message">
			<result name="success">/message.jspresult>
			<interceptor-ref name="show" />
    
			<interceptor-ref name="defaultStack" />
action>

使用自定义的拦截器组件类药注意的事项:

  • 当在< action>元素添加了< interceptor-ref>引用后,框架不会再调用defaultStack拦截器栈,这样会破坏框架的功能
  • 因此,需要将defaultStack显示引用一下
<interceptor-ref name="defaultStack" />

1.2.1 编写拦截器组件类MyInterceptor

package cn.zhengbin.interceptor;

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

public class MyInterceptor extends AbstractInterceptor {
     

	@Override
	public String intercept(ActionInvocation invoke) throws Exception {
     
		System.out.println("页面展示之前");

		String result = invoke.invoke();
		System.out.println("页面展示完成");
		
		System.out.println("页面展示之后");

		return result;
	}

}

1.2.2 声明自定义的拦截器组件类



<struts>
	
	<constant name="struts.enable.DynamicMethodInvocation" value="true" />
	<package name="login" namespace="/" extends="struts-default">
		<interceptors>
			<interceptor name="show" class="cn.zhengbin.interceptor.MyInterceptor" />
		interceptors>
		<action name="fieldValidate_login" class="cn.zhengbin.action.ValidateLoginAction">
			<result name="input">/login.jspresult>
			<result name="success">/main.jspresult>
		action>
		<action name="message" class="cn.zhengbin.action.ValidateLoginAction"
			method="message">
			<result name="success">/message.jspresult>
			<interceptor-ref name="show" />
			
			<interceptor-ref name="defaultStack" />
		action>
	package>
struts>   

1.2.3 编写message.jsp页面

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



  
    My JSP 'message.jsp' starting page

	
	
	    
	
	
	]
	

  
  
  
    

《观沧海》
曹操
东临碣石,以观沧海
水何澹澹,山岛竦峙。
树木丛生,百草丰茂。
秋风萧瑟,洪波涌起。
日月之行,若出其中。
星汉灿烂,若出其里。
幸甚至哉,歌以咏志。

3. OGNL

3.1 OGNL简介

3.1.1 概念

  • 什么是OGNL
    • Object Graph Navigation Language
    • 对象图的导航语言
    • 开源项目,取代页面中的Java脚本,简化数据访问
    • 和EL同属于表达式语言,但功能更为强大

3.1.2 作用

  • OGNL在struts2中做的两件事

    • 表达式语言

      将表单或struts2标签与特定的Java数据绑定起来,用来将数据移入,移除框架

    • 类型转换

      数据进入和流出框架,在页面数据的字符串类型和Java数据类型之间进行转换

3.2 OGNL在框架中的应用

  • OGNL融入struts2
    • 数据流入
    • 数据流出

3.3 值栈与OGNL

  • 值栈(ValueStack)
    • 由struts2框架创建的存储区域,具有栈的特点
    • Action的实例会被存到值栈中
  • OGNL访问值栈
    • 按照从上到下的顺序
    • 靠近栈顶的同名属性会被读取

3.4 类型转换

3.4.1 为什么要类型转换

  • 在基于HTTP协议的Web应用中

    • 客户端请求的所有内容都以文本编码的方式传输到服务器端
    • 服务器端的编程语言却有着丰富的数据类型
  • Servlet中,类型转换工作由开发者自己完成

    String agestr = request.getParameter("age");
    int age = Integer.parseInt(agestr);
    

3.4.2 内置转换器

3.4.2.1 简介

内置类型转换器 说 明
String 将int、long、double、boolean、String类型的数组或者java.util.Date类型转换为字符串
boolean/Boolean 在字符串和布尔值之间进行转换
char/Character 在字符串和字符之间进行转换
int/Integer、float/Float、long/Long、double/Double 在字符串和数值型数据之间进行转换
Date 在字符串和日期类型之间进行转换。具体输入输出格式与当前Locale相关
数组与集合 在字符串数组和数组对象、集合对象之间进行转换

3.4.2.2 原始类型与包装类

  • 原始类型与包装类型

你可能感兴趣的:(笔记,java,struts2)