对于web中Context的理解

2018-07-30  本文已影响326人  onlyHalfSoul

在 java 中, 常见的 Context 有很多, 例如: ServletContext, ActionContext, ServletActionContext, ApplicationContext, PageContext, SessionContext ...

那么, Context 究竟是什么东西呢? 直译是上下文、环境的意思。

  1. context就是“容器”,放的就是应用程序的所有资源,要用时候就访问它,所以context里面的东西,在同一个应用程序里面是全局的;web上下文可以看成web应用的运行环境,一般用context名字来修饰,里面保存了web应用相关的一些设置和全局变量

  2. ServletContext,是一个全局的储存信息的空间,服务器开始,其就存在,服务器关闭,其才释放。request,一个用户可有多个;session,一个用户一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息;

  3. JavaWeb中的上下文环境概念就是:一个web服务启动后的整个服务中的所有内存对象和他们之间的关系组成的一种环境
    spring 上下文和spring mvc上下文和web应用上下文servletContext之间的关系

要想很好理解这三个上下文的关系,需要先熟悉spring是怎样在web容器中启动起来的。spring的启动过程其实就是其IoC容器的启动过程,对于web程序,IoC容器启动过程即是建立上下文的过程。

servletContext 是web应用程序的大环境,用于存储整个web应用程序级别的对象.

  1. Spring上下文(ApplicationContext)
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
ClassName clazz =(ClassName)ctx.getBean("beanName");
ApplicationContext ctx = new FileSystemXmlApplicationContext("src/applicationContext.xml");
ClassName clazz =(ClassName)ctx.getBean("beanName");
HttpSession session = request.getSession();
ServletContext context = session.getServletContext(); //arg0.getSession().getServletContext();

ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(context);
ClassName clazz = (ClassName)ctx.getBean("beanName");

上面两个工具方式的区别是,前者在获取失败时抛出异常,后者返回null。

import org.springframework.context.support.ApplicationObjectSupport;
 
public class ContextOne extends ApplicationObjectSupport
{
    ......
}
........
ContextOne one = new ContextOne();
  one.getApplicationContext();
import org.springframework.web.context.support.WebApplicationObjectSupport;
public class ContextOne extends WebApplicationObjectSupport {
   .......
}
........
ContextOne one = new ContextOne();
 one.getApplicationContext();
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
//通过接口ApplicationContextAware获得spring上下文
public class Context implements ApplicationContextAware {
 private static ApplicationContext ctx;
//设置ApplicationContext对象
 public void setApplicationContext(ApplicationContext context)
   throws BeansException {
  // TODO Auto-generated method stub
   ctx=context;
 }
 //通过beanName获得实例
 public static Object getBean(String beanName)
 {
  return ctx.getBean(beanName);
 }
}

web中的几种Context

ServletContext

一个 WEB 运用程序只有一个 ServletContext 实例, 它是在容器(包括 JBoss, Tomcat 等)完全启动 WEB 项目之前被创建, 生命周期伴随整个 WEB 运用。

当在编写一个 Servlet 类的时候, 首先是要去继承一个抽象类 HttpServlet, 然后可以直接通过 getServletContext() 方法来获得 ServletContext 对象。

这是因为 HttpServlet 类中实现了 ServletConfig 接口, 而 ServletConfig 接口中维护了一个 ServletContext 的对象的引用。

利用 ServletContext 能够获得 WEB 运用的配置信息, 实现在多个 Servlet 之间共享数据等。

<?xml version="1.0" encoding="UTF-8"?>

  <context-param>
    <param-name>url</param-name>
    <param-value>jdbc:oracle:thin:@localhost:1521:ORC</param-value>
  </context-param>
  <context-param>
    <param-name>username</param-name>
    <param-value>scott</param-value>
  </context-param>
  <context-param>
    <param-name>password</param-name>
    <param-value>tigger654321</param-value>
  </context-param>
  
  <servlet>
    <servlet-name>ConnectionServlet</servlet-name>
    <servlet-class>net.yeah.fancydeepin.servlet.ConnectionServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ConnectionServlet</servlet-name>
    <url-pattern>/ConnectionServlet.action</url-pattern>
  </servlet-mapping>
  
  <servlet>
    <servlet-name>PrepareConnectionServlet</servlet-name>
    <servlet-class>net.yeah.fancydeepin.servlet.PrepareConnectionServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>PrepareConnectionServlet</servlet-name>
    <url-pattern>/PrepareConnectionServlet.action</url-pattern>
  </servlet-mapping>

