servlet 執行順序


public class TestServelt {
    
    public static void main(String[] args) {
        ChildServlet childServlet = new ChildServlet();
        childServlet.service();
    }

}


class FatherServlet{
    
    public void service(){
        System.out.println("父類service");
        doGet();
        
    }
    public void doGet(){
        System.out.println("父類goGet");
    }
    
}


class ChildServlet extends FatherServlet{
    
    public void service(){
        System.out.println("子類service");
        super.service();
        
    }
    public void doGet(){
        System.out.println("子類goGet");
    }
    
}

1、初始化階段  調用init()方法

 

2、響應客戶請求階段。調用service()方法,由service()方法根據提交的方式選擇執行doGet()或者doPost()方法

 

3、終止階段  調用destroy()方法--關閉tomcat的時候

<servlet>
      <servlet-name>myServlet</servlet-name>
      <servlet-class>com.myServlet</servlet-class>
      <load-on-startup>1</load-on-startup>   啟動tomcat的時候初始化當前servlet 調用init,數字越小越先加載
</servlet>

 

<context-param>
           <param-name>context/param</param-name>
           <param-value>avalible during application</param-value>
  </context-param>

參數通過getServletContext().getInitParameter("context/param")獲取

<servlet>
    <servlet-name>MainServlet</servlet-name>
    <servlet-class>com.wes.controller.MainServlet</servlet-class>
    <init-param>
       <param-name>param1</param-name>
       <param-value>avalible in servlet init()</param-value>
    </init-param>
    <load-on-startup>0</load-on-startup>
</servlet>

只能在servlet的init()方法中通過this.getInitParameter("param1")獲取

 

Servlet不是線程安全的。

要解釋為什么Servlet為什么不是線程安全的,需要了解Servlet容器(即Tomcat)使如何響應HTTP請求的。

當Tomcat接收到Client的HTTP請求時,Tomcat從線程池中取出一個線程,之后找到該請求對應的Servlet對象並進行初始化,之后調用service()方法。要注意的是每一個Servlet對象再Tomcat容器中只有一個實例對象,即是單例模式。如果多個HTTP請求請求的是同一個Servlet,那么着兩個HTTP請求對應的線程將並發調用Servlet的service()方法。

上圖中的Thread1和Thread2調用了同一個Servlet1,所以此時如果Servlet1中定義了實例變量或靜態變量,那么可能會發生線程安全問題(因為所有的線程都可能使用這些變量)。

比如下面的Servlet中的 name 和 i變量就會引發線程安全問題。

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadSafeServlet extends HttpServlet {

    public static String name = "Hello";   //靜態變量,可能發生線程安全問題
    int i;  //實例變量,可能發生線程安全問題
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

    @Override
    public void init() throws ServletException {
        super.init();
        System.out.println("Servlet初始化");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.printf("%s:%s[%s]\n", Thread.currentThread().getName(), i, format.format(new Date()));
        i++;
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("%s:%s[%s]\n", Thread.currentThread().getName(), i, format.format(new Date()));
        resp.getWriter().println("<html><body><h1>" + i + "</h1></body></html>");
    }
}

在Tomcat中啟動這個Servlet並在瀏覽器發起多個HTTP訪問,最后會發現變量 i 是多線程共享的。

如果需要更加深入透徹地了解Tomcat接收HTTP的細節,以及與Servlet交互的細節,可以深入看看Tomcat的架構和源碼。

jsp 9大內置對象

1.request對象
2.response對象
3.session對象
4.out對象
  1. out對象是JspWriter類的實例,是向客戶端輸出內容常用的對象

  5.page對象

  1. page對象就是指向當前JSP頁面本身,有點象類中的this指針,它是
  2. java.lang.Object類的實例
  3. 序號方法說明
  4. classgetClass 返回此Object的類
  5. inthashCode() 返回此Object的hash碼
  6. booleanequals(Objectobj) 判斷此Object是否與指定的Object對象相等
  7. voidcopy(Objectobj) 把此Object拷貝到指定的Object對象中
  8. Objectclone() 克隆此Object對象
  9. StringtoString() 把此Object對象轉換成String類的對象
  10. voidnotify() 喚醒一個等待的線程
  11. voidnotifyAll() 喚醒所有等待的線程
  12. voidwait(inttimeout) 使一個線程處於等待直到timeout結束或被喚醒
  13. voidwait() 使一個線程處於等待直到被喚醒
  14. voidenterMonitor() 對Object加鎖
  15. voidexitMonitor() 對Object開鎖

 

 6.application對象

