Servlet 基础详解

来源:互联网 发布:孙可望 知乎 编辑:程序博客网 时间:2024/06/08 02:50
1. Servlet简介
     Servlet是服务器端的重要组件,直译为服务端的小程序,它属于动态资源,用来处理请求,服务器接收到请求后会调用Servlet来处理请求。
     Servlet的主要作用 :接收请求 ,处理请求 ,完成响应 。
     例如:
     当我们要完成一个登录功能时,用户会将输入的用户名和密码以POST请求的形式发送到服务器,但是服务器本身并不具有能力来读取用户发送的用户名和密码,也就不可能对用户名和密码进行验证,所以当服务器收到这类请求后需要将请求转个一个Servlet处理。
     Servlet实现类由我们编写,而由Web服务器(Servlet容器)调用,每个Servlet都必须实现javax.servlet.Servlet

2.HelloServlet
(1) 创建一个类并实现Servlet接口
public class HelloServlet implements Servlet {    @Override    public void init(ServletConfig config) throws ServletException {    }    @Override    public ServletConfig getServletConfig() {        return null;    }    /**     * service方法是Servlet最重要的方法,Servlet每次接收请求时     * 都会调用service方法     * request:代表的是请求报文,是浏览器发送给服务器的     * response:代表的是响应报文,是服务器发送给浏览器的     */    @Override    public void service(ServletRequest request, ServletResponse response)            throws ServletException, IOException {        System.out.println("这是我的第一个Servlet!!");        //向浏览器返回一个内容        //获取一个输出流        PrintWriter out = response.getWriter();        //通过流向浏览器输出一个内容        out.print(new Date());    }    @Override    public String getServletInfo() {        return null;    }    @Override    public void destroy() {    }}
(2) 在WEB-INF目录下的web.xml文件中注册映射Servlet.
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">  <servlet>    <servlet-name>HelloServlet</servlet-name>    <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>  </servlet>  <servlet-mapping>    <servlet-name>HelloServlet</servlet-name>    <url-pattern>/hello</url-pattern>  </servlet-mapping></web-app><!--   注册servlet     servlet-name:Servlet的别名,在服务器中Servlet所有的配置都是通过别名,这个名字是给程序员用的,程序员通过别名对Servlet进行配置。     servlet-class:Servlet的全类名,用来创建Servlet实例, 这个名字是给服务器使用的,服务器通过全类名来创建Servlet实例。     url-pattern:为Servlet映射的请求地址,通过该地址可以访问我们创建的Servlet,这个名字是给用户使用的,用户通过该地址来访问Servlet。-->
3.Servlet的生命周期:Servlet对象从被创建到被销毁的过程。
当我们第一次访问Servlet时,有三个方法被调用了: 构造器 ,init ,service 。第一次以后每次访问,只会调用: service当服务器停止时: destroy
(1) 构造器    当Servlet第一次接收请求的时候调用,用来创建Servlet对象,只调用了一次。    Servlet是一个单例的,在服务器中同一个Servlet只有一个实例。    它是以多线程的形式调用service方法    Servlet不是线程安全,所以在service方法尽量不要操作全局变量(2) init()    在构造器调用之后马上被调用,用来初始化Servlet,只调用了一次。(3) service()    每次处理请求时,service都会调用,用来处理请求,会调用多次。(4) destroy()    当停止服务器时(项目卸载、Servlet对象销毁前),用来做一些收尾工作,只会调用一次。
4. ServletConfig
(1) 代表:SerlvetConfig代表的是Servlet的配置信息,具体来说就是Servlet标签中的内容,每一个Servlet都有其唯一的ServletConfig
(2) 获取:该对象由服务器创建,最终会作为参数传递到init()方法,我们可以在init中直接使用
(3) 功能
     ① 可以获取Servlet的别名
     ② 可以获取当前Servlet的初始化参数
     ③ 获取ServletContext对象:
@Override    public void init(ServletConfig config) throws ServletException {        //获取Servlet的别名        String servletName = config.getServletName();        System.out.println(servletName);        //获取当前Servlet的初始化参数        String user = config.getInitParameter("user");        String pwd = config.getInitParameter("password");        System.out.println(user+"--"+pwd);        //获取ServletContext对象        ServletContext servletContext = config.getServletContext();        System.out.println(servletContext);    }
5.ServletContext
(1) 代表:ServletContext代表的是整个的WEB应用,每一个WEB应用都有其唯一的一个ServletContext
(2) 获取:通过ServletConfig的getServletContext()方法获取
(3) 功能:
     ① 获取整个WEB应用的初始化参数
     ② 获取资源的真实路径(主要用来做文件的上传和下载)
                 String realPath = servletContext.getRealPath("index.html");
                 真实路径(物理路径):C:\Users\lilichao\Desktop\day07\note\笔记.txt
                 虚拟路径:http://localhost:8080/08_WEB_Servlet/BServlet
      ③ 作为一个域对象在不同的WEB资源之间共享数据
@Override    public void service(ServletRequest req, ServletResponse res)            throws ServletException, IOException {        //获取ServletContext        ServletContext servletContext = config.getServletContext();        //获取整个web应用的初始化参数        String phone = servletContext.getInitParameter("phone");        System.out.println("phone = "+phone);        //获取index.html的真实路径        String realPath = servletContext.getRealPath("hello.html");        System.out.println(realPath);    }
6.GenericServlet
     在显示开发中我们如果直接实现servlet接口功能也是可以正常实现的,但是所面临的问题是:如果我直接实现Servlet接口,那接口中的所有方法都必须要实现,但是这些方法有的我们用不到,而有的方法实现起来很麻烦而且没给servlet实现的代码都差不多,于是我们就需要一个抽象类来帮助我们实现servlet接口,实现一些通用的方法,而我们只需要继承GenericServlet就可以了,这样的好处是我们不在需要重写全部方法,而只需要重写必须的和我们需要的方法就可以。

7. HttpServlet
     HttpServlet是GenericServlet的子类,他是Tomcat中专门处理HttpServlet的Servlet(实际上Tomcat只处理Http类型的请求)所以在一般情况下我们都会通过继承HttpServlet来实现servlet。
     HttpServlet和GenericServlet一样都是一个抽象类,也就是不能对它们进行实例化,与GenericServlet不同HttpServlet中没有任何抽象方法,所以需要我们根据实际需求来重写它的方法。
     在GenericServlet中service(ServletRequest req, ServletResponse res)方法是一个抽象方法,必须要由子类实现,而在HttpServlet中已经被实现,而在HttpServlet的实现的方法中会被强制转换成HttpServletRequest和HttpServletResponse(不用担心会出现类型转换异常,因为传过来的对象本身就是该类型)。转换类型之后会调用HttpServlet中的一个重载的service(HttpServletRequest req, HttpServletResponse resp)方法。也就是说如果我们要重写service()方法不必再去重写GenericServlet的service()方法了,而可以直接重写HttpServlet重载的service()方法就可以了。
     在service(HttpServletRequest req, HttpServletResponse resp)方法中,会对它的请求类型进行判断,然后根据请求类型的不同再去调用不同的方法。如:post类型的请求回去调用doPost(),get请求回去调用doGet(),delete请求回去调用doDelete(),以此类推。但是在实际应用中我们只会使用到doPost()和doGet(),所以一般情况下我们不会去重写service()方法,而是去重写更简单的doGet()或者doPost()。
    
8.HttpServletRequest 和 HttpServletResponse
(1) HttpServletRequest
     代表:代表的是浏览器发送给服务器的请求报文
     获取:该对象由服务器创建最终作为参数传递doGet()或者doPost()方法中,我们可以在这两个方法中直接使用。
     功能:
     ① 获取用户发送的请求参数
     ② 获取项目的名字(主要用来设置绝对路径)
     ③ 可以作为一个域对象在不同的web资源之间共享数据。
     ④ 可以做请求的转发:转发就是Servlet收到请求以后,自己不去处理请求,而是调用服务器内部的其他资源去处理请求
(2) HttpServletResponse
     代表:代表是服务器发送给浏览器响应报文。
     获取:该对象由服务器创建最终作为参数传递doGet()或者doPost()方法中,我们可以在这两个方法中直接使用。
     功能:
     ① 向浏览器输出一个页面片段,这个方法实际上是在设置响应报文的响应体。
     ② 做请求的重定向
          所谓的重定向,指Servlet收到浏览器发送的请求以后,返回给浏览器一个特殊的响应,这个特殊的响应告诉浏览器,再去向另一个地址发送请求。
     ③ 重定向的特点:
     【1】重定向时浏览器发送了 2 次请求。
     【2】重定向是在浏览器端发生。
     【3】重定向时浏览器的地址栏会发生变化。
     【4】浏览器可以知道重定向的发生。 
(3) 代码说明
public class FServlet extends HttpServlet {    private static final long serialVersionUID = 1L;       protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        /**         * HttpServletRequest         *     代表:代表的是浏览器发送给服务器的请求报文         *  获取:该对象由服务器创建最终作为参数传递doGet()或者doPost()方法中,我们可以在这两个方法中直接使用。         *  功能:         *      [1]获取用户发送的请求参数         *      [2]获取项目的名字(主要用来设置绝对路径)         *      [3]可以作为一个域对象在不同的web资源之间共享数据。         *      [4]可以做请求的转发         */        //获取用户发送的请求参数        String username = request.getParameter("um");        String password = request.getParameter("password");        //将用户名输出到页面中        response.getWriter().print("username = "+username +"<br />");        response.getWriter().print("password = "+password);        //获取项目名        String contextPath = request.getContextPath();        System.out.println(contextPath);        //发起请求的转发        //1.获取一个请求的派发器        RequestDispatcher dispatcher = request.getRequestDispatcher("target.html");        //2.使用派发器发起转发        dispatcher.forward(request, response);    }    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        /**         * HttpServletResponse         *     代表:代表是服务器发送给浏览器响应报文。         *     获取:该对象由服务器创建最终作为参数传递doGet()或者doPost()方法中,我们可以在这两个方法中直接使用。         *  功能:         *      [1]向浏览器输出一个页面或者是页面片段         *      [2]做请求的重定向         */        //向浏览器输出一个页面片段        //这个方法实际上是在设置响应报文的响应体        //1.获取一个输出流        PrintWriter out = response.getWriter();        //2.通过这个流向浏览器输出一段信息        out.print("<h1>Hello Servlet!</h1>");        //做请求的重定向        response.sendRedirect("target.html");    }}

(4) 转发和重定向的对比:

     在一般情况下,用户名验证码等都正确就重定向到成功页面,如果失败就转发到失败页面。例如:
     重定向:response.sendRedirect(request.getContextPath()+ "/pages/user/regist_success.html" );
     转  发 :request.getRequestDispatcher( "/pages/user/regist_error.html" ).forward(request,response);
   
9.字符编码
     计算机在传输字符,需要将字符转换为二进制数据来传输,读取内容时又需要将二进制数据转换为字符,编码和解码所使用的规则,我们称为字符集,常见的字符集: ASCII、ISO-8859-1、GBK、GB2312、UTF-8。
     产生乱码问题的根本原因:编码和解码所采用的字符集不同。
     解决方案:统一编码和解码所采用的字符集为utf-8。         
(1) 请求:浏览器 --> 服务器 :浏览器编码,服务器解码
     ① post请求
     post请求是在Servlet中解码的,Servlet中默认使用iso-8859-1,而它不支持中文,所以肯定乱码,所以post请求我们只需要去指定request使用的字符集即可。
     解决方案:在request.getParameter()方法第一次调用之前调用一下代码:request.setCharacterEncoding("utf-8");
     ② get请求
      get请求是通过url地址来传递请求参数的,它会由Tomcat服务器自动解码,而服务器默认使用的是iso-8859-1。
      解决方案:修改服务器默认的解码字符集,在server.xml配置文件中,在Connector标签中,添加一个                                   URIEncoding="utf-8"。最终为:
<Connector  URIEncoding="utf-8"  connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
(2) 响应:服务器 --> 浏览器 :服务器编码,浏览器解码。
      解决方案:在向浏览器返回响应之前,调用如下代码:response.setContentType("text/html;charset=utf-8");

10.路径问题
    URL地址的格式:http://主机地址:端口号/项目名/资源路径/资源名
(1) 相对路径:
    相对路径相对于:http://主机地址:端口号/项目名/资源路径/
    由于转发的出现,相对路径非常容易出错,所以在开发中我们不使用相对路径,而是使用绝对路径。
(2) 绝对路径
    绝对路径使用 "/" 开头;
    由浏览器去解析的绝对路径,这个"/"代表的是服务器的根目录,http://主机地址:端口号/
         注意:由浏览器解析的绝对路径,我们需要添加上项目名。
    由服务器解析的绝对路径,这个"/"代表的是项目的根目录
         即:http://主机地址:端口号/项目名/所以由服务器解析路径不需要加上项目名。
(3) 常见的路径:
     ① url-pattern:
     ② 转发的路径:               
          url-pattern和转发的路径都是由服务器所解析的,是以项目的根目录为根目录,即: "/"代表的是项目的根目录:http://主机地址:端口号/项目名/
     ③ 重定向的路径:
     ④ 页面中的路径:
          重定向和页面中的路径都是由浏览器解析的,是以服务器的根目录为根目录,即:"/"代表的是服务器的根目录:http://主机地址:端口号/
(5) base标签(HTML页面的处理方式):
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Insert title here</title><!-- base标签中的href属性,将会作为页面中所有相对路径的前缀 --><!-- base标签的作用就是让我们可以以使用相对路径的方式使用绝对路径 --><!-- base标签只对相对路径起作用 --><base href="http://localhost:8080/10_WEB_Path/" /></head><body>    <h1>我是网站的首页</h1>    <!-- 使用绝对路径 -->    <a href="/10_WEB_Path/hello/1.html">去1.html</a>    <hr />    <!-- 使用base标签 -->    <a href="hello/1.html">去1.html</a></body></html>

原创粉丝点击