servlet
编写一个servlet的步骤:
1.自定义一个类继承HttpServlet,复写其中的doGet()和doPost()方法
2.在web.xml做配置:分为两小步 注册写好的servlet 为注册好的servlet配置路径
3.发布写好的servlet
为什么在编写servlet程序时要继承HttpServlet,而不继承Servlet?
因为Servlet并不仅仅是面向HTTP协议的,Servlet接口和协议无关,而HttpServlet是面向HTTP协议的
使得程序员在开发时变得很轻松
Servlet的生命周期:
init():初始化,第一次访问对象创建时被调用,并且只会被调用一次
service():每次相应客户端的请求时都会被tomcat容器调用
destroy():当Servlet对象摧毁时调用
编写servlet的注意事项:
1)servlet初始化时覆盖init()方法,无需覆盖init(config)方法,因为,通过源代码可以知道在有参的init(config)中,调用了无参的init()方法
以下是源代码:
public abstract class GenericServlet
implements Servlet, ServletConfig, java.io.Serializable{
...//伪代码
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
}
2)根据HTTP请求的方式,只需覆盖相应的doGet()和doPost()方法,无需覆盖其中的service方法
在HttpServlet的方法中,又定义了一个service方法,而在servlet的生命周期方法中,
service方法调用了后来定义的这个类中新定义的service方法,然后这个service方法才最终根据请求方式的不同调用了doGet或doPost方法。
所以结论是,servlet的service方法与doGet,doPost方法的关系是调用与
被调用的关系。
以下是源代码:
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < lastModified) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
3)当doGet和doPost代码逻辑相同时,可以相互调用,简化编程
servlet启动时配置注意点
URL-Pattern三种配置方式:
1.完全路径匹配,以/开始,不能包含*
2.目录匹配,以/开始以/*结束
3.扩展名匹配,不能以/开始,以*开始
经典错误:/*.jsp
优先级:完全匹配>目录匹配>扩展名匹配
servletConfig和servletContext
servletConfig对象是servlet的配置信息,用来在servlet初始化阶段向servlet传递信息
自定义servlet中通过getServletConfig()获得ServletConfig对象
ServletContext对象
1.每个工程对应一个ServletContext
2.通过ServletConfig.getServletContext()方法获得
应用一:全局初始化参数
1)配置全局初始化参数(web.xml)
2)获得ServletContext对象 ServletContext context=getServletContext();
3)通过getInitParameter(String name)获得全局参数
应用二:多个servlet之间可以共享数据
共享全局唯一数据,网站访问次数,数据库连接池
setAttribute(name,value)
getAttribute(name)
应用三:读取web工程中资源文件
比如在mail工程中创建四个txt文件
1)在mail的根目录下创建一个1.txt
由于在根目录下,无法访问到,所以没有办法读取
2)在Webroot目录下创建一个2.txt
通过getServletContext().getRealPath("/2.txt");
3)在WEB-INF目录下创建一个3.txt
通过getServletContext().getRealPath("/WEB-INF/3.txt");
4)在src目录下创建一个4.txt
通过getServletContext().getRealPath("/WEB-INF/classes/4.txt");