shtuts框架精讲
程序员文章站
2022-04-11 18:44:57
...
Struts
请求转发-通过Demo01Action 请求转发到 jump.jsp
Demo01Action
大写的SUCCESS的值为字符串"success" 在底层文件中SUCCESS = "success"
所以 return SUCCESS 相当于 return "success"
package com.lanou3g.jump;
import com.opensymphony.xwork2.ActionSupport;
public class Demo01Action extends ActionSupport{
@Override
public String execute() throws Exception {
System.out.println("Demo01Action");
return SUCCESS;
}
}
web.xml
web中需要配置过滤器 在使用action的过程中,无序再为每个类配置servlet,只要配置一个过滤器集合
url-parttern 中写 /* 代表拦截所有的路径 而不是拦截某一个路径 每个action
在经过一个拦截器时,便具备了这个拦截器中的功能
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>sh-struts2-03</display-name>
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
struts.xml
一些xml不支持插入<!DOCTYPE.....>这段内容 显示错误,但是没有关系,即使这一点显示为错误
程序任然可以正常运行 并输出理想的结果 虽然删掉这句错误会消失 但这句话是不可删除的
第一个name可以随便起名 namespace为命名区间,为/时,可以忽略namespace的存在
但如果/后跟的有内容 在通过网址访问时 便需要先写上namespace中的路径 再写
第二个name中的值 extends后的内容为固定的,不可更改 和struts框架底层代码有关联
class后跟的是全限定类名 和具体包中的类产生关联 method是这个类中的方法
该方法为继承父类中的方法 方法名为固定的 用result中的name接收该方法中的返回
值,返回值不一定非要写"success" 只要方法中的返回值和result中的name的值对应上就行
<?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="test" namespace="/" extends="struts-default" >
<action name="demo01Action" class="com.lanou3g.jump.Demo01Action" method="execute">
<result name="success" type="dispatcher" >/jump.jsp</result>
</action>
</package>
</struts>
小结:请求转发
请求转发 使用dispactcher 使用
<result name="success" type="dispatcher" >/jump.jsp</result>
转发到具体的路径中去 只要路径有效 可以去到任何地方 包括servlet html action类
写的时候 代码不要写错了!!!!
请求重定向-Demo02Action定向到jump.jsp
在同一个工程下 配置一次过滤器即可 虽然建立了不同的类 但在前一个类已经配置的基础上
web.xml文件已经不需要再添写任何配置了 一次过滤器 可以用到项目结束 相比
servlet,每个类都需要配置一次,功能上提升了很多,减少了代码的书写
在前一个类已经配置了struts.xml的前提下,这次只需要复制粘贴一下package标签中的action即可,然后对里面的
内容稍作小改 使用关键字redirect
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="test" namespace="/" extends="struts-default" >
<action name="demo01Action" class="com.lanou3g.jump.Demo01Action" method="execute">
<result name="success" type="dispatcher" >/jump.jsp</result>
</action>
<action name="demo02Action" class="com.lanou3g.jump.Demo02Action" method="execute">
<result name="success" type="redirect" >/jump.jsp</result>
</action>
</package>
</struts>
Demo02Action
package com.lanou3g.jump;
import com.opensymphony.xwork2.ActionSupport;
public class Demo02Action extends ActionSupport{
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println("Demo02Action");
return "success";
}
}
通过Demo03Action 请求重定向 到 Demo01Action
从Demo03Action类重定向到Demo01Action 再从Demo01 请求转发到 jump.jsp
Demo03Action
package com.lanou3g.jump;
import com.opensymphony.xwork2.ActionSupport;
public class Demo03Action extends ActionSupport{
@Override
public String execute() throws Exception {
System.out.println("Demo03Action");
return "China";
}
}
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="test" namespace="/" extends="struts-default" >
<action name="demo01Action" class="com.lanou3g.jump.Demo01Action" method="execute">
<result name="success" type="dispatcher" >/jump.jsp</result>
</action>
<action name="demo02Action" class="com.lanou3g.jump.Demo02Action" method="execute">
<result name="success" type="redirect" >/jump.jsp</result>
</action>
<action name="demo03Action" class="com.lanou3g.jump.Demo03Action" method="execute">
<result name="China" type="redirect" >/demo01Action</result>
</action>
</package>
</struts>
重定向的另一种方式(常用)
actionName为你要去往的名字
namespace为命名空间 和package里的命名空间(namespace)内容要一致
<action name="demo03Action" class="com.lanou3g.jump.Demo03Action" method="execute">
<result name="China" type="redirectAction" >
<param name="actionName">demo01Action</param>
<param name="namespace">/</param>
</result>
</action>
通过Demo04Action 请求转发到Demo01Action
通过Demo04Action 请求转发到Demo01Action 再由Demo01Action请求转发到jump.jsp
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="test" namespace="/" extends="struts-default" >
<action name="demo01Action" class="com.lanou3g.jump.Demo01Action" method="execute">
<result name="success" type="dispatcher" >/jump.jsp</result>
</action>
<action name="demo02Action" class="com.lanou3g.jump.Demo02Action" method="execute">
<result name="success" type="redirect" >/jump.jsp</result>
</action>
<action name="demo03Action" class="com.lanou3g.jump.Demo03Action" method="execute">
<result name="China" type="redirectAction" >
<param name="actionName">demo01Action</param>
<param name="namespace">/</param>
</result>
</action>
<action name="Demo04Action" class="com.lanou3g.jump.Demo04Action" method="execute" >
<!-- chain Action直接进行转发 -->
<result name="success" type="chain">
<param name="actionName">Demo01Action</param>
<param name="namespace">/</param>
</result>
</action>
</package>
</struts>
Demo04Action
package com.lanou3g.jump;
import com.opensymphony.xwork2.ActionSupport;
public class Demo04Action extends ActionSupport{
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println("Demo04Action");
return SUCCESS;
}
}
获取servletAPI
ActionContext 对象(数据大管家) 内部也是个map集合
ActionContext的生命周期 是跟谁 请求对象(request)走的
如果request对象被销毁 其他对象任然会存在
Servlet 线程不安全(访问共享数据 会发生问题)
整个程序 系统只帮你创建一次 所以多个用户会共用一个servlet
Struts3 线程安全的 如何做到的?
每当有一个用户访问 Struts2就会给你创建一个ActionContext对象
ActionContext对象 可以获取以下对象和域
request对象
response对象
session对象
servletContext对象
requestScope 域 map
sessionScope 域 map
applicationScope 域 map
获取方式一 测试:Demo05Action
Demo05Action中获取域 并给域赋值 然后通过struts.xml中的配置信息 转发到 scope.jsp
在scope.jsp中 将内容输出
package com.lanou3g.servletapi;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class Demo05Action extends ActionSupport{
@Override
public String execute() throws Exception {
Map<String, Object> requestScope = (Map<String, Object>) ActionContext.getContext().get("request");
requestScope.put("name", "我是request");
Map<String, Object> session = ActionContext.getContext().getSession();
session.put("name", "我是session");
Map<String, Object> application = ActionContext.getContext().getApplication();
application.put("name", "我是application");
return SUCCESS;
}
}
<action name="demo05Action" class="com.lanou3g.servletapi.Demo05Action" method="execute">
<result name="success" type="dispatcher" >/scope.jsp</result>
</action>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
requestScope: ${requestScope.name } <br/>
session: ${session.name } <br/>
application: ${application.name }
<br/>
</body>
</html>
获取方式二 测试:Demo06Action
获取原生servlet对象
<action name="demo06Action" class="com.lanou3g.servletapi.Demo06Action" method="execute">
<result name="success" type="dispatcher" >/scope.jsp</result>
</action>
<body>
request: ${request.name } <br/>
session: ${session.name } <br/>
application: ${application.name }
<br/>
</body>
public class Demo06Action extends ActionSupport{
@Override
public String execute() throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("name", "我是request");
HttpSession session = request.getSession();
session.setAttribute("name", "我是session");
HttpServletResponse response = ServletActionContext.getResponse();
ServletContext application = ServletActionContext.getServletContext();
application.setAttribute("name", "我是appilcation");
return SUCCESS;
}
}
查看jar包的底层文件 可以发现 第二种的实现方式是依赖于第一种实现方式的 第二种实现方式更方便于懂servlet
jsp的人了解使用 可见虽然底层实现一样 但为了不同的人群 设置了不同的实现方法
获取方式三 测试:Demo07Action
package com.lanou3g.servletapi;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.interceptor.ServletRequestAware;
import com.opensymphony.xwork2.ActionSupport;
/*
* 通过实现接口的方式
*/
public class Demo07Action extends ActionSupport implements ServletRequestAware{
private HttpServletRequest request;
public Demo07Action() {
System.out.println("Demo07Action 创建了");
}
@Override
public String execute() throws Exception {
// 直接使用成员变量
this.request.setAttribute("name", "jiekou");
return SUCCESS;
}
// 接口中的方法
@Override
public void setServletRequest(HttpServletRequest request) {
// TODO Auto-generated method stub
// 使用成员变量赋值的方式得到servlet对象
this.request = request;
}
}
<action name="demo07Action" class="com.lanou3g.servletapi.Demo07Action" method="execute">
<result name="success" type="dispatcher" >/scope.jsp</result>
</action>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
request: ${request.name } <br/>
</body>
</html>
结果截图
结果分析
Demo07Action 继承了 ActionSupport类 重写了里面的 execute()方法 同时 Demo07Action
实现了 ServletRequestAware 类 所以又实现了里面的 setServletRequest()方法 这个方法有
个返回值 返回值类型为HttpServletRequest, 所以用HttpServletRequest 类的对象来解释这个返回值
另一个问题就是 execute() 方法 与 setServletRequest() 方法谁先执行 谁后执行的问题
setServletRequest()方法是和过滤器有联系的 在struts-default.xml文档中 第205行 显示为
<interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
打开和它关联的底层文件java代码 发现如下图所示代码 方法intercept的意思为拦截过滤的意思
也就是说当我们提交访问的时候 会先触发过滤器 也就是intercept方法 该方法会在我们的类中
查找有没有ServletRequestAware类以及ServletResponseAware等类的实例化对象 instance of 方法
用来判断该对象是不是属于这个类的 如果是属于其中的那个类 则 根据这个类中的方法 即 setServletRequest(request)
或者 ((ServletResponseAware) action).setServletResponse(response)等方法 将对象直接返回去
我们在自己的方法中无需创建对象 只需要接收即可
如果我们需要 HttpServletResponse类的对象 则 实现ServletResponseAware接口即可 底层实现中
也是通过第一种方式的底层实现 获取到 该对象 转了好几个弯 再把对象返回给我们 不过这些弯对我们也可以说是透明的
总的来说 这三种方法的最低层实现是一样的 为了方便我们编写代码 或者 说给我们更多的选择 让我们有多种方式获取对象
另外 根据上述访问三次打印出的结果可以看出 每次访问的时候都新创建了一个对象 所有是线程安全的
上一篇: SPFA算法精讲
下一篇: 查看Linux系统资源命令