structs2框架学习一(启动过程和各种配置)

本文详细介绍了Struts2框架的启动过程,包括自定义struts.xml配置、web.xml中配置核心过滤器、项目启动步骤。同时,探讨了action的三种使用方式、配置中的统配、常量配置以及全局视图和默认配置。此外,还讲解了属性注入、数据共享的三种方法、请求数据封装和自定义类型转换的实现,提供了丰富的代码示例和实践指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.自定义的struts.xml(开发时频繁使用)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
	<!--
	package:代表一个包,用于管理action ,一个包下不能有同名action
	name:包名,在一个项目中不能有同名的包,一个项目中一个模块一个包或者小项目中前后台分别一个包
	extents:继承,类似于类的继承,如果一个包继承另一个包,那么会把父包的功能继承下来,(我们写的struts.xml中包必须继承默认包struts-default)
	namespace;名称空间,区分不同包的访问路径,默认为”/“
		用户访问action路径索索规则:
		若输入:http://localhost:8080/项目名称/user/a/b/c/login.action
		会先搜索:http://localhost:8080/项目名称/user/a/b/c/login.action若没有
		会继续搜索:http://localhost:8080/项目名称/user/a/b/login.action若没有
		会搜索:http://localhost:8080/项目名称/user/a/login.action知道找到匹配项
	abstract:用于表示当前包是否抽象,若为抽象则不能放入action子标签(若包中不做具体逻辑业务,如只是声明拦截器等那就可以设为抽象包)
	-->
	<package name="xxx" extends="struts-default" namespace="/name" abstract="true">
		<!--
		配置action:http://localhost:8080/项目名称/login.action
		1.
			name:action的名称,用于访问此antion的路径
			class:action业务对象的类名(包名+类名),struts2使用反射构造Action对象
			method:执行的业务方法,默认为execute
		2.result标签的配置
			name:视图的标记,在一个action中名称不要重复
			type:跳转类型
				redirect:重定向
				dispatcher:转发
				redirectAction:重定向到action
				chain:转发到action,可以在不同action中用request共享数据
					ServletActionContext.getRequest().setAttribute("","");放入
				stream:用于下载文件的时候
				文本内容:跳转的页面或者antion
		-->
		<action name="login" class="com.study.action.LoginAction" >
			<result  name="success" type="redirect">/index.jsp</result>
		</action>
	</package>
</struts>

注意:structs.xml中的package各个模块可以分出来放入不同的.xml文件中,只需要在主struts.xml中加入<include file="包名/xxx.xml"></include>即可(注:若两个package中出现完全相同的action则先导入(include)的先执行)

二.web.xml中配置启动struts2核心过滤器

<filter>
        <filter-name>StrutsPrepareAndExecuteFilter</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>StrutsPrepareAndExecuteFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

三.项目启动过程

1)创建核心过滤器对象
2)执行过滤器的init方法依次读取三个xml文件
struts-default:默认配置文件
struts-plugin:插件配置文件(如文件io等)
struts:自己写的业务配置
3)在内存中查询相应的action配置,得到class内容,创建action对象、
5)读取action中的method内容,执行action对象对应的方法

四.struts2中action使用的三种方式

1.直接写public class UserAction{} 不实现任何接口和继承任何类
缺点:没有规则和统一规范,里面的方法随意写
2.实现Action类public class LoginAction implements Action{}
优点:有默认方法execute+一些常用的视图标记

String SUCCESS = "success";
    String NONE = "none";
    String ERROR = "error";
    String INPUT = "input";
    input视图可以在页面打印错误信息
    例如:使用<%@ taglib prefix="s" uri="/struts-tags" %>
				<s:fielderror></s:fielderror>就可以在页面打印错误信息
    String LOGIN = "login";

3.(推荐使用)继承ActionSupport类public class UserAction extends ActionSupport{}
优点:默认方法execute+提供了常用的视图标记+数据校验功能

五.action配置中的统配

