首页 > 代码库 > JAVAWEB开发之Struts2详解(一)——Struts2框架介绍与快速入门、流程分析与工具配置以及Struts2的配置以及Action和Result的详细使用
JAVAWEB开发之Struts2详解(一)——Struts2框架介绍与快速入门、流程分析与工具配置以及Struts2的配置以及Action和Result的详细使用
Struts2框架介绍
三大框架:是企业主流JavaEE开发的一套架构。Struts2 + Spring + Hibernate
什么是框架?为什么要学习框架?
框架是实现部分功能的代码(半成品),使用框架简化企业级软件开发。
Struts2与MVC?
Struts是一款优秀的MVC框架
MVC:是一种思想,是一种模式,将软件分为Model模型、View视图、Controller控制器
JAVAEE软件三层架构:web层(表现层)、业务逻辑层、数据持久层(Sun提供javaEE开发规范)
JavaEE开发更强调三层架构,web层开发注重MVC。
Struts2就是web层开发框架,符合MVC模式
Struts2与Struts1关系:
Struts2是Struts的下一代产品,是在Struts1和WebWork的技术基础上进行了合并的全新的Struts2框架
其全新的Struts2的体系结构与Struts1的体系结构差别巨大。Struts2以WebWork为核心
Struts2=Struts1+WebWork
Struts2是Apache的产品。
Struts2是一个标准的MVC框架。JAVAWEB中的model2模式就是一个MVC模式。model2=Servlet+jsp+JavaBean
Struts2框架是在JAVAWEB开发中使用的。
使用Struts2框架,可以简化我们的web开发,并且降低程序的耦合度。
类似于Struts2框架的产品:
Struts1、webwork、jsf(Sun提供)、SpringMVC都是MVC模式
ssh:Struts2 Spring Hibernate
ssi:springmvc spring ibatis
XWork——它是WebWork的核心
XWork提供了很多核心功能:前端拦截机(interceptor),运行时表单属性验证,类型转换,强大的表达式语言(OGNL—the Object Navigation Language),IOC(Inversion of Control 反转控制)容器等。
Struts2开发入门
Struts2是一个非常优秀的MVC框架,基于Model2设计模型
由传统的Struts1和WebWork两个经典框架发展而来
Struts2核心功能:
- 允许POJO(Plain Old Java Objects)对象作为Action
- Action的execute方法不再与ServletAPI耦合,更易于测试
- 支持更多视图技术(JSP、FreeMarker、Velocity)
- 基于Spring AOP思想的拦截器机制,更易于扩展
- 更强大、更易用输入校验功能
- 整合AJAX支持
Struts2的下载和安装
http://struts.apache.org/download.cgi 下载Struts2最新版
下载后 目录如下:
Struts2目录结构:
- apps:该文件夹包含了基于Struts2的示例应用,这些示例应用对于学习者是非常有用的。
- docs:该文件夹下包含了Struts2相关文档,包括Struts2快速入门、Struts2的文档以及API文档等。
- lib:该文件夹下包含了Struts2框架和核心类库,以及Struts2第三方插件库类。
- src:该文件夹下包含了Struts2框架的全部源代码
开发时没有必要将lib目录下的jar文件全部复制到项目中。
Struts2的入门理论:
导入Struts2必要的Jar包:
- struts2-core-2.3.1.1.jar:Struts2框架的核心类库。
- xwork-core-2.3.1.1.jar:Command模式框架,WebWork和Struts2都基于XWork。
- ognl-3.0.3.jar:对象图导航语言(Object Graph Navigation Language),Struts2框架通过其读写对象的属性。
- freemarker-2.3.18.jar:Struts2的UI标签的模板使用FreeMarker编写。
- commons-logging-1.1.x.jar:ASF出品的日志包,Struts2框架使用这个日志包来支持Log4J和JDK1.4+的日志记录。
- commons-fileupload-1.2.2.jar:文件上传组件2.1.6版本后需要加入此文件。
- commons-io-2.0.1.jar:上传文件依赖的jar包。
- commons-lang-2.5.jar:对java.lang包的增强。
开发中为了方便导入,可以使用app/struts2-bank.war所携带的jar包。
Struts2开发入门示例:
index.jsp——>HelloServlet——>hello.jsp web开发流程
index.jsp——>HelloAction——> hello.jsp Struts2流程
步骤1.导入jar包
下载struts2的jar包 struts-2.3.15.1-all 版本.
struts2的目录结构:
apps: 例子程序
docs:文档
lib:struts2框架所应用的jar以及插件包
src:源代码
core 它是struts2的源代码
xwork-core struts2底层使用了xwork,xwork的源代码
注意:在struts2开发,一般情况下最少导入的jar包,去apps下的struts2-blank示例程序中copy
下载struts2的jar包 struts-2.3.15.1-all 版本.
struts2的目录结构:
apps: 例子程序
docs:文档
lib:struts2框架所应用的jar以及插件包
src:源代码
core 它是struts2的源代码
xwork-core struts2底层使用了xwork,xwork的源代码
注意:在struts2开发,一般情况下最少导入的jar包,去apps下的struts2-blank示例程序中copy
app下是导包出来的war文件 将其后缀名改为rar文件解压即可 复制struts-bank/WEB-INF/lib下的所有jar包
步骤2.创建index.jsp页面和hello.jsp页面
步骤3.对Struts2框架进行配置
1.web.xml中配置前端控制器(核心控制器)-----就是一个Filter
目的:是为了让Struts2框架可以运行。
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
具体代码可以从apps/struts2-bank/WEB-INF/web.xml中进行复制如下图所示:
2.创建一个struts.xml配置文件,这个是Struts2框架的配置文件。
目的:是为了struts2框架流程可以执行。
名称:struts.xml
位置:src下(发布后的classes下)
可以将 apps/struts2-bank/WEB-INF/classes/struts.xml 文件复制到自己项目中的src下然后进行配置修改。
步骤4:创建一个HelloAction类
要求,在HelloAction类中创建一个返回值必须是String类型 的方法,注意:还必须无参数。
public String say(){
return "good";
}
return "good";
}
步骤5:在struts.xml中配置HelloAction
<package name="default" namespace="/" extends="struts-default">
<action name="hello" class="cn.itcast.action.HelloAction" method="say">
<result name="good">/hello.jsp</result>
</action>
</package>
<action name="hello" class="cn.itcast.action.HelloAction" method="say">
<result name="good">/hello.jsp</result>
</action>
</package>
步骤6:在index.jsp中添加链接测试
<a href=http://www.mamicode.com/"${pageContext.request.contextPath}/hello">第一次使用struts2
在地址栏中输入:http://localhost/struts2_day01/index.jsp 访问连接,就可以看到HelloAction类中的say方法执行了,也跳转到了hello.jsp.
在地址栏中输入:http://localhost/struts2_day01/index.jsp 访问连接,就可以看到HelloAction类中的say方法执行了,也跳转到了hello.jsp.
代码如下:
src/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 name="default" namespace="/" extends="struts-default"> <action name="hello" class="cn.itcast.action.HelloAction" method="say"> <result name="good">/hello.jsp</result> </action> </package> <package name="dd" namespace="/abc" extends="struts-default"> <action name="hello" class="cn.itcast.action.HelloAction" method="say"> <result name="good">/hello.jsp</result> </action> </package> </struts>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>mystruts2_day01</display-name> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>HelloAction类
package cn.itcast.action; public class HelloAction { public String say() { System.out.println("hello action say hello"); return "good"; } }index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘index.jsp‘ starting page</title> </head> <body> <a href=http://www.mamicode.com/"${pageContext.request.contextPath}/hello">第一次使用struts2>hello.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘index.jsp‘ starting page</title> </head> <body> <h1>hello Struts2</h1> </body> </html>
其过程原理如下:
模仿Struts2流程完成入门程序
index.jsp 、hello.jsp、 HelloAction、 struts.xml
1.创建一个Filter----StrutsFilter
2.在web.xml文件中配置StrutsFilter
<filter>
<filter-name>struts</filter-name>
<filter-class>cn.itcast.filter.StrutsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.在StrutsFilter中完成拦截操作,并访问Action中的方法,跳转到hello.jsp页面操作.
具体代码如下(注意:需要导入Dom4J和xpath的相关jar包 )
HelloAction
2.在web.xml文件中配置StrutsFilter
<filter>
<filter-name>struts</filter-name>
<filter-class>cn.itcast.filter.StrutsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.在StrutsFilter中完成拦截操作,并访问Action中的方法,跳转到hello.jsp页面操作.
具体代码如下(注意:需要导入Dom4J和xpath的相关jar包 )
HelloAction
package cn.itcast.action; public class HelloAction { public String say() { System.out.println("hello action say method"); return "good"; } }StrutsFilter
package cn.itcast.filter; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class StrutsFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { // 1.强转 HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; // 2.操作 // 2.1 得到请求资源路径 String uri = request.getRequestURI(); String contextPath = request.getContextPath(); String path = uri.substring(contextPath.length() + 1); // System.out.println(path); // hello // 2.2 使用path去struts.xml文件中查找某一个<action name=path>这个标签 SAXReader reader = new SAXReader(); try { // 得到struts.xml文件的document对象。 Document document = reader.read(new File(this.getClass() .getResource("/struts.xml").getPath())); Element actionElement = (Element) document .selectSingleNode("//action[@name=‘" + path + "‘]"); // 查找<action // name=‘hello‘>这样的标签 if (actionElement != null) { // 得到<action>标签上的class属性以及method属性 String className = actionElement.attributeValue("class"); // 得到了action类的名称 String methodName = actionElement.attributeValue("method");// 得到action类中的方法名称。 // 2.3通过反射,得到Class对象,得到Method对象 Class actionClass = Class.forName(className); Method method = actionClass.getDeclaredMethod(methodName); // 2.4 让method执行. String returnValue = http://www.mamicode.com/(String) method.invoke(actionClass>src下struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <struts> <action name="hello" class="cn.itcast.action.HelloAction" method="say"> <result name="good">/hello.jsp</result> </action> </struts>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <filter> <filter-name>struts</filter-name> <filter-class>cn.itcast.filter.StrutsFilter</filter-class> </filter> <filter-mapping> <filter-name>struts</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
Struts2流程分析与工具配置
1.Struts2处理流程
大致是如下流程:
流程分析:
请求——>StrutsPrepareAndExecuteFilter核心控制器——>Interceptor拦截器(实现代码功能)——>Action的execute——>结果页面Result
拦截器 在struts-default.xml定义
执行拦截器 是defaultStack中引用拦截器
拦截器描述(struts-default.xml 在Struts核心包core下)
断点演示过滤器和拦截器的执行顺序
使用如下三个拦截器演示struts的执行流程(断点演示)
默认的是defaultStack
<interceptor name="chain"
class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
<interceptor name="params"
class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
<interceptor name="prepare"
class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
默认的是defaultStack
<interceptor name="chain"
class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
<interceptor name="params"
class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
<interceptor name="prepare"
class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
在栈中的顺序如下:
断点调试 结果如下:
由此证明 Struts项目中执行了栈中的拦截器
2.关于手动配置struts.xml文件中提示操作
如果安装Aptana编辑器 ,请不要用Aptana自带xml编辑器 编写struts2配置文件
struts.xml提示来自于 DTD约束,
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
按理说正常上网,自动缓存dtd,会有提供提示功能,但实际上能上网也不会有代码提示,因为这个网址已经被屏蔽
所以必须配置本地DTD提示
导入DTD时,应该和配置DTD版本一致 配置步骤如下:
struts.xml提示来自于 DTD约束,
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
按理说正常上网,自动缓存dtd,会有提供提示功能,但实际上能上网也不会有代码提示,因为这个网址已经被屏蔽
所以必须配置本地DTD提示
导入DTD时,应该和配置DTD版本一致 配置步骤如下:
在struts2-core-x.x.x.jar中含有 struts-2.3.dtd
将其复制到硬盘任意位置
myeclipse - window - preferences - 搜索xml catalog - Add
注意key的类型要选用URI
将其复制到硬盘任意位置
myeclipse - window - preferences - 搜索xml catalog - Add
注意key的类型要选用URI
3.关联struts.xml源文件
在配置文件中找到对应的类名 双击选中ctrl+shift+t 即可打开搜索窗口 搜索对应类的源代码
如果找不到对应的类需要关联源代码文件夹
涉及到以com.opensymphony.xxx开头的类就上Xwork中src下去找核心源代码 Xwork/src/core
涉及到org.apache.struts.xxx开头的类就上 Struts中src下去找核心源代码 Struts/src/core
涉及到org.apache.struts.xxx开头的类就上 Struts中src下去找核心源代码 Struts/src/core
4.Config Brower插件使用
struts2-config-browser-plugin-2.3.15.1
提供在浏览器中查看 struts2 配置加载情况
将解压struts2/lib/struts2-config-browser-plugin-2.3.7.jar 复制WEB-INF/lib下
访问 http://localhost/struts2_day01/config-browser/index.action 查看 struts2配置加载情况
提供在浏览器中查看 struts2 配置加载情况
将解压struts2/lib/struts2-config-browser-plugin-2.3.7.jar 复制WEB-INF/lib下
访问 http://localhost/struts2_day01/config-browser/index.action 查看 struts2配置加载情况
Struts2配置(重点)
1.Struts2配置文件加载顺序
Struts2框架要能执行,必须先加载StrutsPrepareAndExecuteFilter
在StrutsPrepareAndExecuteFilter的init方法中对Dispatcher进行了初始化。
在Dispatcher类中定义的init方法内描述了struts2配置文件的加载顺序。
init_DefaultProperties(); // [1] ---------- org/apache/struts2/default.properties
init_TraditionalXmlConfigurations(); // [2] --- struts-default.xml,struts-plugin.xml,struts.xml
init_LegacyStrutsProperties(); // [3] --- 自定义struts.properties
init_CustomConfigurationProviders(); // [5] ----- 自定义配置提供
init_FilterInitParameters() ; // [6] ----- web.xml
init_AliasStandardObjects() ; // [7] ---- Bean加载
1.default.properties文件
init_TraditionalXmlConfigurations(); // [2] --- struts-default.xml,struts-plugin.xml,struts.xml
init_LegacyStrutsProperties(); // [3] --- 自定义struts.properties
init_CustomConfigurationProviders(); // [5] ----- 自定义配置提供
init_FilterInitParameters() ; // [6] ----- web.xml
init_AliasStandardObjects() ; // [7] ---- Bean加载
1.default.properties文件
作用:定义了struts2框架中所有常量
位置存放在struts2-core-x.x.x.jar 中 org.apache.struts2包里面
2.struts-default.xml
作用:配置了bean,interceptor,result等
位置:在struts的core核心jar包(struts2-core-x.x.x.jar 根目录下)
struts-plugin.xml
它是struts框架中所使用的插件的配置文件
该文件保存在struts-Xxx-x.x.x.jar
struts.xml
它是web应用默认的struts配置文件(放在项目的src即classpath下)
3.自定义的struts.properties
该文件由自己创建(可以在里面自定义常量)
4.web.xml该文件是web应用的配置文件
常用的几个文件加载顺序依次是:
default.properties
struts-default.xml
struts.xml
在开发中,后加载文件中的配置会将先加载文件中的配置覆盖,即如果多个文件配置了同一个struts2常量,则后一个文件中配置的常量值会覆盖前面文件中配置的常量值。
2.关于Action的配置
1.<package> 作用:是用于声明一个包。用于管理action。它有以下属性:
- name 它用于声明一个包名,包名不能重复,也就是它是唯一的。
- namespace 它与action标签的name属性合并确定了一个唯一访问action的路径(它也是唯一的)
- extends 它代表继承的包名。
- abstract 它的取值可以为true或false,如果为true,代表这个包是用于被继承的。
2.<action> 用于声明一个action
- name 就是一个action的名称,它是唯一的(在同包内)它与package中namespace确定了访问action的路径。
- class 即Action类的全名。
- method 要访问的Action类中的方法的名称,方法无参数,返回值为String。
3.<result> 用于确定返回结果类型
- name 它与action中的方法返回值做对比,确定跳转路径
2.1关于action配置其他细节:
(1)关于默认值问题
<package namespace="默认值"> namespace的默认值是"" (空字符串)
<action class="默认值" method="默认值">
class的默认值是com.opensymphony.xwork2.ActionSupport
method的默认值是execute
<result name="默认值"> result属性name的默认值是 "success"
(2)struts.xml文件的分离
目的:就是为了阅读方便。可以让一个模块一个配置文件,在struts.xml文件中通过
<include file="xxx.xml"/>导入其它的配置文件。
<include file="xxx.xml"/>导入其它的配置文件。
(3)关于访问Action的路径问题
- 步骤一: 获得请求路径为http://localhost/mystruts2_day01_2/a/b/c/hello 这个路径时,分析如下:
- 步骤二:首先会寻找namespace为/a/b/c的package,如果存在则在这个package中寻找名字为hello的action,
- 如果找不到就会跳转到当前包下的默认action页面。如果当前包下没有设置<default-action-ref name="xxx"></default-action-ref> 默认的action页面则转步骤三;
- 步骤三:寻找namespace为/a/b的package,如果存在则在这个package中寻找名字为hello的action,
- 如果找不到就会跳转到当前包下的默认action页面。如果当前包下没有设置<default-action-ref name="xxx"></default-action-ref> 默认的action页面则转步骤四;
- 步骤四:寻找namespace为/a的package,如果存在则在这个package中寻找名字为hello的action,
- 如果找不到就会跳转到当前包下的默认action页面。如果当前包下没有设置<default-action-ref name="xxx"></default-action-ref> 默认的action页面则转步骤五;
- 步骤五:去默认的namespace下寻找该action ,默认的namespace为""(空字符串)/hello如果还是找不到 提示找不到的错误信息。
(4)默认的action
作用:处理当前包下其他action处理不了的路径
<default-action-ref name="action的名称" />
配置了这个,当访问的路径,其它的action处理不了时,就会执行name指定的名称的action。
配置了这个,当访问的路径,其它的action处理不了时,就会执行name指定的名称的action。
(5)action的默认处理类
在action配置时,如果class不写。默认情况下是 com.opensymphony.xwork.ActionSupport
<default-class-ref class="cn.itcast.action.DefaultAction">
如果设置了,那么在当前包下,默认action的请求处理类就为class指定的类
3.关于常量配置
default.properties定义了struts2 框架的大量常量,开发者可以通过改变这些常量来满足应用的需求
3.1修改struts2 的配置常量,可以通过以下三种方式配置:
1.配置src/struts.xml(应用最多)
<constant name="常量名称" value=http://www.mamicode.com/"常量值">
例如:<constant name="struts.devMode" value=http://www.mamicode.com/"true" />
2.配置src/struts.properties(基本不使用)
例如:struts.devMode=false
3.配置web.xml(很少用)
配置常量,是使用StrutsPrepareAndExecuteFilter的初始化参数来配置的
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>struts.action.extension</param-name>
<param-value>do,,</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>struts.action.extension</param-name>
<param-value>do,,</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.2常用常量介绍
(1)<constant name="struts.i18n.encoding" value=http://www.mamicode.com/"UTF-8"/>
指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法和freemarker、velocity输出
(2)<constant name="struts.action.extension" value=http://www.mamicode.com/"action"/>
该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts2处理。
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开
(3)<constant name="struts.serve.static.browserCache" value=http://www.mamicode.com/"false"/>
设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭
(4)<constant name="struts.configuration.xml.reload" value=http://www.mamicode.com/"true"/>
当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开
(5)<constant name="struts.devMode" value=http://www.mamicode.com/"true" />
提供详细报错页面,修改struts.xml后不需要重启服务器 (要求)
开发模式下使用,这样可以打印出更详细的错误信息
(6) <constant name="struts.ui.theme" value=http://www.mamicode.com/"simple" /> 默认的视图主体
(7) <constant name="struts.objectFactory" value=http://www.mamicode.com/"spring" />
与spring集成时,指定由spring负责action对象的创建
(8)<constant name="struts.enable.DynamicMethodInvocation" value=http://www.mamicode.com/"false"/>
该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属 性为 false
(9)<constant name="struts.multipart.maxSize" value=http://www.mamicode.com/“10701096"/> 限制上传文件的大小
关于Action类的创建
有三种方式:
方式1.创建一个POJO类.
简单的Java对象(Plain Old Java Objects)
指的是没有实现任何接口,没有继承任何父类(除了Object)
要求:必须有返回值为String且无参数的方法
优点:无耦合。
缺点:所以工作都要自己实现。
在struts2框架底层是通过反射来操作:
* struts2框架 读取struts.xml 获得 完整Action类名
* obj = Class.forName("完整类名").newInstance();
* Method m = Class.forName("完整类名").getMethod("execute"); m.invoke(obj); 通过反射 执行 execute方法
简单的Java对象(Plain Old Java Objects)
指的是没有实现任何接口,没有继承任何父类(除了Object)
要求:必须有返回值为String且无参数的方法
优点:无耦合。
缺点:所以工作都要自己实现。
在struts2框架底层是通过反射来操作:
* struts2框架 读取struts.xml 获得 完整Action类名
* obj = Class.forName("完整类名").newInstance();
* Method m = Class.forName("完整类名").getMethod("execute"); m.invoke(obj); 通过反射 执行 execute方法
方式二:创建一个类,实现Action接口 (com.opensymphony.xwork.Action)
优点:耦合低。提供了五种结果视图,定义了一个行为方法。
缺点:所有工作都要自己实现。
SUCCESS: 数据处理成功(成功页面)
NONE:页面不跳转 return null; 效果一样
ERROR:数据处理发送错误(错误页面)
INPUT:用户输入数据有误,通常用于表单数据校验(输入页面)
LOGIN:主要权限认证(登录页面)
方式3.创建一个类,继承自ActionSupport类. com.opensymphony.xwork2.ActionSupport
ActionSupport类实现了Action接口。定义了 表单域校验、错误信息设置和获得国际化信息相关一些方法
优点:表单校验、错误信息设置、读取国际化信息 三个功能都支持.
缺点:耦合度高。
ActionSupport类实现了Action接口。定义了 表单域校验、错误信息设置和获得国际化信息相关一些方法
优点:表单校验、错误信息设置、读取国际化信息 三个功能都支持.
缺点:耦合度高。
在开发中,第三种会使用的比较多.
关于Action类的创建 总结如下:
用户编写Action 可以是 POJO
用户编写Action 可以实现Action接口
可以使用结果集常量字符串
用户编写Action 可以继承ActionSupport基类
对请求参数进行校验
设置错误信息
读取国际化信息
execute方法编写注意细节
public 修饰符
String 返回值
无参数
用户编写Action 可以实现Action接口
可以使用结果集常量字符串
用户编写Action 可以继承ActionSupport基类
对请求参数进行校验
设置错误信息
读取国际化信息
execute方法编写注意细节
public 修饰符
String 返回值
无参数
关于Action的访问
1.通过设置method的值,来确定访问action类中的哪一个方法.
<action name="book_add" class="cn.itcast.action.BookAction"method="add"></action>当访问的是book_add,这时就会调用BookAction类中的add方法。
<action name="book_update" class="cn.itcast.action.BookAction"method="update"></action>
当访问的是book_update,这时就会调用BookAction类中的update方法。
2.使用通配符来简化配置
1.在struts.xml文件中<action name="*_*" class="cn.itcast.action.{1}Action" method="{2}"></action>
2.在jsp页面上
book.jsp
<a href=http://www.mamicode.com/"${pageContext.request.contextPath}/Book_add">book add
<a href=http://www.mamicode.com/"${pageContext.request.contextPath}/Book_update">book update
<a href=http://www.mamicode.com/"${pageContext.request.contextPath}/Book_delete">book delete
<a href=http://www.mamicode.com/"${pageContext.request.contextPath}/Book_search">book search
product.jsp
<a href=http://www.mamicode.com/"${pageContext.request.contextPath}/Product_add">product add
<a href=http://www.mamicode.com/"${pageContext.request.contextPath}/Product_update">product update
<a href=http://www.mamicode.com/"${pageContext.request.contextPath}/Product_delete">product delete
<a href=http://www.mamicode.com/"${pageContext.request.contextPath}/Product_search">product search
当访问book add时,这时的路径是 Book_add,那么对于struts.xml文件中.
第一个星就是 Book
第二个星就是 add
对于{1}Action---->BookAction
对于method={2}--->method=add
使用通配符来配置注意事项:
1.必须定义一个统一的命名规范。
2.不建议使用过多的通配符,阅读不方便。
3.动态方法调用(了解)
在struts.xml文件中<action name="book" class="cn.itcast.action.BookAction"></action>
访问时路径: http://localhost/struts2_day01_2/book!add
就访问到了BookAction类中的add方法。
对于book!add 这就是动态方法调用。
注意:struts2框架支持动态方法调用,是因为在default.properties配置文件中设置了动态方法调用为true.
struts.enable.DynamicMethodInvocation = true
在Struts框架中获取Servlet API
Struts2的Action没有与任何Servlet API耦合,便于测试
获取方式有以下几种:
方式1.通过ActionContext来获取
1.首先获取一个ActionContext对象。
ActionContext context=ActionContext.getContext();
2.获取Servlet API
注意:通过ActionContext获取的不是真正的Servlet API,而是一个Map集合
context.getApplication()
context.getSession()
context.getParameter();---得到的就相当于request.getParameterMap()
context.put(String,Object) 相当于request.setAttribute(String,String);
3.ActionContext常用方法:
context.getSession()
context.getParameter();---得到的就相当于request.getParameterMap()
context.put(String,Object) 相当于request.setAttribute(String,String);
3.ActionContext常用方法:
getContext():返回ActionContext实例对象
get(key):相当于HttpServletRequest的getAttribute(String name)方法
put(String,Object):相当于HttpServletRequest的setAttribute方法。
getApplication():返回一个Map对象,存取ServletContext属性。
getSession():返回一个Map对象,存取HttpSession属性。
getParameters():类似调用HttpServletRequest的getParameterMap()方法。
setApplication(Map):将该Map实例里的key-value保存为ServletContext的属性名、属性值。
setSession(Map):将该Map实例里的key-value保持为HttpSession的属性名、属性值。
方式2:注入方式获取(这种方式是真正的获取到了Servlet API)
1.要求action类必须实现指定接口
ServletContextAware:注入ServletContext对象。
ServletRequestAware:注入request对象。
ServletResponseAware:注入response对象。
2.重写接口中的方法
ServletContextAware — void setServletContext(javax.servlet.ServletContext context)
ServletRequestAware — void setServletRequest(javax.servlet.http.HttpServletRequest request)
ServletResponseAware — void setServletResponse(javax.servlet.http.HttpServletResponse response)
3.声明一个web对象,使用接口中的方法的参数对声明的web对象赋值
ServletRequestAware — void setServletRequest(javax.servlet.http.HttpServletRequest request)
ServletResponseAware — void setServletResponse(javax.servlet.http.HttpServletResponse response)
3.声明一个web对象,使用接口中的方法的参数对声明的web对象赋值
private HttpServletRequest request;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
分析其实现原理:
是使用struts2中的一个interceptor完成的.(通过Struts中默认拦截器中的一个ServletConfig拦截器进行注入的)
<interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
if (action instanceof ServletRequestAware) { //判断action是否实现了ServletRequestAware接口
HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST); //得到request对象.
((ServletRequestAware) action).setServletRequest(request);//将request对象通过action中重写的方法注入。
}
<interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
if (action instanceof ServletRequestAware) { //判断action是否实现了ServletRequestAware接口
HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST); //得到request对象.
((ServletRequestAware) action).setServletRequest(request);//将request对象通过action中重写的方法注入。
}
方式3: 通过ServletActionContext获取
ServletActionContext有以下几个静态方法:
static PageContext getPageContext()
static HttpServletRequest getRequest()
static ServletContext getServletContext()
该方案可避免Action类实现XxxAware接口,但Action依然与Servlet API直接耦合
开发中优先使用ActionContext 这样可以避免耦合
开发中优先使用ActionContext 这样可以避免耦合
处理配置处理结果Result
Action处理完用户请求后,将返回一个普通字符串
整个普通字符串就是一个逻辑视图名
Struts2 根据逻辑视图名,决定响应哪个结果
Struts2处理结果使用<result>元素配置
局部结果:将<result>作为<action>子元素配置
全局结果:将<result>作为<global-results>元素的子元素配置
配置<result>元素通常需要指定两个属性
name 该属性指定配置逻辑视图名 作用:与action中的method的返回值匹配 进行跳转
type 该属性指定结果类型 作用:是用于指定跳转方式
整个普通字符串就是一个逻辑视图名
Struts2 根据逻辑视图名,决定响应哪个结果
Struts2处理结果使用<result>元素配置
局部结果:将<result>作为<action>子元素配置
全局结果:将<result>作为<global-results>元素的子元素配置
配置<result>元素通常需要指定两个属性
name 该属性指定配置逻辑视图名 作用:与action中的method的返回值匹配 进行跳转
type 该属性指定结果类型 作用:是用于指定跳转方式
对于type的属性值有以下几种:
在struts-default.xml文件中定义了type可以取的值。
<result-types> <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/> <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/> <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/> <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/> <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/> <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/> <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/> <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/> <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" /> <result-types>
必须掌握的几个type属性值:
chain dispatcherredirect redirectAction stream
dispatcher:它代表的是请求转发,也是默认值。它一般用于从action跳转到页面。
chain:它也相当于请求转发。它一般情况下用于从一个action跳转到另一个action。
redirect:它代表的是重定向它一般从action跳转到页面。
redirectAction:它代表的是重定向 它一般用于从一个action跳转到另一个action。
stream:代表的是服务器端返回的是一个流,一般用于文件下载。
全局结果
当多个action中都使用到了相同result,这时我们应该把result定义为全局结果。struts1中提供了全局forward,struts2中也提供了相似功能:
<package ....>
<global-results>
<result name="message">/message.jsp</result>
</global-results>
</package>
注:局部的会覆盖全局
Struts1中应用范围内action的实例 action是单实例(执行时,现在缓存中查找实例,有用,没有创建新的实例)
Struts2中 应用范围内action的实例,每个请求都会创建一个action实例
Servlet属于单实例多线程的应用,实例只在初始化时被加载
多实例比单实例的优点,不会产生并发问题,但执行速度不如单实例
局部结果页面 和 全局结果页面 区别:
<package ....>
<global-results>
<result name="message">/message.jsp</result>
</global-results>
</package>
注:局部的会覆盖全局
Struts1中应用范围内action的实例 action是单实例(执行时,现在缓存中查找实例,有用,没有创建新的实例)
Struts2中 应用范围内action的实例,每个请求都会创建一个action实例
Servlet属于单实例多线程的应用,实例只在初始化时被加载
多实例比单实例的优点,不会产生并发问题,但执行速度不如单实例
局部结果页面 和 全局结果页面 区别:
<action name="result" class="cn.itcast.struts2.demo6.ResultAction">
<!-- 局部结果 当前Action使用 -->
<result name="success">/demo6/result.jsp</result>
</action>
<global-results>
<!-- 全局结果 当前包中 所有Action都可以用-->
<result name="success">/demo6/result.jsp</result>
</global-results>
<!-- 局部结果 当前Action使用 -->
<result name="success">/demo6/result.jsp</result>
</action>
<global-results>
<!-- 全局结果 当前包中 所有Action都可以用-->
<result name="success">/demo6/result.jsp</result>
</global-results>
代码示例剖析Struts2的配置
具体代码如下:
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> <init-param> <param-name>struts.action.extension</param-name> <param-value>do,,</param-value> </init-param> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
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> <constant name="struts.action.extension" value=http://www.mamicode.com/"def,,">>
struts.properties
struts.action.extension=abc,,BookAction
package cn.itcast.action; import com.opensymphony.xwork2.ActionSupport; public class BookAction extends ActionSupport { public String add(){ System.out.println("book add"); return NONE; } public String update(){ System.out.println("book update"); return NONE; } public String delete(){ System.out.println("book delete"); return NONE; } public String search(){ System.out.println("book search"); return NONE; } }
DefaultAction
package cn.itcast.action; import com.opensymphony.xwork2.ActionSupport; public class DefaultAction extends ActionSupport { @Override public String execute() throws Exception { // return null; 或return NONE; 会跳转一空白页面 System.out.println("DefaultAction execute Method......"); return SUCCESS; } }
DefaultAction2
package cn.itcast.action; import com.opensymphony.xwork2.ActionSupport; public class DefaultAction2 extends ActionSupport { @Override public String execute() throws Exception { // return null; 或return NONE; 会跳转一空白页面 System.out.println("DefaultAction2 execute Method......"); return SUCCESS; } }
HelloAction
package cn.itcast.action; public class HelloAction { public String say() { System.out.println("hello action say method"); return "good"; } public String write() { System.out.println("hello action write method"); return "hehe"; } }ProductAction
package cn.itcast.action; import com.opensymphony.xwork2.ActionSupport; public class ProductAction extends ActionSupport { public String add(){ System.out.println("product add"); return NONE; } public String update(){ System.out.println("product update"); return NONE; } public String delete(){ System.out.println("product delete"); return NONE; } public String search(){ System.out.println("product search"); return NONE; } }
ServletDemo1Action
package cn.itcast.action; import java.util.Map; import cn.itcast.utils.PrintMap; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; //获取Servlet API 通过ActionContext获取 public class ServletDemo1Action extends ActionSupport { public String execute() throws Exception { // 1.获取ActionContext ActionContext context = ActionContext.getContext(); // 2.获取Servlet API // 2.1获取application中的数据 Map<String, Object> applicationMap = context.getApplication(); PrintMap.print(applicationMap); // 2.2获取session中的数据 Map<String, Object> sessionMap = context.getSession(); PrintMap.print(sessionMap); // 2.3获取请求参数 Map<String, Object> paramMap = context.getParameters(); PrintMap.print(paramMap); // 2.4 向request范围存储数据 context.put("username", "tom"); return SUCCESS; } }ServletDemo2Action
package cn.itcast.action; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.interceptor.ServletRequestAware; import com.opensymphony.xwork2.ActionSupport; // 获取Servlet api 通过注入方式 public class ServletDemo2Action extends ActionSupport implements ServletRequestAware { private HttpServletRequest request; @Override public String execute() throws Exception { System.out.println(request.getParameter("username")); return null; } public void setServletRequest(HttpServletRequest request) { this.request = request; } }ServletDemo3Action
package cn.itcast.action; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import org.apache.struts2.interceptor.ServletRequestAware; import com.opensymphony.xwork2.ActionSupport; // 获取Servlet api 通过ServletActionContext获取 public class ServletDemo3Action extends ActionSupport { @Override public String execute() throws Exception { HttpServletRequest request=ServletActionContext.getRequest(); System.out.println(request.getParameter("username")); return null; } }PrintMap
package cn.itcast.utils; import java.util.Map; public class PrintMap { public static void print(Map<String, Object> map) { for (Map.Entry<String, Object> entry : map.entrySet()) { System.out.println(entry.getKey() + "——" + entry.getValue()); } System.out.println("————————————————————————"); } }
book.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 name="bookPackage" namespace="/b" extends="struts-default"> <!-- <action name="Book_add" class="cn.itcast.action.BookAction" method="add"></action> <action name="Book_update" class="cn.itcast.action.BookAction" method="update"></action> <action name="Book_delete" class="cn.itcast.action.BookAction" method="delete"></action> <action name="Book_search" class="cn.itcast.action.BookAction" method="search"></action> --> <action name="*_*" class="cn.itcast.action.{1}Action" method="{2}"></action> </package> </struts>
default.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> <!-- 自定义一个POJO类 --> <package name="pojoPackage" namespace="/" extends="struts-default"> <!-- 当前包下的默认Action 即当以namespace="/"开头的路径找不到时, 就会跳转 /hello 注意:只包含一级目录 例如:/www找不到时会跳转 如果/www/xx/aaa找不到时就会报错 --> <default-action-ref name="hello1"></default-action-ref> <action name="hello" class="cn.itcast.action.HelloAction" method="say"> <result name="good">/hello.jsp</result> </action> <action name="hello1" class="cn.itcast.action.HelloAction" method="write"> <result name="hehe">/hehe.jsp</result> </action> </package> <package name="defaultPackage" namespace="/a" extends="struts-default"> <default-action-ref name="default"></default-action-ref> <!-- 当前包下的Action默认处理类 如果不声明,则默认执行 com.opensymphony.xwork2.ActionSupport类 --> <default-class-ref class="cn.itcast.action.DefaultAction2"></default-class-ref> <!-- 继承自ActionSupport类 使用默认值 --> <action name="default" class="cn.itcast.action.DefaultAction"> <result>/default.jsp</result> </action> <action name="good"> <result>/good.jsp</result> </action> </package> </struts>
servlet.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 name="default" namespace="/" extends="struts-default"> <!-- 全局结果页面 --> <global-results> <result>/demo1_success.jsp</result> </global-results> <action name="demo1" class="cn.itcast.action.ServletDemo1Action"> <!-- 局部结果页面 --> </action> <action name="demo2" class="cn.itcast.action.ServletDemo2Action"> <!-- <result>/demo1_success.jsp</result> --> </action> <action name="demo3" class="cn.itcast.action.ServletDemo3Action"> <!-- <result type="redirect">/demo1_success.jsp</result> --> </action> </package> </struts>book.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘index.jsp‘ starting page</title> </head> <body> <a href=http://www.mamicode.com/"${pageContext.request.contextPath}/Book_add">book add
>
default.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘index.jsp‘ starting page</title> </head> <body> <h1>hello default</h1> </body> </html>
demo1.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘index.jsp‘ starting page</title> </head> <body> <% session.setAttribute("sname", "svalue"); application.setAttribute("aname", "avalue"); %> <a href=http://www.mamicode.com/"${pageContext.request.contextPath}/demo1">访问demo1servletAction>demo1_success.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘index.jsp‘ starting page</title> </head> <body> ${username} </body> </html>good.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘index.jsp‘ starting page</title> </head> <body> <h1>hello GOOD</h1> </body> </html>
hehe.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘index.jsp‘ starting page</title> </head> <body> <h1>hello 呵呵</h1> </body> </html>hello.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘index.jsp‘ starting page</title> </head> <body> <h1>hello Struts2</h1> </body> </html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘index.jsp‘ starting page</title> </head> <body> <a href=http://www.mamicode.com/"${pageContext.request.contextPath}/hello">第一次使用struts2>product.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘index.jsp‘ starting page</title> </head> <body> <a href=http://www.mamicode.com/"${pageContext.request.contextPath}/Product_add">product add
>
JAVAWEB开发之Struts2详解(一)——Struts2框架介绍与快速入门、流程分析与工具配置以及Struts2的配置以及Action和Result的详细使用
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。