07. Servlet


一、Servlet技术

1.1、什么是Servlet

??Servlet是JavaEE规范之一。规范就是接口。Servlet是JavaWeb三大组件之一。三大组件分别是:Servlet程序、Filter过滤器、Listener监听器。Servlet是运行在服务器上的一个java小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。

1.2、如何实现Servlet程序

  1. 编写一个类去实现Servlet接口
  2. 实现Servlet(),处理请求,并响应数据
  3. 到【WEB-INF】中的【web.xml】中配置servlet程序的访问地址
package star.light.servlet;

import javax.servlet.*;
import java.io.IOException;

public class HelloServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * 专门用于处理请求和响应的
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("HelloServlet被访问了!");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

??其中web.xml的内容如下:

<?xml version="1.0" encoding="UTF-8"?>

    
    
        
        HelloServlet
        
        star.light.servlet.HelloServlet
    
    
    
        
        HelloServlet
        
        /hello
    

常见的错误

  1. url-pattern 中配置的路径没有以斜杠打头
    • Caused by: java.lang.IllegalArgumentException: Invalid hello in servlet mapping
  2. servlet-name 配置的值不存在
    • Caused by: java.lang.IllegalArgumentException: Servlet mapping specifies an unknown servlet name HelloServlet1
  3. servlet-class 标签的全类名配置错误
    • 启动时不报错,创建Servlet实例时出错

1.3、URL地址如何定位到Servlet程序

1.4、Servlet的生命周期

  1. 执行 Servlet() 构造器方法
  2. 执行 init() 初始化方法
  3. 执行 service() 方法
  4. 执行 destroy() 销毁方法
package star.light.servlet;

import javax.servlet.*;
import java.io.IOException;

public class HelloServlet implements Servlet {

    public HelloServlet() {
        System.out.println("构造器方法");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init初始化方法");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service方法!");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("destroy销毁方法");
    }
}

??其中web.xml的内容同上。

默认情况下,servlet()构造器和init()初始化方法只在第一次访问创建Servlet程序会调用;我们可以通过来设置启动的先后顺序,数据越小,启动越靠前,最小值0;
service()方法每次访问都会调用;
destroy()销毁方法只有在web工程停止的时候才会调用;
Servlet在容器中是单例的、线程不安全的;

1.5、GET和POST请求的分发处理

package star.light.servlet;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class HelloServlet implements Servlet {

    public HelloServlet() {

    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Service()被执行了");
        HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
        String method = httpServletRequest.getMethod();                                 //获取请求的方式
        if ("GET".equals(method)){
            doGet();
        } else if ("POST".equals(method)){
            doPost();
        }
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }

    public void doGet(){
        System.out.println("get请求");
    }

    public void doPost(){
        System.out.println("post请求");
    }
}

??【get.html】写在【web】文件夹的下一级目录,内容如下:




    
    Title


    

??【post.html】写在【web】文件夹的下一级目录,内容如下:




    
    Title


    

??其中【web.xml】的内容同上。

1.6、通过继承HttpServlet实现Servlet程序

??一般在实际项目开发中,都是使用继承 HttpServlet 类的方式去实现 Servlet 程序。

  1. 编写一个类去继承 HttpServlet 类
  2. 根据业务需要重写 doGet() 或 doPost()
  3. 根据业务需要重写 doGet() 或 doPost()
package star.light.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


public class HelloServlet extends HttpServlet {

