Java网课基础笔记(30)19-08-12

 

struts2执行流程

1. 执行的流程

  • 编写的页面,点击超链接,请求提交到服务器端。
  • 请求会先经过Struts2的核心过滤器(StrutsPrepareAndExecuteFilter)
  • 过滤器的功能是完成了一部分代码功能
  •  就是一系列的拦截器执行了,进行一些处理工作。
  • 咱们可以在struts-default.xml配置文件中看到有很多的拦截器。可以通过断点的方式来演示。
  •  拦截器执行完后,会根据struts.xml的配置文件找到请求路径,找到具体的类,通过反射的方式让方法执行。

2.struts2配置文件加载顺序

1. Struts2框架的核心是StrutsPrepareAndExecuteFilter过滤器,该过滤器有两个功能

  • Prepare -- 预处理,加载核心的配置文件
  •  Execute -- 执行,让部分拦截器执行

2. StrutsPrepareAndExecuteFilter过滤器会加载哪些配置文件呢?

  •  通过源代码可以看到具体加载的配置文件和加载配置文件的顺序
  •  init_DefaultProperties(); -- 加载org/apache/struts2/default.properties
  •  init_TraditionalXmlConfigurations(); -- 加载struts-default.xml,struts-plugin.xml,struts.xml
  •  init_LegacyStrutsProperties(); -- 加载自定义的struts.properties.
  •  init_CustomConfigurationProviders(); -- 加载用户自定义配置提供者
  •  init_FilterInitParameters() ; -- 加载web.xml的初始化

3. 重点了解的配置文件

  •  default.properties -- 在org/apache/struts2/目录下,代表的是配置的是Struts2的常量的值
  •  struts-default.xml -- 在Struts2的核心包下,代表的是Struts2核心功能的配置(Bean、拦截器、结果类型等)
  • struts.xml -- 重点中的重点配置,代表WEB应用的默认配置,在工作中,基本就配置它就可以了!!(可以配置常量)
  •  web.xml -- 配置前端控制器(可以配置常量

* 注意:

  •  前3个配置文件是struts2框架的默认配置文件,基本不用修改。
  •  后3个配置文件可以允许自己修改struts2的常量。但是有一个特点:后加载的配置文件修改的常量的值,会覆盖掉前面修改的常量的值。

4. 总结(重点掌握的配置文件)

  • 先加载default.properties文件,在org/apache/struts2/default.properties文件,都是常量。
  • 又加载struts-default.xml配置文件,在核心的jar包最下方,struts2框架的核心功能都是在该配置文件中配置的。
  •  再加载struts.xml的配置文件,在src的目录下,代表用户自己配置的配置文件
  •  最后加载web.xml的配置文件

 

  •  后加载的配置文件会覆盖掉之前加载的配置文件(在这些配置文件中可以配置常量)
  • 加载default.properties(默认常量值)
  • 加载struts-default.xml(核心的功能),编写包的配置都需要继承struts-default,但是配置文件中不能编写常量的
  • 加载struts.xml(开发必须要编写的配置文件),编写常量的(开发中编写常量的地方)
  • 加载web.xml,也可以编写常量(开发中尽量不要在该配置文件中编写常量值)

5. 注意一个问题
  * 哪些配置文件中可以配置常量?

  • default.properties -- 默认值,咱们是不能修改的!!
  •  struts.xml -- 可以配置,开发中基本上都在该配置文件中配置常量
  • struts.properties -- 可以配置,基本不会在该配置文件中配置
  • web.xml -- 可以配置,基本不会在该配置文件中配置

   后加载的配置文件会覆盖掉之前加载的配置!!

struts.xml配置详解

<package>标签

功能:用来定义不同的模块,管理和配置Action,并且实现包内配置复用(通过包继承)

如果要配置<Action>的标签,那么必须要先配置<package>标签,代表的包的概念

  • name -- 包的名称,在struts容器中具有唯一性(在开发中可以用模块名作为包名),管理action配置
  • extends -- 继承父package中的功能,通常继续struts-default,由于该默认包内定义了大量结果集类型和拦截器,所以struts强制继承struts-default,否则报错
  •  namespace -- 名称空间,一般与<action>标签中的name属性共同决定访问路径(通俗话:怎么来访问action),常见的配置如下

    * namespace="/" -- 根名称空间
    * namespace="/aaa" -- 带有名称的名称空间
    * abstract -- 抽象的。这个属性基本很少使用,值如果是true,那么编写的包是被继承的

例:以昨天开发的工程基础上修改Java网课基础笔记(29)

修改hello.jsp里的路径

<body>
	<!-- struts2框架默认处理后缀名为.action的请求 -->
	<a href="${pageContext.request.contextPath}/xxx/hello.action">hello请求</a> 
</body>

修改result.jsp内容

<body>
<h1>config result</h1>
</body>

修改HelloAction.java

import com.opensymphony.xwork2.Action;
public class HelloAction implements Action {
	//HelloAction类实现Action接口后,执行HelloAction的时候默认执行execute()方法
	//类似post请求执行doPost方法,返回的String类型是返回结果集
	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("hello config");
		//返回逻辑视图
		return "success";
	}
}

 

