Servlet API

Servlet的API就是一组类和方法
其中主要的三个类有
HttpServlet
HttpServletRequest
HttpServletResponse

HttpServlet

这是编写Servlet代码用到的核心类
通过继承这个类 并重新写其中的方法 让tomcat去调用到这里的逻辑

方法名称 调用时机
init 在HttpServlet实例化之后被调用一次
destroy 在HttpServlet示例不再使用的时候调用一次
service 收到HTTP请求的时候调用
doGet 收到GET请求的时候调用(由service方法调用)
doPost 收到POST请求的时候调用(由service方法调用)
doPut/doDelete/doOptions 收到其他请求的时候调用(由service方法调用)

webapp被加载的时候 执行init 使用这个方法进行一些初始化操作
webapp在被销毁的时候(tomcat结束) 执行destroy 使用这个方法进行一些收尾工作 但是这个方法不保证能够调用到 所以关闭tomcat还可以通过 8005端口给tomcat发起特殊请求(可以执行destroy) tomcat就关闭了 或者直接杀死tomcat进程(无法执行destroy)
每次收到请求都会执行service 处理每个请求

Servlet的生命周期(什么阶段 做什么事)

  1. webapp刚被加载的时候 调用servlet的init方法
  2. 每次收到请求的时候 调用service方法
  3. webapp要结束的时候 调用destroy方法

对于上述的方法 浏览器只能方便构造get请求 不方便构造其他的方法 所以可以使用postman

创建一个MethodServlet类

public class MethodServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("doGet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("doPost");
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("doPut");
    }

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("doDelete");
    }
}

启动tomcat
Servlet API_第1张图片
然后我们使用postman软件使用上述的各种方法发出请求
Servlet API_第2张图片
Servlet API_第3张图片
Servlet API_第4张图片

Servlet API_第5张图片

HttpServletRequest

Tomcat收到HTTP请求 就会被解析成下面对象

方法 描述
String getProtocol() 返回请求协议的名称和版本
String getMethod() 返回请求的HTTP方法的名称 例如GET POST 或者 PUT
String getRequestURI() 从协议名称直到HTTP请求的第一行的查询字符串中 返回该请求的URL的一部分
String getContextPath() 返回指示请求上下文的请求URI部分
String getQueryString() 返回包含在路径后的请求URL中的查询字符串
Enumeration getParameterNames() 返回一个String对象的枚举 包含在该请求中包含的参数的名称
String getParameter(String name) 以字符串形式返回请求参数的值 或者如果参数不存在则返回null
String[] getParameterValues(String name) 返回一个字符串对象的数组 包含所有给定的请求参数的值 如果参数不存在则返回null
Enumeration getHeaderNames(String name) 返回一个枚举 包含该请求中包含的所有头名
String getHeader(String name) 以字符串形式返回指定请求头的值
String getCharacterEncoding() 返回请求主体中使用的字符编码的名称
String getContentType() 返回请求主体的MIME类型 如果不知道类型则返回null
int getContentLength() 以字节为单位返回请求主体的长度 并提供输入流 或者如果长度未知则返回-1
InputStream getInputStream() 用于读取请求的body内容 返回一个InputStream对象

注意:URI 唯一资源标识符 URL 唯一资源定位符

Enumeration getParameterNames()
String getParameter(String name)
可以通过一些方式 给服务器传递自定义的数据(query string、body(键值对格式))

Enumeration getHeaderNames(String name)
String getHeader(String name)
获取到请求头里的键值对Tomcat收到请求之后也会把请求头解析成Map

示例:

@WebServlet("/Reques")
public class RequesServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //将调用req的各种方法汇总到一个字符串中
        StringBuilder respBody = new StringBuilder();
        respBody.append(req.getProtocol());
        respBody.append(req.getMethod());
        respBody.append(req.getRequestURI());
        respBody.append(req.getContextPath());
        respBody.append(req.getQueryString());

        //拼接header
        Enumeration<String> headers = req.getHeaderNames();
        while (headers.hasMoreElements()){
            String header = headers.nextElement();
            respBody.append(header+":"+req.getHeader(header));
        }
        //统一返回结果
        resp.getWriter().write(respBody.toString());
    }
}

Servlet API_第6张图片
让网页换行显示

@WebServlet("/Reques")
public class RequesServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        //将调用req的各种方法汇总到一个字符串中
        StringBuilder respBody = new StringBuilder();
        respBody.append(req.getProtocol());
        respBody.append("
"
); respBody.append(req.getMethod()); respBody.append("
"
); respBody.append(req.getRequestURI()); respBody.append("
"
); respBody.append(req.getContextPath()); respBody.append("
"
); respBody.append(req.getQueryString()); respBody.append("
"
); //拼接header Enumeration<String> headers = req.getHeaderNames(); while (headers.hasMoreElements()){ String header = headers.nextElement(); respBody.append(header+":"+req.getHeader(header)); respBody.append("
"
); } //统一返回结果 resp.getWriter().write(respBody.toString()); } }

Servlet API_第7张图片
相当于把http请求详情打印出来

String getParameter(String name)
如何获取到query string 和 body的数据?
示例:
获取query string