    /**
     * doGet()在get请求中调用
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet的doGet()");
    }

    /**
     * doPost()在post请求中调用
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet的doPost()");
    }
}

??其中【web.xml】、【get.html】、【post.html】的内容同上。

1.7、Servlet类的继承体系

二、ServletConfig类

??ervletConfig 类是 Servlet 程序的配置信息类,它可以获取可以获取 Servlet 程序的别名 servlet-name 的值、获取初始化参数 init-param、获取 ServletContext 对象。Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建,我们负责使用。 Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个 Servlet 程序创建时,就创建一个对应的 ServletConfig 对象。

package star.light.servlet;

import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


public class HelloServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        //获取Servlet程序的别名Servlet-name的值
        System.out.println("HelloServlet程序的别名是:" + servletConfig.getServletName());
        //获取初始化参数
        System.out.println("初始化参数username的值是:" + servletConfig.getInitParameter("username"));
        System.out.println("初始化参数url的值是:" + servletConfig.getInitParameter("url"));
        //获取ServletContext对象
        System.out.println(servletConfig.getServletContext());
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

??其中【web.xml】中内容如下:

<?xml version="1.0" encoding="UTF-8"?>

    
        HelloServlet
        star.light.servlet.HelloServlet
        
        
            
            username
            
            root
        
        
            url
            jdbc:mysql://localhost:3306/test
        
    
    
        HelloServlet
        /hello
    

三、ServletContext类

??ServletContext 是一个接口,它表示 Servlet 上下文对象。一个 web 工程,只有一个 ServletContext 对象实例。ServletContext 对象是一个域对象。域对象,是可以像 Map 一样存取数据的对象。这里的域指的是存取数据的操作范围,整个 web 工程。 ServletContext 是在 web 工程部署启动的时候创建,在 web 工程停止的时候销毁。ServletContext 类可以获取 web.xml 中配置的上下文参数 context-param、获取当前的工程路径,格式: /工程路径、获取工程部署后在服务器硬盘上的绝对路径。它还可以像 Map 一样存取数据。

存数据 取数据 删除数据
Map put() get() remove()
域对象 setAttribute() getAttribute() removeAttribute()
package star.light.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ServletContextTest extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取web.xml中配置的上下文参数context-param
        ServletContext context = getServletConfig().getServletContext();
        System.out.println(context);

        String username = context.getInitParameter("username");
        System.out.println("context-param参数username的值是:" + username);
        System.out.println("context-param参数password的值是:" + context.getInitParameter("password"));

        //获取当前的工程路径,格式:/工程路径
        System.out.println("当前工程路径:" + context.getContextPath());

        //获取工程部署在服务器硬盘上的绝对路径
        /*
            /  斜杠被服务器解析地址为:http://ip:port/工程名   映射到IDEA代码的web目录
         */
        System.out.println("工程部署的路径是:" + context.getRealPath("/"));
        System.out.println("工程下css目录的绝对路径是:" + context.getRealPath("/css"));

        //像Map一样存取数据
        ServletContext context1 = getServletContext();          //获取ServletContext对象
        System.out.println("保存之前:Context中获取域数据key1的值是:" + context.getAttribute("key1"));
        context.setAttribute("key1","value1");
        System.out.println("保存之后:Context中获取域数据key1的值是:" + context.getAttribute("key1"));
    }
}
package star.light.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ServletContextTest1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletContext context = getServletContext();
        System.out.println(context);
        System.out.println("Context1中获取域数据key1的值是:" + context.getAttribute("key1"));
    }
}

??其中【web.xml】中内容如下:

<?xml version="1.0" encoding="UTF-8"?>

    
    
        username
        root
    
    
        password
        abc123
    
    
        ServletContextTest
        star.light.servlet.ServletContextTest
    
    
        ServletContextTest
        /servletContext
    
    
        ServletContextTest1
        star.light.servlet.ServletContextTest1
    
    
        ServletContextTest1
        /servletContext1
    

四、Http协议

4.1、什么是HTTP协议

??协议是指双方,或多方,相互约定好,大家都需要遵守的规则。HTTP 协议是 Hyper Text Transfer Protocol(超文本传输协议)的缩写。所谓 HTTP 协议,就是指,客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫 HTTP 协议。 HTTP 协议中的数据又叫报文。浏览器发送给服务器的数据:请求报文;服务器返回给浏览器的数据:响应报文。

4.2、请求的HTTP格式协议

??客户端给服务器发送数据叫请求。服务器给客户端回传数据叫响应。请求又分为 GET 请求,和 POST 请求两种。

  • GET 请求
    • 请求行:展示当前请求的最基本的信息
      • 请求的方式 GET
      • 请求的资源路径[+?+请求参数]
      • 请求的协议的版本号 HTTP/1.1
    • 请求头:通过具体的参数对本次请求进行详细的说明
      • key : value 组成 不同的键值对,表示不同的含义。
    • get方式,没有请求体,但是有一个queryString
  • POST 请求
    • 请求行:展示当前请求的最基本的信息
      • 请求的方式 POST
      • 请求的资源路径[+?+请求参数]
      • 请求的协议的版本号 HTTP/1.1
    • 请求头:通过具体的参数对本次请求进行详细的说明
      • key : value 不同的请求头,有不同的含义
    • post方式,有请求体,form data

4.3、常见的GET请求和POST请求

  • GET请求
    • form标签 method="get"
    • a标签
    • link标签引入css
    • script标签引入js文件
    • img标签引入图片
    • iframe标签引入html文件
    • 在浏览器地址栏中输入地址后敲回车
  • POST请求
    • form标签 method="post"