application對象實現了用戶間數據的共享,可存放全局變量。它開始於服務器

的啟動,直到服務器的關閉,在此期間,此對象將一直存在;這樣在用戶的前

后連接或不同用戶之間的連接中,可以對此對象的同一屬性進行操作;在任何

地方對此對象屬性的操作,都將影響到其他用戶對此的訪問。服務器的啟動和

關閉決定了application對象的生命。它是ServletContext類的實例。

 

7.exception對象

exception對象是一個例外對象,當一個頁面在運行過程中發生了例外,就產

生這個對象。如果一個JSP頁面要應用此對象,就必須把isErrorPage設為true,

否則無法編譯。他實際上是Java.lang.Throwable的對象

 

8.pageContext對象

pageContext對象提供了對JSP頁面內所有的對象及名字空間的訪問,也就是

說他可以訪問到本頁所在的SESSION,也可以取本頁面所在的application的

某一屬性值,他相當於頁面中所有功能的集大成者,它的本類名也叫

pageContext。

 

9.config對象

config對象是在一個Servlet初始化時,JSP引擎向它傳遞信息用的,此信息包括Servlet初始化時所要用到的參數(通過屬性名和屬性值構成)以及服務器的有關信息(通過傳遞一個ServletContext對象)

 

 

HttpSession 

是基於Cookie  實現的

 

HttpSession的創建時間

jsp中   顯示調用時會創建session

servlet  中調用  request.getSession時會創建session




 

 自定義標簽

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

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
    version="2.1">
    
  <description>testjsp 1.1 core library</description>
  <display-name>testjsp core</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>testjsp</short-name>
  <uri>http://tj.com/testjsp</uri>
  
  <tag>
     <!-- 描述 HelloSimpleTag的名稱-->
     <name>hello</name>
     <tag-class>com.tag.TestJspFragment</tag-class>
     <body-content>scriptless</body-content>
     

<attribute>
        <name>value</name>
        <!-- 是否必須 -->
        <required>true</required>
        <!-- 是否支持EL表達式 -->
        <rtexprvalue>true</rtexprvalue>
     </attribute>
<!-- 標簽體 --> <!-- 沒有標簽體 --> <!-- <body-content>empty</body-content> --> <!-- 不經過處理直接把內容交給標簽處理器類 --> <!-- <body-content>tagdependent</body-content> --> <!-- 可以有EL${} 不可以有<%=%> 大部分情況下取值為scriptless--> <body-content>scriptless</body-content> </tag> </taglib>


public class TestJspFragment extends SimpleTagSupport{
    
    
    @Override
    public void doTag() throws JspException, IOException {
        //當定義標簽體的時候會調用setJspBody(JspFragment arg0) {
        //把JspFragment傳遞過來
    
        JspFragment fragment = getJspBody();
        
        StringWriter sw = new StringWriter();
        //若為NULL輸出到頁面 等同於fragment.invoke(getJspContext().getOut());
        fragment.invoke(sw);
        //把內容寫到sw中
        
        String content = sw.toString().toUpperCase();
        //把內容轉換成大寫寫入到頁面
        getJspContext().getOut().print(content);
        
        
    }

}

//InputStream inputStream = pageContext.getServletContext().getResourceAsStream("src");//根路徑


//如果有標簽體就會調用此方法,把JspFragment傳過來
    public void setJspBody(JspFragment arg0) {
        System.out.println("setJspBody");
    }

public void setParent(JspTag arg0) {
        //父標簽獲取不到子標簽,子標簽可以獲取到父標簽的引用
        System.out.println("setParent");
        
        //arg0指的就是父標簽的引用,需要強轉
        
    }

 

 

