Servlet api细解

Servlet api细解_第1张图片

日升时奋斗,日落时自省 

目录

1、HttpServlet

2、HttpServletRequest

2.1、GET请求中的参数

2.2、获取POST请求中的参数(FORM)

2.3、获取POST请求中的参数(JSON)

3、HttpServletResponse

3.1、设置状态码

3.2、页面跳转

3.3、页面刷新


1、HttpServlet

我们写Servlet代码的时候,首先第一步就是先创建类,继承自HttpServlet,重写其中要紧的方法

核心方法:

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

此处方法来演示一帆:

首先先看一下service方法,看一下对应的jidea提供的service的源码

 剩下的就是init和destroy方法

那我们这里就创建一个Maven项目此处就叫做(hello_servlet3),以下直接写出这两个方法,使用idea中smart tomcat插件直接运行(附代码)

@WebServlet("/hello3")
public class Hello_Servlet3  extends HttpServlet {
    @Override
    public void init() throws ServletException {
        //可以在这里重写 init 方法
        //输入 一些咱们自己的 “初始化” 相关的逻辑
        System.out.println("init ");
    }

    @Override
    public void destroy() {
        System.out.println("destroy ");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //把数据显示到服务器控制台
        System.out.println("hello3");
        //把数据写回浏览器
        resp.getWriter().write("hello world3");
    }


}

Servlet api细解_第2张图片

 HttpServlet类中主要也就是针对请求和响应来,所以以下就是针对HttpServletRequest和HttpServletResponse类来进行细致化了解

2、HttpServletRequest

当Tomcat通过Socket API读取HTTP请求(字符串),并且按照HTTP协议的格式把字符串解析成HttpServletRequest对象

接收HTTP的请求来的req,能做到调用基本的方法,完成我们的后端操作(以下是常用API)

方法 描述
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 getHeader(String
name)
以字符串形式返回指定的请求头的值。
String
getCharacterEncoding()
返回请求主体中使用的字符编码的名称。
String getContentType() 返回请求主体的 MIME 类型,如果不知道类型则返回 null。
int getContentLength() 以字节为单位返回请求主体的长度,并提供输入流,或者如果长
度未知则返回 -1。
InputStream
getInputStream()
用于读取请求的 body 内容. 返回一个 InputStream 对象

创建一个ShowRequestServlet类来演示对应的方法(以下附加代码 ,注释比较详细,一下还有图解)

如果一直是按照我们这里创建的目录和注解,直接输入路径 :127.0.0.1:8080/hello_servlet3/showRequest

@WebServlet("/showRequest")
public class ShowRequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //这里是设置响应的 content-type 告诉浏览器 显影就body 里的数据格式是啥样的
        //setContentType 调用的第一个参数 是数据类型此处是text/html   第二个参数 是设计字符集
        resp.setContentType("text/html; charset=utf8");
        // 这个 StringBuilder 把这些 api 的结果拼起来 ,统一写响应中
        StringBuilder stringBuilder=new StringBuilder();
        //协议名称 和 版本号  getProtocol 反馈出来的是 协议名称 和 版本号
        stringBuilder.append(req.getProtocol());
        stringBuilder.append("
"); //方法 此处的getMethod http请求时使用的方法 是什么 基本常见的就是 GET POST stringBuilder.append(req.getMethod()); stringBuilder.append("
"); //字符串 getRequestURI 从请求中得到一个地址 stringBuilder.append(req.getRequestURI()); stringBuilder.append("
"); //getQueryString 针对网址后面 查询字符串 stringBuilder.append(req.getQueryString()); stringBuilder.append("
"); //获取到 header 中所有的键值对 getHeaderNames方法 返回的是一个枚举类型 Enumeration headerNames=req.getHeaderNames(); //此处采用类似于迭代的方式 将所有的剪键值对 打印出来 while(headerNames.hasMoreElements()){ //每次都会提取下一个元素 key值 String headername=headerNames.nextElement(); //此处getHeader 表示的请求头的对应值 也就是 value值 stringBuilder.append(headername+":"+req.getHeader(headername)); stringBuilder.append("
"); } //前面使用了 StringBuild 来接收这些字符串 此处就是将这些字符串 响应给页面 resp.getWriter().write(stringBuilder.toString()); } }

Servlet api细解_第3张图片

 上面介绍了基本的操作,查看一些HTTP发送来的信息(其实把这些抓个包也能看到,可以作为对比)

剩下的还有很多方法,

这里在罗列两个刚刚没有提到的方法,getCharacterEncoding()直接传入字符集就可以了,也是设定字符集的方法,但是我们上面已经提及到了一个可以设置字符集的:getContentType(),里面就可以带着设置了字符集,如果两个都在同一个类里面出现的时候getContentType()更加强制,所以这个功能也更强,这里也就算是提一下,认识就行,不能见了不认识,也比较常见

还有一个就是:getContentLength(),以字节为单位返回请求主体的长度,如果长度未知则返回-1

2.1、GET请求中的参数

GET请求中的参数一般都是通过query string 传递给服务器的也就是刚刚演示到的查询字符串

127.0.0.1:8080/hello_servlet3/showRequest?studentId=10&classId=20

此时浏览器通过query string 给服务器传递里两个参数一个是studentId 还有一个就是classId对应值就是 10 和 20 其实一个键值对表示的

这里创建一个GetParameter类来演示这个效果,这个类仍然在这个项目当中(代码附加详细注释)

@WebServlet("/getparameter")
public class GetParameterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //预测一个浏览器会发一个形如 /getParameter?student=10&classId=20请求
        //借助req 里的getParameter 方法就能拿到query string 中的键值对内容
        String student=req.getParameter("studentId");
        String classId=req.getParameter("classId");
        resp.setContentType("text/html");
        //这里就使用 以下这设置字符集的操作 这里设置,上面就不需要设置了
        resp.setCharacterEncoding("utf8");
        //上面 setContentType 可以同时设置两个 也可以分开设置同时 设置下面的字符集
        //resp.setCharacterEncoding("utf-8");
        //设置字符集这些都要写在write上面 ,不能写在下面的 要不就不会生效了
        //响应在程序内部
        System.out.println("学生 ="+student+"序号 ="+classId);
        //下面直接响应给页面显示出来
        resp.getWriter().write("学生 ="+student+"序号 ="+classId);
    }
}