@WebServlet("/Pameter")
public class PameterServlet extends HttpServlet {
    //约定 客户端使用query string传递数据
    //例如 username=zhangsan&password=123456
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("username=" + username);
        System.out.println("password=" + password);
        resp.getWriter().write("ok!");
    }
}

Servlet API_第8张图片

Servlet API_第9张图片
获取body(只考虑form表单格式)

@WebServlet("/Pameter2")
public class Pameter2Servlet extends HttpServlet {
    //预期让客户端发出一个POST请求 同时使用form格式的数据 在body中把数据传递过来
    //body 形如:
    //username=张三&password=123
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username =req.getParameter("username");
        String password =req.getParameter("password");
        System.out.println("username="+username);
        System.out.println("password="+password);
        resp.getWriter().write("ok!");
    }
}

Servlet API_第10张图片
在这里插入图片描述
body为json的格式
我们要使用这种格式要用jackson jackson也是第三方库需要通过maven从中央仓库把这个库下载并导入到项目中
maven地址: https://mvnrepository.com/
Servlet API_第11张图片
我们在2.14版本之中选择一个

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.14.2</version>
</dependency>

添加到pom.xml文件后下载依赖
Servlet API_第12张图片
如果报红可以点击右侧的maven然后重新下载
Servlet API_第13张图片
然后我们可以使用一个ObiectMapper类的方法
把一个对象映射到JSON字符串 也可以把JSON字符串映射到对象
创建一个JsonServlet类
Servlet API_第14张图片

我们使用了objectMapper.readValue()这个方法将json字符串给解析成了Java对象
其中第一个参数是一个对象流 表示了json是从请求的body使用通过getInputStream得到对象 进一步的读取出来的
第二个参数 则是指定的类型 当前得到的json字符串需要转换成一个Java对象需要指定对象的类型就和上面的User类一个类型(定义一个类 让这个类里的属性的名字和类型和json字符串相匹配)
通过上面的方法就把json字符串映射成一个Java对象的过程
我们打开psotman测试

可以看到我们可以将一个json格式的body请求转换成了一个java对象
Servlet API_第15张图片
服务器已经顺利的把客户端发来的json格式数据给进行解析
在这里插入图片描述
readValue就把req的body的字符串给解析 然后构造了User对象

HttpServletResponse

同样也是和HTTP响应数据相匹配(状态码 各种header body)针对这些属性就可以进行"设置"
请求对象 拿到之后的目的 是为了获取里面的属性(读)
响应对象 拿到之后的目的 是为了设置里面的属性(写)
对于doXXX这样的方法 就是要根据请求计算响应
请求对象 是Tomcat收到请求之后 对http协议解析得到的对象
响应对象 是Tomcat创建空的对象 我们在代码中把响应对象的属性设置好返回给客户端

方法 描述
void setStatus(int sc) 设置状态码
void setHeader(String name,String value) 设置一个带有给定名称的值的header 如果name已存在 则覆盖旧的值
void addHeader(String name,String value) 添加一个带有给定名称和值的header 如果name已存在 不覆盖旧的值 并添加新的键值对
void setContentType(String type) 设置被发送到客户端的响应的内容类型
void setCharacterEncoding(String charset) 设置被发送到客户端的字符编码(MIME字符集)例如 UTF-8
void sendRedirect(String location) 使用指定的重定向位置URL 发送临时响应到客户端
PrintWriter() 用于往body中写入文本格式数据
OutputStream getOutputStream() 用于往body中写入二进制格式数据

注意:
使用了addHeader haeder中就可能出现key相同的两个键值对

设置状态码示例:
将状态码设置成200
Servlet API_第16张图片
Servlet API_第17张图片
设置成500
Servlet API_第18张图片
Servlet API_第19张图片
设置成404
Servlet API_第20张图片
Servlet API_第21张图片

设置响应报头示例:
此处通过refresh属性设置浏览器自动刷新(每隔两秒返回一个时间戳)
Servlet API_第22张图片

Servlet API_第23张图片
Servlet API_第24张图片
让页面重定义到百度主页

Servlet API_第25张图片

我们打开抓包工具八爪鱼
然后浏览器输入
在这里插入图片描述
就会自动跳转到百度网页
Servlet API_第26张图片
从八爪鱼可以看出我们的浏览器先访问了这一个url然后才跳转百度网页
在这里插入图片描述
浏览器看到开头请求的两个字段就知道要跳转到百度了
Servlet API_第27张图片
301是永久重定向
302是临时重定向
或者使用 resp.sendRedirect(“https://www.baidu.com”);一次性把两个步骤合到一起

Servlet API_第28张图片

让服务器返回一个html数据
Servlet API_第29张图片
浏览器看到的是
Servlet API_第30张图片
这是因为在IDEA里的中文字符串一般都是utf8的编码
浏览器会跟随系统的编码windows简体中文版本默认的编码是gbk 使用要按照gbk的方式匹配
我们就可以使用

 resp.setContentType("text/html;charset=utf8");

Servlet API_第31张图片

Servlet API_第32张图片

你可能感兴趣的:(servlet,http)