首页 > 代码库 > Head-First Servelts&JSP reading note 3

Head-First Servelts&JSP reading note 3

<servlet>  <servlet-name>BeerParamTests</servlet-name>  <servlet-class>TestInitParams</servlet-class>  <init-param>    <param-name>adminEmail</param-name>    <param-value>likewecare@wickedlysmart.com</param-value>  </init-param></servlet>

web.xml中的片段。

这个片段针对的是TestInitParams这个servlet。

getServletConfig()能够获得这个servlet相关的信息。

getServletConfig().getInitParameter("adminEmail");

能够获得对应的paramValue——likewecare@wickedlysmart.com

 

当容器初始化一个Servlet的时候,会创建一个唯一对应的ServletConfig。

Container会从DD中读取相应的信息,绑定到这个ServletConfig对象上。

然后,调用Servlet类的init方法,把servletConfig对象的引用给Servlet对象。

 

ServletConfig对象的方法:

1 String getInitParameter(String);

2 Enumeration getInitParameterNames();  // Enumeration的一个实现类是StringTokenizer。。。

3 ServletContext getServletContext();

4 String getServletName();  // nearly with no use

 

 

<servlet>  <servlet-name>BeerParamTests</servlet-name>  <servlet-class>TestInitParams</servlet-class></servlet><context-param>  <param-name>adminEmail</param-name>  <param-value>clientheaderror@wickedlysmart.com</param-value></context-param>

web.xml中的片段。

ServletContext,属于整个web-app,而不是某一个servlet。

this.getServletContext().getInitParameter("adminEmail");

this.getServletConfig().getServletContext().getInitParameter("adminEmail");

BOTH RIGHT!!! If the servlet extends HttpServlet or GenericServlet.

 

ServletContext对象的方法:

1 String getInitParameter(String)

2 Enumeration getInitParameterNames();

3 Object getAttribute(String);

4 getAttributeNames();

5 setAttribute(String, Object);

6 removeAttribute(String);

7 getRequestDispatcher(String);

 

 

Listener

有的时候需要在某一个或某些事件执行之前去完成一些工作,或之后完成一些工作。

这个工作可以让每一个servlet去实现,但是显得累赘,这个时候可以把这些工作提取出来,交给一个Java类去完成,这个java类就是一个Listener。

 

ServletContextListener

监听ServletContext的动作的监听器

public class SomeServletContextListener implements ServletContextListener {  public void contextInitialized(ServletContextEvent event){    ServletContext sc = event.getServletContext;
    String some = sc.getInitParameter("some");
    Dog dog = new Dog(some);
    sc.setAttribute("dog", dog);
  }  public void contextDestoryed(ServletContextEvent event){    // NOTHING TO DO HERE~  }}

 

 

设置监听器,在web.xml中,追加

<listener>    <listener-class>xx.xx.SomeServletContextListener</listener-class></listener>

 

这样,Container就会去指定的位置寻找监听器类了,然后

 

Servlet类中,通过

Dog dog = (Dog) getServletContext().getAttribute(“dog”);

 

就可以获得这个dog对象了,注意强制类型转换。

 

 

其他类型的监听器:

ServletContextAttributeListener:用于监听ServletContext中的Attribute变动的。

  1. attributeAdded
  2. attributeRemoved
  3. attributeReplaced

HttpSessionListener:用于监听Session创建和销毁的,也就是说多少个用户在使用该程序。

  1. sessionCreated
  2. sessionDestroyed

ServletRequestListener:用于监听对该程序进行请求,以便对请求进行封装或者log情报打印等。

  1. requestInitialized
  2. requestDestroyed

等等。。。

ServletRequestAttributeListener

HttpSessionBindingListener

HttpSessionAttributeListener

HttpSessionActivationListener

 

所谓监听器,就是对某些东西进行监听,如追加,删除,变化,初始化和销毁。

 

Attribute的种类:ServletContext,HttpSession,HttpServletRequest

Parameter的种类:ServletContext init Parameter,Request Parameter,ServletConfig init Parameter

 

可以对Attribute进行设定,如this.getServletContext().setAttribute("Some", new Some());

但是不能对parameter进行修改。

 

可以获取Attribute和Parameter,但是Attribute的返回类型是Object,而Parameter返回类型是String,如:

Object o = request.getAttribute("Some");

String str = request.getParameter("Some");

String str = this.getServletConfig().getInitParameter("Some");

 

Attribute的存在的三个区域:

Context:ServletContext,对所有的用户可见;

Session:HttpSession,只对当前Session可见;

Request:ServletRequest,只对当前请求可见。

 

Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
Enumeration getAttributeNames()

 

Context Scope is not thread-safe

因为application的任何一个用户都可以新建一个servletcontext的一个attribute,当然也有修正和删除它的权利。

所以放到servletContext中的attribute不能保证其安全性。

syncronized(this.getServletContext) 能够保障其线程安全性。

 

HttpSession Scope is not thread-safe

synchronized(request.getSession());

 

HttpServletRequest Scope is thread-safe.

 

 

RequestDispatcher有两种获得方式,一种是通过request,一种是通过ServletContext

RequestDispatcher view = request.getRequestDispatcher(“result.jsp”);

RequestDispatcher view = getServletContext().getRequestDispatcher(“/result.jsp”);

注意:他俩是相当不同的!!!

request的方式的话,如果参数是以"/"开头的话,它回去该项目的root目录下去寻找该页面,否则他会去request的相对路径下去寻找页面。

servletContext,只能以用“/”开头的字符串作为参数!

之后就可以用这个view.forward(request, response);了。

 

You can’t forward the request if you’ve already committed a response!

public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {  response.setContentType(“application/jar”);  ServletContext ctx = getServletContext();  InputStream is = ctx.getResourceAsStream(“bookCode.jar”);  int read = 0;  byte[] bytes = new byte[1024];  OutputStream os = response.getOutputStream();  while ((read = is.read(bytes)) != -1) {    os.write(bytes, 0, read);  }  os.flush();  // cause an illegalStateException  RequestDispatcher view = request.getRequestDispatcher(“result.jsp”);  view.forward(request, response);  os.close();}