Servlet api细解_第4张图片

 2.2、获取POST请求中的参数(FORM)

POST请求的参数一般通过body传递给服务器,body中的数据格式有很多种类,form表单也是一种形式,仍然可以操作类获取参数值,创建一个的类,叫做POSTParameterServlet,其实和上一个代码是一样的,只是为了区分开form表单和query string

Servlet 的java代码:

@WebServlet("/postParameter")
public class PostParameterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String student=req.getParameter("studentId");
        String classId=req.getParameter("classId");
        resp.setContentType("text/html;charset=utf8");
        resp.getWriter().write("studentId ="+student+"classId ="+classId);
    }
}

form表单的代码:




    
    
    
    Document



    

 如何操作?

Servlet api细解_第5张图片

 2.3、获取POST请求中的参数(JSON)

如果POST请求中的body是按照JSON的格式来传递,获取参数此处代码有所变动

此处新创建一个类,来接收JSON形式的,该类叫做:PostParameter2Servlet

JSON是以body的形式来传输数据的,需要对这个body进行处理

body里面存放的也是键值对,但是这里取值就不同了,java代码中需要创建一个类,定义并且与body相同的属性(前后端就会先约定好,需要的属性,下面图解操作)

Servlet代码:

class Student{
    public int studentId;
    public int classId;
}
@WebServlet("/postParameter2")
public class PostParameter2Servlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //通过这个方法处理 body 为 json 格式的数据
        //直接把 req 对象里 body 完整读取出来
        //getInputStream
        // 在流对象中读多少个字节 取决于 content - type


        //getContentLength   获取字节的长度
        int length=req.getContentLength();
        //创建一个缓存 大小就是 获取字节大小的缓存大小
        byte[] buffer=new byte[length];
        //此处就 需要获取body字节数
        InputStream inputStream= req.getInputStream();
        //将这个字节流 读入缓存中
        inputStream.read(buffer);
        //把这个字节数组  构造成 String 打印出来 String中的第一个参数就是 缓存数组 第二个参数就是从第几个开始 从0 开始
        //第三个参数就是 缓存数组的长度 第四个参数就是 设定字符集
        String body=new String(buffer,0,length,"utf8");
        //打印 在控制台
        System.out.println(body);
        //响应到页面
        resp.getWriter().write(body);
    }
}

JSON代码:

此处使用的就是postman构造一个post请求进行发送

Servlet api细解_第6张图片

 前后端交互解析:
Servlet api细解_第7张图片

 当然了这里提及到JSON格式的传输使用字节流读取并响应的,看着有点繁琐,能不能一步到位,当然可以,只需要改动后端代码就可以