<!--
		一个模块中的一个方法都需要一个action太浪费资源
		我们可以使用统配功能(首先约定名称一致):建议使用
			*:表示路径统配符。使用统配符的内容  {1}表示匹配第一个*的实际内容
		我们也可以使用动态方法调用(六中有动态方法调用的开启,默认开启)
			使用方法:用user.action访问时可以直接用user!方法名.action调用方法
			缺点:安全性问题,会暴露所有的方法:不建议使用
		-->
		<action name="user_*" class="com.study.action.UserAction" method="{1}">
			<result name="{1}" type="dispatcher">/{1}.jsp</result>
		</action>
		<!--
		多模块使用一个action
		约定:第一个*代表模块第二个代表方法
		-->
		<action name="*_*" class="com.study.action.{1}Action" method="{2}">
			<result name="{2}">/{1}/{2}.jsp</result>
		</action>

六.常量配置

指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法 和freemarker 、velocity的输出 
    <constant name="struts.i18n.encoding" value="UTF-8"/>
    自定义后缀修改常量 
    <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" />
    该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性
    为 false
    <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
    上传文件的大小限制 
    <constant name="struts.multipart.maxSize" value=“10701096"/>

例子1:
<!--修改default.properties的默认常量--> <!-- 修改action默认后缀名(规则:一个逗号(,)一个规则) 修改前访问login.action 修改后访问login.do --> <constant name="struts.action.extension" value="action,do,"></constant>

七.全局视图配置 和默认配置

1.全局配置

局部的会覆盖全局的配置

<global-results>
			<result  name="success" type="redirect">/index.jsp</result>
</global-results>

2.默认配置

<!--
		默认配置:(全部默认的action,专门用于转发(不能用重定向)到web-inf下的页面)
		action中
			name:必须填
			class:可选 默认为ActionSupport 该类继承于struts-default
			method:默认execute
		result中
			name:可选  默认为success
			type:可选  默认为dispatcher
		-->
		<action name="register">
			<result>/WEB-INF/login.jsp</result>
		</action>

八.属性注入

模拟文件上传
UploadAction类:

package com.study.action;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.io.FileUtils;
import java.io.File;
/**
 * @author: Demon
 * @date: 2019/1/26
 * @time: 15:36
 * Description:模拟文件上传(属性注入)
 */
public class UploadAction extends ActionSupport {
    private String path;

    public void setPath(String path) {
        this.path = path;
    }

    public String update() throws Exception {
        //获取文件
        File file = new File("e:/1.jpg");
        System.out.println(path);
        //文件上传至服务器
        FileUtils.copyFile(file, new File(path + "/img"));
        return SUCCESS;
    }
}

struts.xml文件配置:

<!--属性注入-->
		<action name="ioc" class="com.study.action.UploadAction" method="update">
			<result name="success">/success.jsp</result>
			<!--
			属性注入:param
				name:UploadAction中setter方法名
			-->
			<param name="path">e:/img/</param>
		</action>

九.数据共享三种方法(struts2提供的域对象的使用)

第一种(若单纯存储数据不推荐,若用到域对象中除了共享数据外的其他方法就必须使用)

ServletActionContext对象:可以在struts2的action中使用域对象
特点:依赖servlet原生的api

HttpServletRequest request= ServletActionContext.getRequest();

第二种(Action对象方法比较少时可以用)

ActionContext对象(拦截器创建的方法):action的上下文对象,提供了操作不同域对象数据的map集合
特点:不依赖servlet原生的api,只能在某个方法中用

		ActionContext actionContext=ActionContext.getContext();
        //得到request域的map集合
        Map<String ,Object> requestMap=actionContext.getContextMap();
        requestMap.put("list",list);
        //得到session
        Map<String ,Object> sessionMap=actionContext.getSession();
        sessionMap.put("list",list);
         //得到context域
        Map<String ,Object> contextMap=actionContext.getApplication();
        contextMap.put("list",list);

第三种(推荐使用)

通过struts提供的接口(RequestAware,SessionAware,ApplicationAware )注入到Action中
特点:不依赖servlet原生的api,可以在Action类中的所有方法中共享

public class Test extends ActionSupport implements RequestAware,SessionAware,ApplicationAware {
    private Map<String, Object> contextMap;
    private Map<String, Object> requestMap;
    private Map<String, Object> sessionMap;

    @Override
    public void setApplication(Map<String, Object> map) {
        this.contextMap = map;
    }