struts.xml增加以下内容

<package name="anotherPackage" extends="struts-default" namespace="/xxx">
	<action name="hello" class="HelloAction">
		<result name="success">/result.jsp</result>
	</action>
</package>

测试(注意路径)

namespace:访问路径,

【面试知识点一】

如果rul是http://localhost:8080/project工程名/xxx/qqq.action,namespace就是/xxx

如果rul是http://localhost:8080/project工程名/xxx/yyy/qqq.action,namespace就是/xxx/yyy

【面试知识点二】

如果rul是http://localhost:8080/project工程名/xxx/yy/zz/hello.action

首先去搜索namespace为/xxx/yy/zz的package

如果找不到,去搜索/xxx/yy的package

如果找不到,去搜索/xxx的package

【面试知识点三】

namespace="" 和namespace="/"的区别

namespace="/"的优先级比namespace=""的优先级高】

即首先去搜索namespace="/",如果搜不到,则搜索namespace=""

<action>标签

功能:用来管理具体的Action,负责接收客户的请求,进行处理,并且完成响应

  • name属性:action的名字,用于配置请求的URL路径
  • class属性:action对应的完整包路径,该类编写了action具体业务逻辑代码。
  • 找到action之后,系统会默认会执行Action类中的execute方法。
  • 若没有class属性,系统会默认执行ActionSupport中execute方法,而ActionSupport的execute会默认返回 success逻辑视图,这种处理方式在struts-default.xml 文件已经进行了规定。
  • 当访问的Action不存在的时候,我们可以自行设定默认执行的Action。在操作中,当系统访问不到对应请求的action的时候,会执行我们自行设定默认执行的action,这种方式需要我们在struts.xml文件中提前进行相关配置

例:以昨天开发的工程基础上修改Java网课基础笔记(29)

修改HelloAction.java

import com.opensymphony.xwork2.Action;
public class HelloAction implements Action {
	//HelloAction类实现Action接口后,执行HelloAction的时候默认执行execute()方法
	//类似post请求执行doPost方法,返回的String类型是返回结果集
	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("hello action");
		//返回逻辑视图
		return "success";
	}
}
  • 问题一:如果action 没有配置class属性

在struts.xml中

<package name="anotherPackage" extends="struts-default"
		namespace="/xxx">
		<!--没有写class属性,程序会产生什么结果? 若没有class属性,系统会默认执行ActionSupport中execute方法,而ActionSupport的execute会默认返回 
			success逻辑视图,这种处理方式在struts-default.xml 文件已经进行了规定。 -->
		<action name="hello">
			<result name="success">/result.jsp</result>
		</action>
	</package>

还是会执行成功

  • 问题二:action的name属性写错,即写错名字
<package name="anotherPackage" extends="struts-default"
		namespace="/xxx">
		<!-- action的name属性写错 -->
		<action name="helle">
			<result name="success">/result.jsp</result>
		</action>
	</package>

测试结果(会报错,找不到action)

像上面出现的404这种错误页面对用户来说很不友好,所有我们应该自己定义错误页面。

新建一个errorPage.jsp

<body>
错误
<img alt="" src="${pageContext.request.contextPath}/img/404.jpg">
</body>

找张404图片放在WebConent/img下

在struts.xml修改