4.4、响应的HTTP协议格式

  • 响应行
    • 响应的协议和版本号 HTTP/1.1
    • 响应状态码
    • 响应状态描述符
  • 响应头:包含服务器的信息,服务器发送给浏览器的信息(内容的媒体信息、编码、内容长度等)
    • key:value 不同的响应头,有其不同的含义
  • 响应体:相应的实际内容

4.4、常用的响应码说明

状态码 含义
200 服务器成功处理了当前请求,成功返回响应
302 重定向
400 [SpringMVC特定环境]请求参数问题
403 没有权限
404 找不到目标资源
405 请求方式和服务器端对应的处理方式不一致
406 [SpringMVC特定环境]请求扩展名和实际返回的响应体类型不一致
50X 服务器端内部错误,通常都是服务器端抛异常了

4.5 MIME类型说明

??MIME 是 HTTP 协议中数据类型。 MIME 的英文全称是"Multipurpose Internet Mail Extensions" 多功能 Internet 邮件扩充服务。MIME 类型的格式是“大类型/小 类型”,并与某一种文件的扩展名相对应。

常见的 MIME 类型:

文本 文本类型 MIME类型
超文本标记语言 .html,htm text/html
普通文本 .txt text/plan
RTF文本 .rtf applicaton/rtf
GIF图形 .gif image/gif
JPEG图形 .jpeg,jpg image/jpeg
au声音文件 .au audio/basic
MIDI音乐文件 .mid,.midi audio/midi,audio/x-midi
RealAudio音乐文件 .ra,.ram audio/x-pn-realaudio
MPEG文件 .mpg,.mpeg video/mpeg
AVI文件 .avi video/x-msvideo
GZIP文件 .gz application/x-gzip
TAR文件 .tar application/x-tar

五、会话跟踪技术

??因为服务器无法判断两次请求是同一个客户端发过来的,还是不同客户端发过来的。因此,客户端第一次发请求给服务器时,服务器会获取 session,获取不到,则会创建新的,然后响应给客户端。下次客户端给服务器发请求时,会把 sessionID 发给服务器,那么服务器就能获取到,然后服务器就会判断这一次请求和上次某次请求时同一个客户端,从而能够区分开客户端。

request.getSession()                //获取当前会话,没有则创建一个新的会话
request.getSession(true)            //获取当前会话,没有则创建一个新的会话
request.getSession(false)           //获取当前会话,没有则返回null,不会创建新的会话
session.getId()                     //获取sessionID
session.isNew()                     //判断当前session是否是新的
session.getMaxInactiveInterval()    //session的非激活间隔时长,默认1800秒
session.setMaxInactiveInterval()    //设置session的非激活间隔时长
session.invalidate()                //强制让会话立即失效
session.getCreationTime()           //获取会话的创建时间
session.getLastAccessedTime()       //获取会话最近一次的访问时间

??template:

package star.light;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class SessionTest extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 获取session,如果获取不到,则创建一个新的session
        HttpSession session = req.getSession();
        System.out.println("Session ID:" + session.getId());

        System.out.println(session.isNew());

        System.out.println("session maxInactiveInterval: " + session.getMaxInactiveInterval());
        session.setMaxInactiveInterval(1000);
        System.out.println("session maxInactiveInterval: " + session.getMaxInactiveInterval());

        System.out.println("session create time: " + session.getCreationTime());
        System.out.println("session last access time: " + session.getLastAccessedTime());

//        session.invalidate();
    }
}

??其中【web】下的【WEB-INF】中的web.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>

    
        SessionTest
        star.light.SessionTest
    
    
        SessionTest
        /sessionTest
    

六、session保存作用域

??session保存作用域是和具体的某一个session对应的;

session.setAttribute(key,vale)      //向当前session保存作用域保存一对数据
session.getAttribute(key)           //从session保存作用域获取指定key所对应的value值
removeAttribute()                   //从当前session的保存作用域中的数据

??template:

package star.light;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ScopeTest1 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //向HttpSession保存数据
        req.getSession().setAttribute("username","sakura");
    }
}
package star.light;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ScopeTest2 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //从HttpSession保存作用域中获取数据
        Object username = req.getSession().getAttribute("username");
        System.out.println(username);
    }
}

??其中【web】下的【WEB-INF】中的web.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>

    
        ScopeTest1
        star.light.ScopeTest1
    
    
        ScopeTest1
        /scopeTest1
    
    
        ScopeTest2
        star.light.ScopeTest2
    
    
        ScopeTest2
        /scopeTest2
    

七、请求转发与请求重定向

7.1、请求转发

