Servlet基本操作
一、Servlet的請求流程
web專案中的web.xml檔案配置為:
<servlet> <!--別名--> <servlet-name>Hello</servlet-name> <!--類的全限定名--> <servlet-class>hello.HelloServlet</servlet-class> </servlet> <!-- 向外暴露一個資源名稱,供外界訪問,資源名稱前面必須有/ --> <servlet-mapping> <servlet-name>Hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
-
1、 第一次 在瀏覽器位址列輸入http://localhost:80/test/hello 後回車 (第一次請求)
-
2、此時servlet會解析這個請求資訊,首先前面的localhost:80一般是域名資訊,一般會交給DNS解析成ip,80是http協議的預設埠.這裡主要討論後面的一部分,test/hello
-
3、伺服器會tomcat目錄裡的conf目錄下尋找service.xml檔案,在所有Context元素中尋找path內容為這裡的test的,可以找到這個元素中屬性docBase的內容,根據docBase中的路徑找到這個web專案的根路徑
-
4、在專案的根路徑下尋找web.xml檔案,也就是上面的檔案,在這個檔案中尋找url-patternd內容為hello的元素,如果沒有就會報404錯誤,說明資源不存在。如果有,找到和他在一個元素中的servlet-name,根據這個名字它會去尋找上面servlet元素中的和它同名元素,最終找到servlet-class中的類的全限定名稱。
-
5、利用反射去呼叫Serlvet類中的構造器從而建立物件(顯然構造器必須是public的)。
Servlet ser = ClassforName("hello.HelloServlet");
-
6、呼叫init方法,ser.init(ServletConfig config);
-
7、呼叫service方法 ser.service(...);
-
8、對瀏覽器做出響應,以html等形式
-
9、正常終止伺服器,會執行destroy() 但是如果非正常終止並不會執行此方法。
如果是非第一次請求,不會在第5步建立物件了,而是直接從servlet的例項緩衝池中直接獲取物件。接著執行後續操作。
注意:servlet的建立,初始化,執行和銷燬等操作都是有伺服器來負責呼叫的。
javax.servlet.Servlet介面中有四個方法:
public void init(ServletConfig config) throws ServletException { //執行servlet的初始化操作 } public ServletConfig getServletConfig() { //獲取Servlet的配置資訊物件 return null; } public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { //服務,具體操作的方法 } public String getServletInfo() { //獲取servlet的資訊,作者,版權 return null; } public void destroy() { //銷燬物件 }
二、Servlet的初始化引數
在web.xml檔案中的Servlet元素下可以新增初始化引數
<servlet> <!--別名--> <servlet-name>Hello</servlet-name> <!--類的全限定名--> <servlet-class>hello.HelloServlet</servlet-class> <init-param> <param-name>name</param-name> <param-value>Willing</param-value> </init-param> </servlet>
獲取初始化引數就要用到ServletConfig介面中的方法
String name =config.getInitParameter("name");//根據引數名獲取引數值 Enumeration<String> en = config.getInitParameterNames();//獲取所有的引數名,返回一個迭代器
因為它們並不是static方法,所有要用ServletConfig的物件去呼叫,實際上物件伺服器已經幫我們建立好了,在init方法init(ServletConfig config)的引數中,我們只需拿來用。方便起見可定義為成員變數.
ServletConfig config;//把config物件定義為成員變數 @Override public void init(ServletConfig config) throws ServletException { this.config = config; }
三、Servlet的繼承體系
每次寫一個servlet都得實現javax.servlet.Servlet肯定很痛苦。所有就有專門的來已經實現好了,自己只需要繼承就行了。servlet的繼承體系
我們只要繼承HttpServlet,
public class TestServlet extends HttpServlet { private static final long serialVersionUID = 1L; public void init() throws ServletException { //自己的初始化操作 } //編寫Servlet方式一 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //編寫處理請求的程式碼 //不能呼叫父類中 的service:super.service(); } //編寫Servlet方式二 //處理POST請求 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } //處理GET請求 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //處理全部的請求 } }
四、HttpSevletRequst的常用方法
HttpServletRequst是ServletRequest的子介面,封裝了處理http協議請求的方法
String getMethod();//返回請求方式GET 或 POST String getRequestURI();//返回請求行中的資源名稱 StringBuffer getRequestURL();//返回瀏覽器中位址列中的資訊 String getContextPath();//返回上下文路徑path屬性值 String getHeader(String name) //返回請求頭資訊 String getParameter(String name);//返回指定引數名的引數值(一般是表單使用者輸入) String getParameterValues(String name);//返回指定名稱的多個引數值
請求亂碼處理
請求預設是ISO-8859-1,不支援中文
- 方式一:解決中文亂碼
- 1.按照ISO-8859-1把亂碼恢復成二進位制形式byte[] data = username.getBytes("ISO-8859-1");
- 2.對二進位制形式重新編碼為UTF-8,username = new String(data,"UTF-8");
- 方式二(推薦):可以呼叫req.setCharacterEncoding("UTF-8");//適用於POST方式
- 方式三:修改service.xml配置檔案中修改埠的的元素
五、HttpServletResponse的常用方法
HttpServletResponse是ServletResponse的子介面,封裝了處理http協議請求的方法
ServletOutputStream getOutputStream();//返回位元組輸出流物件 PrintWriter getWriter() //返回一個列印流物件,這是父介面HttpResponse中的方法 void addCookie(Cookie cookie)//把cookie物件響應給瀏覽器
注意:這裡位元組輸出流不能和字元輸出流共存。
響應亂碼處理
/** * 解決輸出中文亂碼問題 */ resp.setCharacterEncoding("UTF-8"); //設定輸出的MIME型別,設定為html resp.setContentType("text/html"); //上面兩行程式碼也可以合併在一起寫成: //resp.setContentType("text/html;charset=utf-8");
/** * 獲取位元組輸出流物件,不能與位元組輸出流共存 */ //OutputStream out = resp.getOutputStream(); //out.write("Hello".getBytes()); /** * 獲取符輸出流物件 */ PrintWriter p = resp.getWriter(); p.println("你好");//這裡的換行並不作用,在網頁中是以html形式顯示的,換行用br標籤 p.print("Hello");
六、註解配置Servlet
JavaEE6(Servlet3) 可以用註解配置,代替了web.xml檔案
/** * value屬性是一個數組,所有可以傳多個,因為url-pattern也可以有多個值 * *初始化引數initParams的屬性的型別還是個@WebInitParam註解,並且是一個數組 */ @WebServlet(value = {"/test","/hello"} ,initParams = { @WebInitParam( name = "encoding" ,value = "UTF-8"), @WebInitParam( name = "name" , value = "Willing") } ) public class AnnServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //獲取初始化引數 String encoding = getInitParameter("encoding"); String name = getInitParameter("name"); System.out.println(encoding+","+name); } }