<package name="anotherPackage" extends="struts-default"
		namespace="/xxx">
		<!-- 告诉struts框架,如果action找不到,就跳转到指定到Action  必须配置在action节点前面 -->
		<default-action-ref name="errorPage"></default-action-ref>
		<!-- action的name属性写错 -->
		<action name="helle">
			<result name="success">/result.jsp</result>
		</action>
		<!-- 配置一个出错要执行的Action -->
		<action name="errorPage">
			<result name="success">/errorPage.jsp</result>
		</action>	
	</package>

测试结果

<constant>常量配置

  • struts.xml(推荐)(在package包外面)
<!-- 配置后缀名常量 -->
<constant name="struts.action.extension" value="abc"></constant>

在hello.jsp中修改 

<body>
	<!-- struts2框架默认处理后缀名为.action的请求 -->
	<a href="${pageContext.request.contextPath}/xxx/hello.action">hello请求</a>
	<br> 
	<!-- 修改后缀名 -->
	<a href="${pageContext.request.contextPath}/xxx/helle.abc">helle请求(别看差眼啦)</a> 
</body>

测试结果(注意路径)

  • struts.properties
key=value
  • web.xml
<!-- 配置struts2的过滤器 -->
		<filter>
			<filter-name>struts2</filter-name>
			<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
			<!-- 修改后缀名 -->
		<init-param>
		<param-name>struts.action.extension</param-name>
		<param-value>xyz</param-value>
		</init-param>
		</filter>

在hello.jsp修改

<body>
	<!-- struts2框架默认处理后缀名为.action的请求 -->
	<a href="${pageContext.request.contextPath}/xxx/hello.action">hello请求</a>
	<br> 
	<!-- 修改后缀名 -->
	<a href="${pageContext.request.contextPath}/xxx/helle.abc">helle请求(别看差眼啦)</a> 
	<br>
	<a href="${pageContext.request.contextPath}/xxx/helle.xyz">helle请求(xyz)</a> 
</body>

测试结果

单击第三个

但是现在点击第二个(会报错)

原因:加载的配置文件会覆盖之前的配置文件

文件分离(分模块)

修改hello.jsp

<body>
	<!-- struts2框架默认处理后缀名为.action的请求 -->
	<a href="${pageContext.request.contextPath}/xxx/hello.action">hello请求</a>
	<br> 
	<!-- 修改后缀名 -->
	<a href="${pageContext.request.contextPath}/xxx/helle.abc">helle请求(别看差眼啦)</a> 
	<br>
	<a href="${pageContext.request.contextPath}/xxx/helle.xyz">helle请求(xyz)</a> 
	<br>
	<a href="${pageContext.request.contextPath}/part1/hello.xyz">文件分离</a> 
</body>

在struts.xml引入其他配置文件

<!-- 引入分离文件 -->
<include file="struts-part1"></include>

增加struts-part1.xml

<package name="mypart1" extends="struts-default" namespace="/part1">
		<action name="hello" class="HelloAction">
			<result name="success">/result.jsp</result>
		</action>
	</package>

测试结果

注意:如要引用完整的包名:<include file="/ceshi/src/struts-part1.xml"></include>

Action编写方式(3种)

  1. 实现Action接口(可以使用结果集常量字符串)
  2. 继承ActionSupport类:(重点之重点,推荐方式)

          对请求参数进行校验

         设置错误信息

         读取国际化信息

   3.pojo类(非入侵性,简单,干净)没有extends父类,也没有implements接口

新建项目工程struts_01,配置上同

Action接口中有5个常量和一个execute方法

5个常量分别是:

public static final java.lang.String SUCCESS = "success"; 运行成功返回的逻辑视图

  public static final java.lang.String NONE = "none";不返回任何结果页面

  public static final java.lang.String ERROR = "error";运行失败时返回的逻辑视图

  public static final java.lang.String INPUT = "input";校验失败时返回的逻辑视图

  public static final java.lang.String LOGIN = "login";登录时返回的逻辑视图

新建my.jsp

<body>
<h1>
<a href="${pageContext.request.contextPath}/my1.action">Action的编写方式一 实现Action接口</a><br>
<a href="${pageContext.request.contextPath}/my2.action">Action的编写方式二 继承ActionSupport类</a><br>
<a href="${pageContext.request.contextPath}/my3.action">Action的编写方式三 普通Java类(pojo类)</a>
</h1>
</body>