/*Cookie cookie = new Cookie("name", "aaaa");
        //cookie 的作用范圍默認為當前文件路徑的子目錄
        cookie.setPath("/");//站點的根目錄
        cookie.setMaxAge(30);//最大秒數,存在磁盤對應當前瀏覽器,同一個站點最多存20個cookie,每個cookie最大4k
        
        //客戶端第一請求時  服務端給客戶端返回一個cookie    在請求頭中set-cookie
        //第二次客戶端訪問服務端會帶着cookie
        response.addCookie(cookie);*/
        
        //response.encodeURL("session/a.jsp");
        
        
        response.encodeUrl("session/a.jsp");//實現URL的重寫,在后邊加上;jeesessionid=331232131321
        
        //服務端獲取客戶端cookie
        
        /*Cookie []cookies =  request.getCookies();
        
        
        if(cookies!=null){
            
            for (Cookie coo : cookies) {
                System.out.println(coo.getName()+":"+coo.getValue());
            }
            
        }*/

 

 
//http://localhost:8080/spring1/IndexServlet
        String method = request.getServletPath();//IndexServlet
        
        try {
            Method me = getClass().getDeclaredMethod("add", request.getClass(),response.getClass());
            me.invoke(this, request,response);
            //cs.getDeclaredMethod("add", null).invoke(this, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        

自定義標簽函數

之前例子已經寫好了,由於時間關系一直沒有發布,這次帶來的是關於taglib中的<tag>的基本功能已經介紹完畢了,在taglib中我們發現有一個標簽叫做<function>,這次簡單介紹<function>標簽的基本用法,<function>標簽可以做什么呢?它可以讓我們在jsp用直接調用某個方法,根據自定義的方法返回指定的值,兼容jstl標簽,省去了在jsp中直接使用<%!%>來定義方法體再調用的繁瑣.如果你用過el語言的話估計會很快上手,其實<function>標簽就是一個擁有方法體的el語言.注意:function所定義的方法必須需要是靜態的,如果不是靜態的話jstl是不能識別所定義的方法.

Java代碼如下:

package org.lxh.taglib;

import java.util.List; public class FunctionTag { public static String hello(String name) { return name; } public static Integer bbq(List list) { return list.size(); } } 

方法必須靜態,可以定義有返回值或者void類型的方法.

tld:

<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <tlib-version>1.0</tlib-version> <short-name>my</short-name> <uri>http://lauedward.spaces.live.com</uri> <function> <!--EL頁面調用名字--> <name>hello</name> <!--指定標簽的處理類,指定了標簽由哪個Java類來處理。--> <function-class>org.lxh.taglib.FunctionTag</function-class> <!--指定EL頁面調用名字中實際調用的方法.指定處理類的實際方法.參數和回調函數要寫完整路徑--> <function-signature>java.lang.String hello(java.lang.String)</function-signature> </function> <function> <name>bbq</name> <function-class>org.lxh.taglib.FunctionTag</function-class> <function-signature>java.lang.Integer bbq(java.util.List)</function-signature> </function> </taglib>

注意:在<function-signature>需要寫完整的類名,假如是String類型的話就必須寫java.lang.String這樣字,不支持泛型的定義如java.util.List<java.lang.String>eclipse會把<>當作xml的格式來判斷的,所以就省略該泛型的定義.

jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="my" uri="/WEB-INF/tld/testFunction.tld"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<%@page import="java.util.*"%><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<%
    List<String> list = new ArrayList<String>();
    list.add("aa");
    list.add("bb");
    list.add("cc");
    request.setAttribute("list", "helloword");
    request.setAttribute("name", list);
    Map map = new HashMap();
    map.put("1","a");
    map.put("2","b");
    map.put("3","c");
    map.put("4","d");
%>

<br>
${my:hello(list)}
<br>
${my:bbq(name)}
<br>

</body>
</html>

注意:調用方法的時候必須類型要傳入相同類型的值,否則的話會報錯,不過對於方法體是String的話,是可以傳入list,set,map那些,因為傳入后會直接調用list的.toString()方法直接當字符串輸出.










HttpSessionListener

 

HttpSessionAttributeListener

 

ServletContextListener

 

web.xml 的加載順序是:context-param -> listener -> filter -> servlet ,而同個類型之間的實際程序調用的時候的順序是根據對應的 mapping 的順序進行調用的。

 

 

 

 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM