servlet作用:
用户发出请求以后,服务器怎么知道要调用哪个方法来处理请求呢?
servlet的web.xml配置方法
< servlet>
< servlet-name>name</ servlet-name>
< servlet-class>包名+类名< /servlet-class>
< init-param>
< param-name>paramname</ param-name>
< param-value>paramvalue</ param-value>
</ int-param>
</ servlet>
< servlet-mapping>
< servlet-name>name</ servlet-name>
< url-pattern>?< url-pattern>
</ servlet-mapping>
服务器收到请求后,首先找到web.xml文件并找到url-pattern即路径别名,然后找到对应的servlet-name,这一步即确定了到底要调用那个方法来处理请求;接下来通过servlet-name来定位到相应的servlet-class,然后通过反射可以加载相应的servlet类。因为我们一般的servlet都会实现GenericServlet接口或继承HttpServlet接口,所以我们调用自己实现的servlet方法时其实就是在调用GenericServlet接口或HttpServlet接口的方法。然后就可以通过重写这些方法来处理请求了。如果xml中有init-param时,则这些信息会被封装到ServletConfig对象里并且传入init()方法中。
服务器接到请求后会创建request对象并将其作为参数传递给service方法
servlet生命周期:
加载、使用、销毁
服务器被启动时web.xml被加载进内存
servlet类在第一次被调用时被加载进内存或有load-on-startup标签时服务器启动时立即加载进内存
加载进内存前会生成相应的字节码文件(.class)。servlet文件或web项目中任意文件发生更改后服务器会重新帮我们编译servlet类并覆盖之前servlet的字节码文件
init方法:第一次sevlet类加载进内存时被调用,只要服务器不关闭,这个方法不会再次被调用,因此我们一般不重写这个方法。
destory方法:服务器被关闭后调用,servlet被从内存中销毁。
doGET与doPOST的区别:
doGET:GET请求会将请求参数附在相应的URI中,不安全;GET方法后面的信息量字节大小不要超过1.3K
doPOST:请求而POST请求参数会被放入请求体中,在URL中并没有明文显示,安全;POST方法后面的信息量字节大小没有限制
上图为servlet相关的接口和抽象类。GenericServlet实现了三个接口,并由HttpServlet来继承它,我们使用时,基本都是写一个继承HttpServlet抽象类的类,并且实现doGET、doPOST等方法
上图为继承关系(request和response相关的类)
下面为源码的解读:
ServletConfig接口:
ServletConfig是一个servlet设置对象,在初始化期间它被servlet容器用来传递信息给servlet,它传递的主要信息是init-param标签中的属性。ServletConfig对象是一个共享对象,因此并发的写操作很危险
方法:
下面四个方法可获取init-param标签中的属性
public String getServletName();
public ServletContext getServletContext();
public String getInitParameter(String name);
public Enumeration< String > getInitParameterNames();
Servlet:
定义所有servlet必须实现的方法。
servlet是一个在Web服务器中运行的Java小程序,servlet接收并响应从客户端来的请求,通常通过HTTP来传输。
我们可以通过编写一个继承GenericServlet的类或继承HttpServlet的类来实现这个接口。
这个接口定义方法(init)来初始化一个servlet,来响应(service)request和从服务器移除(destory)一个servlet。这就是一个servlet的生命圈。
这个接口提供getServletConfig方法来得到启动信息,并且getServletInfo方法可以允许servlet来返回基本的servlet信息,就像作者,版本和版权之类的信息。
init()方法只有在首次访问servlet类被调用或者在xml中配置了< load-on-startup >标签,则随着web服务器启动而调用
public void init(ServletConfig config) throws ServletException;
public ServletConfig getServletConfig();
public void service(ServletRequest req, ServletResponse res)
public String getServletInfo();
public void destroy();
ServletConfig(servlet设置):
一个servlet设置对象在初始化期间会被一个servlet容器用来向servlet传递信息。
public String getServletName();
public ServletContext getServletContext();
public String getInitParameter(String name);
public Enumeration getInitParameterNames();
GenericServlet:
重写了Servlet接口一些方法
HttpServlet:
提供了一个抽象方法来被继承并用于创建HTTP servlet。它的一个子类必须重写至少一个方法,通常是这些:doGET、doPOST、doPUT、doDELETE、init和的destory。
HttpServlet中没有init()方法,但它还是可以通过GenericServlet接口中的getServletConfig方法来获取ServletConfig 对象并且能够对其做一定的设置
我们只需在HttpServlet的实现类中这样做 this.getServletConfig();就行了
方法:
public HttpServlet() { }
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
protected void doPut(HttpServletRequest req, HttpServletResponse resp)
protected void doDelete(HttpServletRequest req,HttpServletResponse resp)
protected void service(HttpServletRequest req, HttpServletResponse resp)
public void service(ServletRequest req, ServletResponse res)
这里有两个service方法,首先请求request、response会到达public修饰的service方法,然后在内部将request和response向下转型成Httpservletrequest和Httpservletresponse对象,并将它们转发给protected修饰的service方法,在protected修饰的service方法中首先request会调用自身的getMethod方法,判断请求是GET,POST还是其他方法,然后调用对应的doGET,doPOST等方法来进行请求和响应的处理。
这两个service方法通常都不需要进行重写。
ServletRequest:
定义一个对象来传递客户端请求信息至Servlet,Servlet容器创建一个ServletRequest对象并将它作为一个参数(argument)传递给Servlet的service方法。一个ServletRequest对象提供包括参数名和值,属性,和input stream在内的数据。继承ServletRequest的接口可以提供额外特定协议的数据(如HTTP数据是由javax.servlet.http.HttpServletRequest提供的)
public Object getAttribute(String name);
public Enumeration<String> getAttributeNames();
public String getCharacterEncoding();
public void setCharacterEncoding(String env) throws UnsupportedEncodingException;
public int getContentLength();
public String getContentType();
public String getParameter(String name);
public Enumeration<String> getParameterNames();
public String[] getParameterValues(String name);
public Map<String, String[]> getParameterMap();
public String getProtocol();
public String getScheme();
public String getServerName();
public int getServerPort();
public String getRemoteHost();
public String getRemoteAddr();
public RequestDispatcher getRequestDispatcher(String path);
public void setAttribute(String name, Object o);
public void removeAttribute(String name);
public int getRemotePort();
public String getLocalName();
public String getLocalAddr();
public int getLocalPort();
public ServletContext getServletContext();
若要访问WEB-INF这个私有目录下的文件,可以用转发的方式完成,比如访问一个html文件:
req.getRequestDispatcher("/WEB-INF/*.html").forward(req,resp);
请求转发后一般用return结束请求
这时,req和resp对象会被放入缓冲,我们可以用如下代码
req.getWriter.flush();
在转发完成之前来强行输出缓冲内容,但这样的话,表示resp对象在转发完成前已被输出,则它就会从缓冲区中被踢出。当转发完成时,控制台就会报resp以输出的错误。所以我们不要轻易在转发完成前对resp对象进行操作
ServletResponse:
用来帮助Servlet发送一个响应给客户端。
方法:
public String getCharacterEncoding();
public String getContentType();
public PrintWriter getWriter() throws IOException;
public void setCharacterEncoding(String charset);
public void setContentLength(int len);
public void setContentType(String type);
HttpServletRequest:
继承于ServletRequest接口用来提供请求信息给HttpServlet。
Servlet容器会创建一个HttpServletRequest对象并将其作为一个参数传递给Servlet的service方法(doGET,doPOST等)。
public Cookie[] getCookies();
public long getDateHeader(String name);
public String getHeader(String name);
public Enumeration<String> getHeaders(String name);
public Enumeration<String> getHeaderNames();
public int getIntHeader(String name);
public String getMethod();
public String getPathInfo();
public String getContextPath();
public String getQueryString();
public String getRemoteUser();
public String getRequestedSessionId();
public String getRequestURI();
public StringBuffer getRequestURL();
public String getServletPath();
public HttpSession getSession();
HttpServletResponse:
用来发送response。(比如它有访问HTTP头和cookies的方法)
public void addCookie(Cookie cookie);
public boolean containsHeader(String name);
public String encodeURL(String url);
public void sendError(int sc, String msg) throws IOException;
public void sendRedirect(String location) throws IOException;
public void setDateHeader(String name, long date);
public void addDateHeader(String name, long date);
public void setHeader(String name, String value);
public void addHeader(String name, String value);
public void setIntHeader(String name, int value);
public void addIntHeader(String name, int value);
public String getHeader(String name);
实现servlet的三种方式
1、实现Servlet接口
缺点:不必要的方法必须要重写
2、继承GenericServlet
缺点:不能区分不同的请求方式
3、实现HttpServlet并重写doGET()和doPOST()方法