新建result.jsp

<body>
<h1>result</h1>
</body>

方式一 实现Action接口

编写MyAction1.java

public class MyAction1 implements Action {
	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Action编写方式一");
		return SUCCESS;
	}
}

struts.xml配置文件

<package name="default" extends="struts-default" namespace="/">
		<action name="my1" class="struts_01.MyAction1">
			<result name="success">/result.jsp</result>
		</action>
	</package>

测试结果

方式二 继承ActionSupport类

继承ActionSupport类后,具有Action接口功能,还有严重功能(重点推荐的方式)

编写MyAction2.java

public class MyAction2 extends ActionSupport {
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Action编写方式二");
		return SUCCESS;
	}
}

struts.xml配置文件增加action

<action name="my2" class="struts_01.MyAction2">
			<result name="success">/result.jsp</result>
		</action>

测试结果

方式三 普通Java类(pojo类)

编写MyAction3.java

//可去掉throws Exception 但一定要execute方法
public class MyAction3 {
	public String execute() throws Exception {
		System.err.println("Action编写方式三");
		return "success";
	}
}

struts.xml配置文件增加action

<action name="my3" class="struts_01.MyAction3">
			<result name="success">/result.jsp</result>
		</action>

测试结果

Action访问方式

方式一  通过<action>标签中的method属性,访问到Action中的具体的方法。

编写loginresult.jsp

<body>
<h1>resultLogin</h1>
</body>

编写registresult.jsp

<body>
<h1>regist result</h1>
</body>

编写UserAction.java

public class UserAction extends ActionSupport {
	public String login() throws Exception {
		System.err.println("执行了login方法");
		return "success";
	}
	public String regist() throws Exception {
		System.out.println("执行了regist方法");
		return SUCCESS;
		
	}

}

struts.xml配置文件

<!-- 第一种方式:method属性指明了要执行的方法名,达到不同的请求执行不同的方法 -->
		 <action name="userLogin" class="struts_01.UserAction" method="login">
			<result name="success">/resultLogin.jsp</result>
		</action>
		<action name="userRegist" class="struts_01.UserAction" method="regist">
			<result name="success">/resultRegist.jsp</result>
		</action>

测试结果

方式二 通配符的访问方式:(访问的路径和方法的名称必须要有某种联系.) 

  • 一个通配符
  • sruts.xml增加action
<!-- 第二种方式:(一个通配符)使用通配符配置执行方法 {1}自动匹配*方法 -->
		<!-- http://localhost:8080/struts_01/user_login.action 
			http://localhost:8080/struts_01/user_regist.action -->
		<action name="user_*" class="struts_01.UserAction" method="{1}">
			<result name="success">/{1}result.jsp</result>
			<allowed-methods>login,regist</allowed-methods> 
		</action>
  • 测试结果

2.5版本以后,为了增加安全性,内部会验证是否允许访问该方法。

用通配符一定要加上<allowed-methods>action方法名</allowed-methods> 

  • 两个通配符
  • sruts.xml增加action
<!-- 2个通配符方式  了解即可 -->
		<!-- *_* 如UserAction_login   即UserAction匹配{1} login匹配{2}  -->
		<action name="*_*" class="struts_01.{1}"  method="{2}">
			<result name="success">/{2}result.jsp</result>
			<allowed-methods>login,regist</allowed-methods>
		</action>
  • 测试结果

方式三 动态方法调用(了解)

需求信息:单纯使用method属性来配置action方法,调用不同的方法,需要配置不同的action,配置较多。

可以采用通配符的方式解决,也可以通过动态方法解决

优点:在配置action时无需配置method

缺点:不安全,不推荐使用,是方法名暴露在url

  • sruts.xml增加action
<!-- 开启动态方法调用 -->
	<constant name="struts.enable.DynamicMethodInvocation"
		value="true"></constant>
<!-- 第三种方式:通过动态方法调用 在默认情况下,动态方法是关闭的,需要手动开启 -->
		<action name="userDy" class="struts_01.UserAction">
			<result name="success">/loginresult.jsp</result>
			<allowed-methods>login</allowed-methods>
		</action>
  • 测试结果

同样的,也需要添加<allowed-methods>login</allowed-methods>

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值