    @Override
    public void setRequest(Map<String, Object> map) {
        this.requestMap = map;
    }

    @Override
    public void setSession(Map<String, Object> map) {
        this.requestMap = map;
    }

    //放数据
    public String test() {
        contextMap.put("list", list);
        requestMap.put("list", list);
        sessionMap.put("list", list);
        return null;
    }
}

十.请求数据封装

实现原理是依靠struts-default.xml中的拦截器(类似于过滤器,拦截器只对antion起作用)实现的,其中<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>实现请求参数的封装

第一种方式:直接赋值给简单的参数

代码示例
页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/data/user_get.action">
名字:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
性别:<input type="radio" name="sex" value="男"/>男
        <input type="radio" name="sex" value="女"/>女
爱好:<input type="checkbox" name="hobby" value="抽烟">抽烟
    <input type="checkbox" name="hobby" value="喝酒">喝酒
    <input type="checkbox" name="hobby" value="烫头">烫头<br/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

接收类UserAction:

public class UserAction extends ActionSupport{
    private String userName;
    private String password;
    private String sex;
    private String[] hobby;
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public void setHobby(String[] hobby) {
        this.hobby = hobby;
    }
    public String get(){
        System.out.println(userName);
        System.out.println(password);
        System.out.println(sex);
        System.out.println(hobby);
        return SUCCESS;
    }
}

第二种方式:直接赋值给javabean对象

注意:这里需要在表单jsp页面提交时name属性应该为对象名.属性的getter方法名
代码示例
页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/data/user_get.action">
名字:<input type="text" name="user.userName"/><br/>
密码:<input type="password" name="user.password"/><br/>
性别:<input type="radio" name="user.sex" value="男"/>男
        <input type="radio" name="user.sex" value="女"/>女
爱好:<input type="checkbox" name="user.hobby" value="抽烟">抽烟
    <input type="checkbox" name="user.hobby" value="喝酒">喝酒
    <input type="checkbox" name="user.hobby" value="烫头">烫头<br/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

接收类UserAction:

package com.study.data;
import com.opensymphony.xwork2.ActionSupport;
import com.study.bean.User;
/**
 * @author: Demon
 * @date: 2019/1/26
 * @time: 17:13
 * Description:
 */
public class UserAction extends ActionSupport{
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
    public String get(){
        System.out.println(user);
        return SUCCESS;
    }

javabean:User类这里略

十一.自定义类型转换继承StrutsTypeConverter

自定义日期的类型转换

MyDateConverter:类

package com.study.converter;
import org.apache.struts2.util.StrutsTypeConverter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * @author: Demon
 * @date: 2019/1/26
 * @time: 19:53
 * Description:自定义日期转换器
 */
public class MyDateConverter extends StrutsTypeConverter{
    SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy/MM/dd");
    /**
     *从页面到服务器的类型转换
     * map:值栈上下文对象
     * strings:从页面传递过来的参数值
     * aClass:转换到的类型 String-》java.util.Date
     */
    @Override
    public Object convertFromString(Map map, String[] strings, Class aClass) {
        try {
            //判断values是否为空
            if(strings==null||strings.length==0){
                return null;
            }
            Date[] dates=new Date[strings.length];
            //取出数据进行转换
            for(int i=0;i<dates.length;i++){
                Date date=simpleDateFormat.parse(strings[i]);
                dates[i]=date;
            }
            return dates;
        } catch (ParseException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    @Override
    public String convertToString(Map map, Object o) {
        return null;
    }
}

与struts2绑定才能使用:
1)方式一:局部绑定(只能绑定一个)
建立一个Action的文件名-conversion.properties
一定和绑定的Action放在同一个目录下
例如:
UserAction-conversion.properties与UserAction在同一目录下
properties中写user.birth对应自己定义的转换器(如:MyDateConverter )的全名(包名+类名)
2)方式二:全局绑定(绑定整个项目的action)
建立一个xwork-conversion.properties(名称不能改)
放在src目录下
例如:
properties写java.util.Date对应自己定义的转换器(如:MyDateConverter )的全名(包名+类名)

抗遗忘最好的方法就是记下来
未完待续。。。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值