更改后的后端代码:(但是这里需要导入Jackson的依赖,需要去中央仓库找 和前面提到的Servlet依赖是一样的方法 输入网址的地方输入nvm

Servlet api细解_第8张图片

 附后端改后的代码:

class Student{
    public int studentId;
    public int classId;
}
@WebServlet("/postParameter2")
public class PostParameter2Servlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建一个 ObjectMapper 能够将JSON格式转换为 java
        ObjectMapper objectMapper=new ObjectMapper();
        //readValue 将一个 json 格式的字符串转换成 java 对象
        /*
        * 1、 从body 中读取 json 格式 字符串
        * 2、根据第二个参数对象, 创建 Student 实例
        * 3、解析上述json 格式的字符串 处理成 map 键值对结构
        * 4、变量所有键值对 看键的名字 和 Student那个实例属性名字匹配 就把value值赋值上去
        * 5、返回Student实例
        * */
        Student student=objectMapper.readValue(req.getInputStream(),Student.class);
        System.out.println(student.studentId+","+student.classId);
        resp.getWriter().write(student.studentId+","+student.classId);
    }
}

操作:启动服务器 然后 postman向服务器发送消息

演示:

Servlet api细解_第9张图片

总结:

<1>此处使用的自定义了Student类 ,这个类用来表示解析之后生成的JSON对象,这个类的属性和名字和类型要和JSON字符串的key相对应

<2>Jackson依赖的核心类就是ObjectMapper,其中的readValue方法把一个JSON字符串转换成Java对象,其中的writeValueAsString方法把一个java对象转成JSON格式字符串

<3>readValue的第二个参数为Student类型(也就是我们自定义的类型),通过这个类对象,在readValue1的内部就可以借助反射机制来构造出Student对象,并且根据JSON中key,把对应的value赋值给Student的对应字段

以上操作基本已经全部演示了一下(有想法的友友们,可以自己尝试自己试一下)

3、HttpServletResponse

Servlet中的方法接收到请求后计算出响应,把响应的数据设置到HttpServletResponse对象中

后来Tomcat就会把这个HttpServletResponse对象按照HTTP协议的格式,转换成一个字符串,并通过socket写回给浏览器

此处也会演示HttpServletResponse相关的一些API

方法 描述
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 getWriter() 用于往 body 中写入文本格式数据.
OutputStream
getOutputStream()
用于往 body 中写入二进制格式数据.

3.1、设置状态码

此处创建一个StatusServlet类,注解设置为@WebServlet("/status")

附代码(加详细注释):

@WebServlet("/status")
public class StatusServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //这里就不再演示接收请求了进行请求处理了, 此处直接响应一个 404 
        //其实这个响应不一有啥反应 空白页
        resp.setStatus(404);
        // 但是这里不设置 body   设置一下 响应数据类型
        resp.setContentType("text/html;charset=utf8");
        //响应的一个html的语句 仅仅只是为了演示效果
        resp.getWriter().write("

404 没有找到

"); } }

这里代码写好以后,直接在idea中启动程序

Servlet api细解_第10张图片

 以上最后提到了针对响应报错的一个方法sendError,我个人感觉挺好用,其实可以尝试一下,毕竟只需要一行代码;

3.2、页面跳转

这里创建一个RedirectServlet类 注解设置为 @WebServlet("/Redirect")

附代码(加详细注释):

@WebServlet("/Redirect")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          //sendRedirect方法能直接将页面跳转到 参数的 url 中
          resp.sendRedirect("https://www.sogou.com");
          //下面这两行  其实表达的是和上面一行代码 的意思是一样的  setStatus设置状态码 302表示重定向
//        resp.setStatus(302);
        //setHeader 第一个参数写 Location 就是我们在HTTP 抓包的时候看见的 重定向 key 第二个参数就是 url 
//        resp.setHeader("Location","https://www.sogou.com");
    }
}

Servlet api细解_第11张图片

 3.3、页面刷新

创建一个AutoRefreshServlet类 ,注解设置为@WebServlet("/autoRefreshServlet")

附代码(加详细注释):

@WebServlet("/autoRefreshServlet")
public class AutoRefreshServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //执行操作刷新操作  第二个参数是一秒  也就是每一秒刷新一次
        resp.setHeader("Refresh","1");
        //获取时间 但是这里获取的是一个时间戳  还需要转换一下时间格式
        long timeStamp=new Date().getTime();
        //下面使用SimpleDateFormat类 进行java的时间格式转换 ,这个可以去查看一下
        //因为不好记 而且语言与语言之间不一样
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //调用SimpleDateFormat中的format方法 转换时间格式
        String date = format.format(timeStamp);
        //响应到页面上
        resp.getWriter().write("timeStamp:"+date);
    }
}

Servlet api细解_第12张图片

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