Struts2学习(五)【访问servletAPI方式】
2017-10-24 16:44
429 查看
一、原理
每次请求时,都会创建一个与请求对应的 ActionContext对象。请求完成会销毁ActionContext.
ActionContext创建好以后,与当前线程绑定,我们需要的时候从 ThreadLocal中去就行了。
ActionContext中存储着多个域的对象,已经请求和响应的对象。
public class ActionContext implements Serializable { static ThreadLocal<ActionContext> actionContext = new ThreadLocal<>(); ......... private Map<String, Object> context; .... public ActionContext(Map<String, Object> context) { this.context = context; } public void setActionInvocation(ActionInvocation actionInvocation) { put(ACTION_INVOCATION, actionInvocation); } public ActionInvocation getActionInvocation() { return (ActionInvocation) get(ACTION_INVOCATION); } public void setApplication(Map<String, Object> application) { put(APPLICATION, application); } public Map<String, Object> getApplication() { return (Map<String, Object>) get(APPLICATION); } public static void setContext(ActionContext context) { actionContext.set(context); } public static ActionContext getContext() { return actionContext.get(); } public void setContextMap(Map<String, Object> contextMap) { getContext().context = contextMap; } public Map<String, Object> getContextMap() { return context; } public void setConversionErrors(Map<String, Object> conversionErrors) { put(CONVERSION_ERRORS, conversionErrors); } public Map<String, Object> getConversionErrors() { Map<String, Object> errors = (Map) get(CONVERSION_ERRORS); if (errors == null) { errors = new HashMap<>(); setConversionErrors(errors); } return errors; } ............. public void setParameters(HttpParameters parameters) { put(PARAMETERS, parameters); } public HttpParameters getParameters() { return (HttpParameters) get(PARAMETERS); } public void setSession(Map<String, Object> session) { put(SESSION, session); } public Map<String, Object> getSession() { return (Map<String, Object>) get(SESSION); } public void setValueStack(ValueStack stack) { put(VALUE_STACK, stack); } public ValueStack getValueStack() { return (ValueStack) get(VALUE_STACK); } public void setContainer(Container cont) { put(CONTAINER, cont); } ....... public Object get(String key) { return context.get(key); } public void put(String key, Object value) { context.put(key, value); } }
二、通过ActionContext访问
2.1 分析
由上面的分析我们可以知道,我们可以通过当前线程的 ActionContext获取到我们域对象。例如我们获取 Session域,我们可以通过
Map<String, Object> sessionScope = ActionContext.getContext().getSession();
其他方式的域获取也是一样的。
我们也可以看看主要的的方法
public class ActionContext implements Serializable { static ThreadLocal<ActionContext> actionContext = new ThreadLocal<>(); ......... private Map<String, Object> context; .... public Map<String, Object> getApplication() { return (Map<String, Object>) get(APPLICATION); } public static ActionContext getContext() { return actionContext.get(); } public Map<String, Object> getContextMap() { return context; } public Map<String, Object> getSession() { return (Map<String, Object>) get(SESSION); } public Object get(String key) { return context.get(key); } }
这里面我们获取 session域和application域客户通过上面的方法。但是我们的 request 域就有点特殊了。
根据上面的方法中,我们看不到直接获取 request域的的方法呀?怎么来实现呢,我们知道上面这里个域的获取其实都是通过 键来获取的,那么我们的思路也就来了,我们可以通过 request域的键来获取request域。如下
//request域=> map (struts2并不推荐使用原生request域) Map<String,Object> requestScope = (Map<String,Object>)ActionContext.getContext().get("request");
但是Struts2并不推荐这么做,我们的ActionContext对象和request的生命周期是一样的,实际上我们的值可以存在 ActionContext 对象中。这一点我们可以去到我们和核心过滤器中证明。查找到我们的核心过滤器 StrutsPrepareAndExecuteFilter,查找到我们的 doFilter方法
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; ............ //对request见此进行了包装,修改了取值方式 //先从原生request中查找,然后还会从ActionContext中查找 request = prepare.wrapRequest(request); ...... }
2.2 获取域对象
根据上面的分析,我们知道了如果我们我们想要获取 session域和application域可以通过ActionContext,如果我们想要获取request域的话,那么我们可以把ActionContext当做request域来使用。例如
//session域 map Map<String, Object> sessionScope = ActionContext.getContext().getSession(); // application域 map Map<String, Object> applicationScope = ActionContext.getContext().getApplication(); //request域存值 ActionContext.getContext().put("name","request_wiming");
2.3 DemoApi1Action
package com.qwm.struts2_2.b_api; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import java.util.Map; /** * @author: wiming * @date: 2017-09-18 16:50:34 星期一 * @decription: * 第一种方式获取 */ public class DemoApi1Action extends ActionSupport{ @Override public String execute() throws Exception { /* static ThreadLocal<ActionContext> actionContext = new ThreadLocal<>(); (Map<String, Object>) get(SESSION); */ //session域 map Map<String, Object> sessionScope = ActionContext.getContext().getSession(); // application域 map Map<String, Object> applicationScope = ActionContext.getContext().getApplication(); //request域=> map (struts2并不推荐使用原生request域) //Map<String,Object> requestScope = (Map<String,Object>)ActionContext.getContext().get("request"); //推荐 // ActionContext和 request域的生命周期是一样的 // 全局过滤器包装了原生的request,主要就是改变了取值的时候,先从原生request中查找,然后还会从ActionContext中查找 ActionContext.getContext().put("name","request_wiming_test1"); sessionScope.put("name","session_wiming_test1"); applicationScope.put("name","application_wiming_test1"); return SUCCESS; } }
2.4 api.jsp
<%-- Created by IntelliJ IDEA. User: qiwenming Date: 2017/9/18 Time: 17:11 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>原生ServletApi取值</title> </head> <body> request: ${requestScope.name}<br><br> session: ${sessionScope.name}<br><br> application: ${applicationScope.name}<br> </body> </html>
2.5 配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <package name="apidemo" namespace="/apidemo" extends="struts-default"> <action name="Api1Action" class="com.qwm.struts2_2.b_api.DemoApi1Action" method="execute"> <result name="success">/api.jsp</result> </action> </package> </struts>
2.6 图示
)
三、通过ServletActionContext访问
3.1 分析与访问对象
通过ServletActionContext访问,我们直接调用它提供的方法就可以访问到里面的我们需要的域对象了。如下
//原生request HttpServletRequest request = ServletActionContext.getRequest(); //原生response HttpServletResponse response = ServletActionContext.getResponse(); //原生session HttpSession session = ServletActionContext.getRequest().getSession(); //原生servlerContext ServletContext servletContext = ServletActionContext.getServletContext();
具体我们可以看看,他里面的方法是怎么时候实现的。
ServletActionContext
public class ServletActionContext extends ActionContext implements StrutsStatics { .............. public static PageContext getPageContext() { return (PageContext) ActionContext.getContext().get(PAGE_CONTEXT); } public static HttpServletRequest getRequest() { return (HttpServletRequest) ActionContext.getContext().get(HTTP_REQUEST); } public static HttpServletResponse getResponse() { return (HttpServletResponse) ActionContext.getContext().get(HTTP_RESPONSE); } public static ServletContext getServletContext() { return (ServletContext) ActionContext.getContext().get(SERVLET_CONTEXT); } .............. }
我们发现其实它里面是去调用 我们的 ActionContext的get方法,最终的实现和我们的前面一种方式是一样的
3.2 demo
package com.qwm.struts2_2.b_api; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.ServletActionContext; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.util.Map; /** * @author: wiming * @date: 2017-09-18 16:50:34 星期一 * @decription: * 第二种方式获取 不推荐 */ public class DemoApi2Action extends ActionSupport{ @Override public String execute() throws Exception { //原生request // 内部调用 ActionContext.getContext().get(HTTP_REQUEST) HttpServletRequest request = ServletActionContext.getRequest(); //原生response HttpServletResponse response = ServletActionContext.getResponse(); //原生session HttpSession session = ServletActionContext.getRequest().getSession(); //原生servlerContext ServletContext servletContext = ServletActionContext.getServletContext(); request.setAttribute("name","request_wiming_test2"); session.setAttribute("name","session_wiming_test2"); servletContext.setAttribute("name","application_wiming_test2"); return SUCCESS; } }
3.4 配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <package name="apidemo" namespace="/apidemo" extends="struts-default"> <action name="Api2Action" class="com.qwm.struts2_2.b_api.DemoApi2Action" method="execute"> <result name="success">/api.jsp</result> </action> </package> </struts>
3.4 图示
四、通过实现接口方式访问
4.1 分析
通过接口的方式访问,主要是通过实现 Aware结尾的接口来实现的。 实现我们setXXX方法,保存我们我们需要的对象,然后就可以访问了。例如
public class DemoApi3Action extends ActionSupport implements ServletRequestAware{ private HttpServletRequest request; public String execute() throws Exception{ //这里就可以使用那我们的request了 //原生session HttpSession session = request.getSession(); return SUCCESS; } @Override public void setServletRequest(HttpServletRequest request) { this.request = request; } }
那么这个功能是怎么完成的呢?这其实是拦截器做的。打开默认配置文件 struts2-core-2.5.13.jar!\struts-default.xml
struts-default.xml
..... <struts> ..... <package name="struts-default" abstract="true" strict-method-invocation="true"> ..... <interceptors> ........ <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/> <interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/> <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/> .... <interceptor-stack name="defaultStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="i18n"/> ............ </interceptor-stack> ......... </interceptors> <default-interceptor-ref name="defaultStack"/> <default-class-ref class="com.opensymphony.xwork2.ActionSupport" /> <global-allowed-methods>execute,input,back,cancel,browse,save,delete,list,index</global-allowed-methods> </package> </struts>
产生这个作用的拦截器的是在配置中的 servletConfig,它对应的类是
org.apache.struts2.interceptor.ServletConfigInterceptor
我们来看看它的 intercept方法
public class ServletConfigInterceptor extends AbstractInterceptor implements StrutsStatics { .... public String intercept(ActionInvocation invocation) throws Exception { final Object action = invocation.getAction(); final ActionContext context = invocation.getInvocationContext(); if (action instanceof ServletRequestAware) { HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST); ((ServletRequestAware) action).setServletRequest(request); } ....省略的部分根据实现不同的接口来给不同的参数赋值... return invocation.invoke(); } }
通过
((ServletRequestAware)action).setServletRequest(request);
就把request对象传递到了我们的 DemoApi3Action中了,然后我们就可以尽情的玩耍了。
4.2 DemoApi3Action
package com.qwm.struts2_2.b_api; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.interceptor.ServletRequestAware; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * @author: wiming * @date: 2017-09-18 17:37:20 星期一 * @decription: * 第三种方式获取 * 想要获取多个,就是实现多个域 */ public class DemoApi3Action extends ActionSupport implements ServletRequestAware{ private HttpServletRequest request; public String execute() throws Exception{ //原生session HttpSession session = request.getSession(); //原生servlerContext ServletContext servletContext = request.getServletContext(); request.setAttribute("name","request_wiming_test3"); session.setAttribute("name","session_wiming_test3"); servletContext.setAttribute("name","application_wiming_test3"); return SUCCESS; } @Override public void setServletRequest(HttpServletRequest request) { this.request = request; } }
4.3 配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <package name="apidemo" namespace="/apidemo" extends="struts-default"> <action name="Api3Action" class="com.qwm.struts2_2.b_api.DemoApi3Action" method="execute"> <result name="success">/api.jsp</result> </action> </package> </struts>
4.4 图示
相关文章推荐
- JAVAEE学习——struts2_02:结果跳转方式、访问servletAPI方式、获得参数以及封装、练习:添加客户
- Struts2的Action中访问servletAPI方式
- [原创]java WEB学习笔记55:Struts2学习之路---详解struts2 中 Action,如何访问web 资源,解耦方式(使用 ActionContext,实现 XxxAware 接口),耦合方式(通过ServletActionContext,通过实现 ServletRequestAware, ServletContextAware 等接口的方式)
- Struts2访问ServletAPI的三种方式,以及使用推荐对比
- Struts2的Action访问ServletAPI的方式
- SSH与SSM学习之Struts205——访问servletAPI方式
- struts2访问servletAPI的几种方式
- Java EE SSH框架之Struts2(3)—— 结果跳转方式和访问ServletAPI方式
- struts2学习笔记--总结获取servletAPI的几种方式
- struts2学习之访问Servlet对象的两种实现方式
- struts2学习(11)——action访问ServletAPI
- java struts2入门学习实例--将客户端IP地址和访问方式输出到浏览器
- Struts2访问ServletAPI的三种方式
- Struts2中访问ServletAPI的四种方式
- Struts2 - Struts访问ServletAPI和OGNL学习(从零开始学习Strust2_07)
- Android学习 —— 数据的存储与访问方式四: ContentProvider
- Struts2学习(第六篇)——获取servletAPI和封装表单数据
- Struts2学习笔记----访问Servlet API
- Struts2的Action访问Session对象的两种方式及原理
- Struts2 Action访问web元素的四种方式