2016年3月15日 星期二

ServletContext的初始化參數、HttpServletResponse方法 (Servlet 五)

初始化參數前面給有介紹到,但之前的初始化參數是ServletConfig的,由GenericServlet實作,是針對這一支Servlet使用,其他Servlet取不到,而ServletContext的初始化參數每支Servlet都取得到
web.xml
<web-app>
    <context-param>
        <param-name>abc</param-name>
        <param-value>111</param-value>
    </context-param>
    <context-param>
        <param-name>def</param-name>
        <param-value>222</param-value>
    </context-param>
</web-app>


@WebServlet(
    urlPatterns = { "/xxx" },
    loadOnStartup = 1,
    initParams = {
        @WebInitParam(name = "p1", value = "xxx"),
        @WebInitParam(name = "p2", value = "20")
    }
)
// @WebInitParam(name = "bbb", value = "bbb")
public class TestServletContextParam extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/plain; charset=Big5");
        PrintWriter out = resp.getWriter();
    
        out.println("Context Params");
        ServletContext sc = getServletContext();
        Enumeration<String> contextParams = sc.getInitParameterNames();
        while (contextParams.hasMoreElements()) {
            String key = contextParams.nextElement();
            out.println("key=" + key);
            out.println("value=" + sc.getInitParameter(key));
        }
    
        out.println("this Servlet Params");
        Enumeration<String> thisServletParams = getInitParameterNames();
        while (thisServletParams.hasMoreElements()) {
            String key = thisServletParams.nextElement();
            out.println("key=" + key);
            out.println("value=" + getInitParameter(key));
        }
    }
}

※結果:
Context Params
key=abc
value=111
key=def
value=222
this Servlet Params
key=p1
value=xxx key=p2 value=20

※上面是ServletContext的,下面是本身自己的

※再寫一支Servlet寫法一樣,但不要用annotation,web.xml也不要設定(只要設定路徑即可),這時會發現取得到ServletContext,而TestServletContextParam的初始化參數取不到

※註解那行寫了不會錯,但沒作用,API有寫說要配合@WebFilter或@WebServlet的

※annotation好像沒有設定ServletContext初始化參數的寫法



※HttpServletResponse方法

.父介面是ServletResponse


※注意事項

BufferedReader in1 = req.getReader();
ServletInputStream in2 = req.getInputStream();
PrintWriter out1 = resp.getWriter();
ServletOutputStream out2 = resp.getOutputStream();

※會出例外,如:IllegalStateException: getReader() has already been called for this request

※in1和in2只能出現一個; out1和out2只能出現一個



※ContentType

resp.setContentType("text/html");
PrintWriter out1 = resp.getWriter();
resp.setContentType("image/gif");
ServletOutputStream out2 = resp.getOutputStream();
    
PrintWriter out = resp.getWriter();
ServletContext sc = req.getServletContext();
out.println(sc.getMimeType("*.jpg") + "<br />");
out.println(sc.getMimeType("abc.txt")); 

※ContentType不知道要打什麼,可以用ServletContext的MimeType,給副檔名就會印出來了

※也可以打開Servers的web.xml,裡面可以複製

※而最好的方式是在Servers點兩下就會跳出如下的畫面,可以看出副檔是body、htm、html的mimeType都是text/html



※BufferSize

System.out.println("預設的BufferSize=" + resp.getBufferSize());
resp.setBufferSize(16 * 1024);
System.out.println("設定後的BufferSize=" + resp.getBufferSize());

※單位是Byte,所以預設的會印出8192,最後印出16384

※主要是連網站有個緩衝,緩衝滿了會重新連線,所以如果感覺太慢了,可以適當的加大這個數字



※reset

PrintWriter out = resp.getWriter();
     
System.out.println("xxxA");
out.println("xxxB");
resp.reset();
System.out.println("oooA");
out.println("oooB");
resp.reset();
out.println("oooC");

※reset了兩次,所以只會印出oooC,是指out,控制台都能印出



※ContentLength

resp.setContentType("text/plain; charset=UTF-8");
resp.setContentLength(3);
PrintWriter out = resp.getWriter();
out.println("一");

※回傳給網頁的大小,單位為B,而我印了一個中文字,且編碼是UTF-8,所以印的出「一」,但如果小於3,什麼都不會印出,如果打的是abcdef,那只會印出「abc」,有些人不知道為什麼,認為UTF-8是2個Byte,我這一篇可以證明



※sendError

resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "xxx");

※sendError是個overloading,差在有沒有說明而已,
第一行的標頭會印出「HTTP Status 400 - 」,第二行會印出「HTTP Status 400 - xxx」




※resp.setStatus

1xx:Informational
2xx:Successful
3xx:Redirection
4xx:Client Error
5xx:Server Error

維基百科有說明,我將它貼到這來,裡面有連結,可以連到這裡,才有上面那段

HTTP/1.1 200 OK

Date: Mon, 23 May 2005 22:38:34 GMT
Content-Type: text/html; charset=UTF-8
Content-Encoding: UTF-8
Content-Length: 138
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
ETag: "3f80f-1b6-3e1cb03b"
Accept-Ranges: bytes
Connection: close

<html>
<head>
<title>An Example Page</title>
</head>
<body>
Hello World, this is a very simple HTML document.
</body>
</html>

※最上面是Status Line
再來是Response Header
最後是Response Content,也就是HTML

Header還有很多可看另一頁,注意有分request和response



※setXXXHeader

setHeader(String, String);
setIntHeader(String, int);
setDateHeader(String, long);
   &nbsp;
addHeader(String, String);
addIntHeader(String, int);
addDateHeader(String, long);
    
containsHeader(String);

※設定標頭,可以設字串、數字、日期,使用set會蓋掉前面的;使用add會增加到原來的之後,containsHeader看名字叫知道了

※setHeader("text/html", "charset=utf-8");有沒有charset我忘了,因為很麻煩,所以有setContentType



※Refresh

<head>
    <meta http-equiv="Refresh" content="3">
</head>
    
res.setHeader("Refresh", "3");
res.setHeader("Refresh", "3; URL=http://www.xxx.ooo");

※上面是HTML的寫法,下面是Servlet的寫法

※過程如下圖的上面,下面是待會要說的sendRedirect
※如果沒有URL,兩個都一樣,都是Servlet直接回傳



※sendRedirect

res.sendRedirect(String)是
res.setStatus(resp.SC_MOVED_TEMPORARILY); // 302
+
res.setHeader("Location", location);
因為太麻煩,所以才有sendRedirect

sendRedirect(String):絕對、相對路徑(「/」的用意和form action的觀念一樣)都可以
setHeader:只能用絕對路徑

Object account = session.getAttribute("account");
if(account == null){
    session.setAttribute("location", req.getRequestURI());
    resp.sendRedirect(req.getContextPath() + "/login.jsp");
    return;
}

※取不到登入者的帳號,可以這樣運用

沒有留言:

張貼留言