</web-app>
package net.yeah.fancydeepin.servlet;

import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class PrepareConnectionServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public void init() throws ServletException {
        
        ServletContext context = getServletContext();
        String url = context.getInitParameter("url");
        String username = context.getInitParameter("username");
        String password = context.getInitParameter("password");
        context.setAttribute("url", url);
        context.setAttribute("username", username);
        context.setAttribute("password", password);
    }

    protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
        
        doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        response.sendRedirect("ConnectionServlet.action");
    }
}
package net.yeah.fancydeepin.servlet;

import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

public class ConnectionServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        
        ServletContext context = getServletContext();
        System.out.println("***************************************");
        System.out.println("URL: " + context.getAttribute("url"));
        System.out.println("Username: " + context.getAttribute("username"));
        System.out.println("Password: " + context.getAttribute("password"));
        System.out.println("***************************************");
        super.service(request, response);
    }
}

当访问 PrepareConnectionServlet.action 时, 后台打印输出:

***********************************************
URL:  jdbc:oracle:thin:@localhost:1521:ORC
Username:  scott
Password:  654321
***********************************************

ActionContext

ActionContext 是当前 Action 执行时的上下文环境, ActionContext 中维护了一些与当前 Action 相关的对象的引用, 如: Parameters (参数), Session (会话), ValueStack (值栈), Locale (本地化信息) 等。
在 Struts1 时期, Struts1 的 Action 与 Servlet API 和 JSP 技术的耦合度都很紧密, 属于一个侵入式框架:

public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response){
    // TODO Auto-generated method stub
    return null;
}

到了 Struts2 时期, Struts2 的体系结构与 Struts1 之间存在很大的不同。Struts2 在 Struts1 的基础上与 WebWork 进行了整合, 成为了一个全新的框架。
在 Struts2 里面, 则是通过 WebWork 来将与 Servlet 相关的数据信息转换成了与 Servlet API 无关的对象, 即 ActionContext 对象。
这样就使得了业务逻辑控制器能够与 Servlet API 分离开来。另外, 由于 Struts2 的 Action 是每一次用户请求都产生一个新的实例, 因此, ActionContext 不存在线程安全问题, 可以放心使用。

package net.yeah.fancydeepin.action;

import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;

public class ContextAction extends ActionSupport {

    private static final long serialVersionUID = 1L;
    private String username;
    private String password;

    public String execute(){
        
        ActionContext context = ActionContext.getContext();
        ValueStack value = context.getValueStack();
        value.set("username", username);
        value.set("password", password);
        Map<String, Object> session = context.getSession();
        session.put("url", "http://www.blogjava.net/fancydeepin");
        return SUCCESS;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
<s:property value="username"/><BR>
<s:property value="password"/><BR>
<s:property value="#session.url"/><BR>

当访问 context.action 并传给相应的参数的时候, 在浏览器中会输出相应的信息。

留意到上面 Struts2 的 Action 中并有没添加属性的 getting 方法, 而是手动的将参数值放到值栈(ValueStack)中的, 否则页面是得不到参数来输出的。

ServletActionContext

首先, ServletActionContext 是 ActionContext 的一个子类。ServletActionContext 从名字上来看, 意味着它与 Servlet API 紧密耦合。

ServletActionContext 的构造子是私有的, 主要是提供了一些静态的方法, 可以用来获取: ActionContext, ActionMapping, PageContext,

HttpServletRequest, HttpServletResponse, ServletContext, ValueStack, HttpSession 对象的引用。

public String execute(){
        
    //或 implements ServletRequestAware
    HttpServletRequest request = ServletActionContext.getRequest();
    //或 implements ServletResponseAware
    HttpServletResponse response = ServletActionContext.getResponse();
    //或 implements SessionAware
    HttpSession session = request.getSession();
    //或 implements ServletContextAware
    ServletContext context = ServletActionContext.getServletContext();
        
    return SUCCESS;
}

DispatcherServlet

https://www.jianshu.com/p/1a163a6b98a5

上一篇下一篇

猜你喜欢

热点阅读