Servlet Basic
Servlet标准代码
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class HelloServlet extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletExcpetion{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println();
out.close;
}
}
获取HTML form中的输入参数
方法:
String request.getParameter()
输入的参数为HTML中的name=“frame”
对应的
返回值:String
String userName = request.getParameter("fname");
Servlet关键点
- 没有main方法
public static void main(String[] args)
- 没有构造器
- 两个关键的方法
doGet()
doPost()
Serlvet 源码
init()
:在servlet第一次创建或者load的时候调用,只调用一次
service()
:每次有request都会被调用
destroy()
:当用完了servlet调用
Servlet创建过程
当程序收到HTTP请求时:
- 寻找servlet(如果找不到servlet,loads,调用构造器以及
init()
) - 创建或者重复使用Thread,这个Thread会调用
service()
方法 - 创建或传递request以及response对象
- 向请求端返回response对象
Life cycle of servlet
init()
👇
service()
👇
destroy()
ServletConfig
ServletConfig
对象由container创建
- 每个Servlet有且仅有一个
ServletConfig
- 这些参数是写
web.xml
里面的
web.xml
<init-param>
<param-name>ourz</param-name>
<param-value>yes</param-value>
</init-param>
Servlet中调用
out.println(getServlerConfig.getInitParameter("ourz"));
// yes
ServletContext
Servlet
- 每一个Servlet或者每一个JSP都有一个
ServletConfig
对象 - 包含了所有初始参数
Web Application
- 每个Web application都有一个
ServletContext
对象 - 写在Web xml中
web.xml
<context-param>
<param-name>ourz</param-name>
<param-value>yes</param-value>
</context-param>
Servlet中调用
ServletContext ctx = getServletContext();
out.println(ctx.getInitParameter("ourz"));
Attribute
两个重要的方法
-
getAttribute(String)
-
setAttribute(String, Object)
getParameter()
String getParameter(String)
- 返回null表明unknown parameter
- 返回**""**表明这个parameter没有值
getParameterNames()
String[] Enumeration getParameterNames(String)
- 返回null表明unknown parameter
- 返回**""**表明这个parameter没有值
例子:读取Checkbox
<form action="http://localhost:8080/servlet/elem004.ProcessBigForm"
method="post">
Please enter: <br><br>
Your login: <input type="text" name="Login"> <br><br>
Your favourite colour:
<input type="radio" name="Colour" value="blue">Blue
<input type="radio" name="Colour" value="red">Red
<input type="radio" name="Colour" value="green">Green <br><br>
Which of these courses you are taking: <br>
<input type="checkbox" name="Course" value="elem001">ELEM001 <br>
<input type="checkbox" name="Course" value="elem002">ELEM002 <br>
<input type="checkbox" name="Course" value="elem003">ELEM003 <br>
<input type="checkbox" name="Course" value="elem004">ELEM004 <br>
<input type="submit" value="Send to Servlet">
</form>
Servlet
// More code here ...
out.println("<table border=1>");
// Obtain all the form’s parameters from the request object.
Enumeration paramNames = req.getParameterNames();
while (paramNames.hasMoreElements()) {
String paramName = (String) paramNames.nextElement();
// Obtain values for this parameter and check how many there are.
String[] paramValues = req.getParameterValues(paramName);
if (paramValues.length == 1)
{ // a single value
String paramVal = req.getParameter(paramName);
out.println("<tr><td>" + paramName +"</td><td>" + paramVal + "</td> </tr>");
} else { // If several values print a list in the table.
out.println("<tr><td>" + paramName +"</td><td><ul>");
for (int i = 0; i < paramValues.length; i++)
out.println("<li>" + paramValues[i] + "</li>");
out.println("</ul></td></tr>");
}
}
out.println("</table>");
out.close();
Advanced Servlet
包含:
Getting another file to do work
- Redirect
- Forward(
RequestDispatcher
)
Request and Response headers
Conversation
- Sessions
- URL writing
JavaBeans
Redirect & Forwarding
Redirect与Forwarding的概念
Redirect
只能写在GET中
Servlet方法:必须写在全部的response之前
response.sendRedirect("url");
回复状态码:
- 302:暂时移动
- 301:永久移动
结果:浏览器读取Response中的header,然后向新的URL发请求
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class TestRedirect extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String userName = request.getParameter("uname");
// validate
// another file is responsible for doing something with this
response.sendRedirect("www.security.co.uk/checkUserName.do");
// more servlet code ...
}
}
Forwarding
利用Object RequestDispatcher
Servlet方法:
RequestDispatcher view = request.getRequestDispatcher("display.jsp");
view.forward(request, response);
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class TestForward extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String userName = request.getParameter(“uname”);
// validate
// another file is responsible for displaying this
RequestDispatcher view = request.getRequestDispatcher(“display.jsp”);
view.forward(request, response);
// more servlet code ...
}
}
Request Headers
获取请求Header
String getHeader(String) // 大小写不敏感
常用的header自己的方法
getContentLength();
getContentType();
获取所有的Headers的可遍历对象
Enumeration getHeaderNames();
获取请求中的其他信息
getMethod()
getRequestURL()
getProtocol()
服务器端的回复格式
包含:
- 状态栏(包含HTTP版本号 状态码 信息 (HTTP/1.1 200 OK))
- Response Header (Content-type: text/plain)
- 空白行
- document
Servlet能做的
通过设置不同的状态栏和Response Header
- 告诉用户要输密码
- 提示attached document的类型
- forward到其他的网页
HTTP状态码
设置状态码
Servlet只需要去设置状态码,HTTP版本是已经定义好的了
Servlet方法:
response.setStatus(int)
必须在PrintWriter之前使用此方法
特殊的状态码
一些特殊的状态码以文本的形式定义在HttpServletResponse
类中,可以直接调用
HttpServletResponse.SC_NOT_FOUND
来使用 404码
两个常用的方法:
-
public void sendError(int sc, String message)
-
public void sendRedirect(String url)
会同时返回 301 状态码
设置Response Header
Servlet方法:
res.setHeader(String header, String value);
有以下例子:
对于常用的Header来说,有以下的方法可使用:常用
- 重要
setContentType(String type)
- 重要
sendRedirect(String encodedURL)
setContentLength(int length)
addCookie(String cookie)
设置Refresh Header
用法1:设置浏览器多久会重新请求页面
servlet方法:30s刷新一下
res.setHeader("Refresh", "30");
终止浏览器刷新:发送204(SC_NO_CONTENT)状态码
res.setStatus(204);
res.setStatus(response.SC_NO_CONTENT);
204状态码:请求成功但是没有任何东西返回
用法2:设置浏览器多久会去到下一个页面
Servlet方法:5秒后到URL的页面
res.setHeader(“Refresh”, “5; URL=http://host/path”);
Content-Type包含的Header
常用text/html(默认为text/plain)
setContentType();
该方法必须要在OutputStream之前使用
有以下可用的
检查是否可接收特定的Content-Type
Servlet方法:
String req.getHeader("Accept")
例子:如果能接收image/jpeg
就发
Session
概述:服务器传SessionID给新客户端,客户端会随Request发SessionID给服务器,服务器根据SessionID去找该客户端在服务器存了的东西和属性
Servlet端的Session追踪
HttpSession API是高层的接口,建立与cookies
和URL-rewriting
之上
- 浏览器能支持cookies就用cookies,不支持cookies就使用URL-rewriting
- Servlet不担心使用哪个方法
要经常使用URL-rewriting方法
如何跟踪?
服务器端使用session ID来匹配全部的Session object
-
session ID是一个String,当客户端第一次访问服务器时,以cookies的形式发送回客户端
-
如果客户端不支持cookies或者客户disabled cookies的话
- Session Tracker会进行URL rewriting
获取当前请求的Session
HttpSession session = request.getSession();
HttpSession Object
Servlet会保留一个关于HttpSession Object的表
-
这个Object通过
session id
来被查找 -
这是从请求对象中提取的:
cookies或者rewritten URL
HttpSession session = request.getSession();
-
HttpSession object其实就是一个哈希表,用来存储用户的数据
HttpSession的生命周期默认为30min
判断是否存在已有的Session Object
HttpSession session = request.getSession();
if(session.isNew()) { // e.g., add username to it }
else {
// e.g., add new information, extract previous
// stored information from the session object
}
第一次访问Servlet
判断该Session是否已经存在,不存在的将其存为新的Session对象
HttpSession session = request.getSession();
if (session.isNew()) {
String uName = request.getParameter(“fullName”);
session.setAttribute(“userName”,uName);
// [session.setAttribute(String key, Object value)]
}
非第一次访问Servlet
将Session中的信息取出返回
HttpSession session = request.getSession();
if (session.isNew()) { ... }
else {
int uAge = Integer.parseInt(request.getParameter(“age”));
session.setAttribute(“userAge”, uAge);
String name = (String) session.getAttribute(“userName”);
...
out.println(“hello ” + name + “ your age is ” + uAge);
}
Session死亡时间
Servlet方法:在超过设置的时间后会丢弃Session
HttpSession session = request.getSession();
session.setMaxInactiveInterval(2*60*60); // two hours
方法invalidate()和logout()显式地删除会话对象。
也可以配置文件来使用
<session-config>
<session-timeout>30</session-timeout>
</session-config>
URL Rewriting
将全部要返回浏览器的内容都写入URL,包括session ID
例如:
如果用户点击URL,又会回到Server
在URL重写中,服务器端程序不断添加或更改URL(它们的长度可以不断增加),以记住在页面之间交换的数据。
encodeURL
Servlet方法:
response.encodeURL(“/store/catalog”)
两个作用:
- 检查URL是否需要被重写
- 如果URL需要重新,那么session id会被插入URL中并返回重写好的URL
Encoding URL
两种情况需要Encoding URL
-
当url嵌入到生成的网页中时
String originalURL = someRelativeOrAbsoluteURL; String encodedURL = res.encodeURL(originalURL); out.println(“<A HREF=\”” + encodedURL + “\”>...</A>”);
-
使用重定向时 originalURL指的是重定向要去的地址
String originalURL = someURL; String encodedURL = res.encodeRedirectURL(originalURL); res.sendRedirect(encodedURL);
Rewritten
需要两个不同的方法,因为它们遵循不同的规则来确定是否需要重写URL。
如果不重写URL,在以下情况session会lost:
- 浏览器不支持cookie
- 点击了未重写的URL
JavaBean 与 Session的应用
应用JavaBean的好处
- 可以存储一个范围的属性
- 很容易定制化
将Session中的Value设成有一个JavaBean
package chain.web; import chain.model.*;
import java.io.*; import javax.servlet.*;
import javax.servlet.http.*; import java.util.*;
public class OperandsServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
response.setContentType("text/html");
DataBean db;
// Get the current session object, create one if necessary.
HttpSession session = request.getSession(true);
if (session.isNew()) { // So first time.
db = new DataBean();
int op1 = Integer.parseInt(request.getParameter("op1"));
int op2 = Integer.parseInt(request.getParameter("op2"));
db.setOp1(op1);
db.setOp2(op2);
session.setAttribute("sum", db);
try {
PrintWriter out = response.getWriter();
out.println("<HTML><HEAD><TITLE>Asking for
Operator</TITLE></HEAD>");
out.println("<BODY><H1>Asking for Operator</H1>");
out.println("<form method='POST' action='http://localhost:8080/servlet/DoSums'>");
out.println("Input Operator");
out.println("<input type='text' name='op' value=''> <br><br> ");
out.println("<input type='submit' value='input operator'>");
out.println("</form>");
out.println("</BODY></HTML>");
}
catch (java.io.IOException e) {
System.err.println(" Print exception" +e);
}
} // end if
else { // There is a session variable for this user.
db = (DataBean)session.getAttribute("sum");
String s = request.getParameter("op");
db.setOperator(s);
try { double x = db.calculate(); db.setAnswer(x); }
catch(Exception e) { System.out.println(e); }
session.setAttribute("sum", db);
try {
request.getRequestDispatcher("Display.jsp").
forward(request, response);
}
catch (javax.servlet.ServletException e) {
System.err.println(" Servlet exception" + e);
}
catch (java.io.IOException e) {
System.err.println(" Print exception" +e);
}
// getServletContext().getRequestDispatcher("/output.jsp").
forward(request, response);
}
}
}