??请求转发是指,服务器收到请求后,从一次资源跳转到另一个资源的操作叫请求转发。它是一次响应的过程,对于客户端而言,内部经过了多少次转发,客户端是不知道的。

请求转发的特点:

  • 浏览器地址栏没有变化
  • 它们是一次请求
  • 它们共享Request域中的数据
  • 可以转发到【WEB-INF】目录下
  • 不能访问工程以外的资源

package star.light.servlet;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class Servlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取请求的参数
        String username = req.getParameter("username");
        System.out.println("在Servlet1中查看参数:" + username);

        //传递给Servlet2
        req.setAttribute("key","Servlet1传递的数据");
        //请求转发必须以斜杠开头,,斜杠表示:http://ip:port/工程名/,映射到IDEA代码的web目录
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
        requestDispatcher.forward(req,resp);
    }
}
package star.light.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class Servlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取请求的参数
        String username = req.getParameter("username");
        System.out.println("在Servlet2中查看参数:" + username);

        //查看Servlet传来的参数
        Object key = req.getAttribute("key");
        System.out.println("Servlet1传来的数据:" + key);

        System.out.println("Servlet2执行相关程序");
    }
}

??其中【web.xml】中内容如下:

<?xml version="1.0" encoding="UTF-8"?>

    
        Servlet1
        star.light.servlet.Servlet1
    
    
        Servlet1
        /servlet1
    
    
        Servlet2
        star.light.servlet.Servlet2
    
    
        Servlet2
        /servlet2
    

7.2、base标签

??当我们点击a标签进行跳转的时候,浏览器地址栏中的地址是:http://localhost:8080/servlet/a/b/c.html;跳转回去的a标签的路径是:../../index.html;所有相对路径在工作时都会参照当前浏览器地址栏中的地址来进行跳转,那么参照后得到的地址是:http://localhost:8080/servlet/index.html(正确的跳转路径);

??当我们使用请求转发的方式来进行跳转的时候,浏览器地址栏中的地址是:http://localhost:8080/servlet/forwradC;跳转回去的a标签的路径是:../../index.html;素有相对路径在工作时都会参照当前浏览器地址栏中的地址进行跳转,那么参照后得到的地址是:http://localhost:8080/index.html(错误的地址);

??base标签可以设置当前页面中所有相对路径工作时,参照哪个路径来进行跳转.

package star.light.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ForwardC extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("经过了ForwardC程序");
        req.getRequestDispatcher("/a/b/c.html").forward(req,resp);
    }
}

??其中【index.html】写在【web】文件夹的下一级目录,内容如下:




    
    Title


    

这是首页,web下的index.html

用超链接的方式跳到a/b/c/html
用请求转发的方式跳到a/b/c/html

??【c.html】写在【web】文件夹的下一级目录,内容如下:




    
    Title
    
    


    

这是【a】下的【b】下的c.html页面

跳回首页

??其中【web.xml】中内容如下:

<?xml version="1.0" encoding="UTF-8"?>

    
        ForwardC
        star.light.servlet.ForwardC
    
    
        ForwardC
        /forwardC
    

7.4、请求重定向

??请求重定向,是指客户端给服务器发请求,然后服务器告诉客户端说。我给你一些地址。你去新地址访问。叫请求重定向(因为之前的地址可能已经被废弃)。请求重定向是两次响应的过程,客户端肯定知道请求 URL 有变化。

请求重定向的特点:

  • 浏览器地址栏会发生改变
  • 两次请求
  • 不共享Request域中数据
  • 不能访问WEB-INF下的资源
  • 可以访问工程外的资源

package star.light.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class Response1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Response1已搬迁!");
        req.setAttribute("key","value");
//        //方式一:
//        //设置响应状态码,表示重定向(已搬迁)
//        resp.setStatus(302);
//        //设置响应头,说明新的地址在哪里
//        resp.setHeader("Location","http://localhost:8080/servlet/response2");

        //方式2:
        resp.sendRedirect("http://localhost:8080/servlet/response2");
    }
}
package star.light.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class Response2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(req.getAttribute("key"));
        resp.getWriter().write("response2's result!");
    }
}

??其中【web.xml】中内容如下:

<?xml version="1.0" encoding="UTF-8"?>

    
        Response1
        star.light.servlet.Response1
    
    
        Response1
        /response1
    
    
        Response2
        star.light.servlet.Response2
    
    
        Response2
        /response2
    

八、HttpServletRequest类

8.1、HttpServletRequest类概述

??每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中。 然后传递到 service()(doGet() 和 doPost())中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。

8.2、HttpServletRequest类的常用方法

getRequestURI()             //获取请求的资源路径
getRequestURL()             //获取请求的统一资源定位符(绝对路径)
getRemoteHost()             //获取客户端的 ip 地址
getHeader()                 //获取请求头
getParameter()              //获取请求的参数
getParameterValues()        //获取请求的参数(多个值的时候使用)
getMethod()                 //获取请求的方式 GET 或 POST
setAttribute(key, value)    //设置域数据
getAttribute(key)           //获取域数据
getRequestDispatcher()      //获取请求转发对象

template:

package star.light.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HttpServletRequestTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("获取请求的资源路径:" + req.getRequestURI());
        System.out.println("获取请求的统一资源定位符(绝对路径):" + req.getRequestURL());
        System.out.println("获取客户端的ip地址:" + req.getRemoteHost());
        System.out.println("获取请求头User-Agent:" + req.getHeader("User-Agent"));
        System.out.println("获取请求方式:" + req.getMethod());
    }
}

??其中【web.xml】中内容如下:

<?xml version="1.0" encoding="UTF-8"?>

    
        HttpServletRequestTest
        star.light.servlet.HttpServletRequestTest
    
    
        HttpServletRequestTest
        /httpServletRequest
    

8.3、获取请求参数

package star.light.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;

public class ParameterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("GET请求获取请求的参数");

        /**
         *  //get方式目前不需要上设置编码(基于tomcat8)
         *  //如果get方式请求发送的中文数据需要编码(tomcat8之前)
         */
        String username = req.getParameter("username");     //获取请求的参数
        String password = req.getParameter("password");
        String[] hobby = req.getParameterValues("hobby");

        /**
         *  // 1.将字符串打散成字节数据
         *  byte[] bytes = username.getBytes("ISO-8859-1");
         *  // 2.将字节数组按照设定的编码重新组装成字符串
         *  username = new String(bytes,"UTF-8");
         */
        System.out.println("用户名:" + username);
        System.out.println("密码:" + password);
        System.out.println("爱好:" + Arrays.asList(hobby));
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("POST请求获取请求的参数");

        //在获取请求参数之前才有效
        req.setCharacterEncoding("UTF-8");                      //设置请求体的字符集为UTF-8,从而解决请求的中文乱码问题

        String username = req.getParameter("username");         //获取请求的参数
        String password = req.getParameter("password");
        String[] hobby = req.getParameterValues("hobby");

        System.out.println("用户名:" + username);
        System.out.println("密码:" + password);
        System.out.println("爱好:" + Arrays.asList(hobby));
    }
}

??【get.html】写在【web】文件夹的下一级目录,内容如下:




    
    Title


    
用户名:
密 码:
兴 趣:Java python UnrealEngine

??【post.html】写在【web】文件夹的下一级目录,内容如下:




    
    Title


    
用户名:
密 码:
兴 趣:Java python UnrealEngine

??其中【web.xml】中内容如下:

<?xml version="1.0" encoding="UTF-8"?>

    
        ParameterServlet
        star.light.servlet.ParameterServlet
    
    
        ParameterServlet
        /parameterServlet
    

九、HttpServletResponse类

9.1、HttpServletResponse类概述

??HttpServletResponse 类和 HttpServletRequest 类一样。每次请求进来,Tomcat 服务器都会创建一个 Response 对象传 递给 Servlet 程序去使用。HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应的信息, 我们如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse 对象来进行设置。

9.2、两个输出流

  • getOutputStream(); 字节流 常用于下载(传递二进制数据)
  • getWriter(); 字符流 常用于回传字符串(常用)

两个流同时只能使用一个。 使用了字节流,就不能再使用字符流,反之亦然,否则就会报错。

package star.light.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        //方式一;不推荐使用
//        //服务器默认的字符集为ISO-8859-1,如果要使用中文,需要将服务器的字符集的设置为utf-8,
//        resp.setCharacterEncoding("UTF-8");
//        //设置浏览器使用UTF-8字符集
//        resp.setHeader("Content-type","text/html;charset=UTF-8");

        //方式二:此方法一定要在获取流对象之前调用才有效
        resp.setContentType("text/html;charset=UTF-8");
        System.out.println(resp.getCharacterEncoding());

        PrintWriter writer = resp.getWriter();
        writer.write("response's content!
"); writer.write("你好,世界!
"); } }

??其中【web.xml】中内容如下:

<?xml version="1.0" encoding="UTF-8"?>

    
        ResponseIOServlet
        star.light.servlet.ResponseIOServlet
    
    
        ResponseIOServlet
        /responseIOServlet