JavaWeb核心篇(2)——Request和Response

上篇文章中提及到了Servlet,在Servlet中我们主要继承了HTTPServlet类,在HTTPServlet类中我们会接触到两个对象

这篇文章主要介绍Servlet中使用的Request和Respnse对象

简单介绍

首先我们先了解一下客户端与服务端之间信息如何传递:

从上图,我们可以看到:

  • 客户端发送请求,而请求是以HTTP请求数据格式进行发送,因而Servlet就创建了一个Request类来封装这些接收数据
  • 服务端给出响应,而响应是以HTTP响应数据格式进行发送,因而Servlet就创建了一个Response类来封装这些返回数据

简单来说:

  • Request对象:获得请求数据
  • Response对象:设置响应数据

Request介绍

我们在介绍Request之前,应当先了解一下Request的继承体系:

我们可以看到HttpServletRequest是基于ServletRequest接口创建的针对Http协议的请求对象接口

我们在使用Request对象时,也常常使用HttpServletRequest接口

Request获得请求数据

Request对象被创建的主要目的就是获得请求数据

我们将根据HTTP请求数据对象的三种格式分开介绍获得请求数据方法

  1. 请求行:

请求行格式:

  1. GET/request-demo/req1?username=zhangsan HTTP/1.1

请求行获得代码:

函数 解释
String getMethod() 获得请求方式(GET/POST)
String getContextPath() 获得虚拟目录(项目访问路径):/request-demo
StringBuffer getRequestURL() 获得URL(统一资源定位符):http://localhost:8080/request-demo/req1
String getRequestURI() 获得URI(统一资源标识符):/request-demo/req1
String getQueryString 获得请求参数(GET方法):username=zhangsan HTTP/1.1
  1. 请求头:

请求头格式:

  1. User-Agent: Mozilla/5.0 Chrome/91.0.4472.106

请求头获得代码:

函数 解释
String getHeader(String name) 根据请求头名称,获得值
  1. 请求体:

请求体格式:

  1. username=superbaby&password=123456

请求体获得代码:

函数 解释
ServletInputStream getInputStream() 获得字节输入流
BufferedReader getReader() 获得字符输入流

最后给出代码展示:

  1. package com.itheima.web.request;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.BufferedReader;
  8. import java.io.IOException;
  9. /**
  10. * request 获取请求数据
  11. */
  12. @WebServlet("/req1")
  13. public class RequestDemo1 extends HttpServlet {
  14. @Override
  15. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  16. // String getMethod():获取请求方式: GET
  17. String method = req.getMethod();
  18. System.out.println(method);//GET
  19. // String getContextPath():获取虚拟目录(项目访问路径):/request-demo
  20. String contextPath = req.getContextPath();
  21. System.out.println(contextPath);
  22. // StringBuffer getRequestURL(): 获取URL(统一资源定位符):http://localhost:8080/request-demo/req1
  23. StringBuffer url = req.getRequestURL();
  24. System.out.println(url.toString());
  25. // String getRequestURI():获取URI(统一资源标识符): /request-demo/req1
  26. String uri = req.getRequestURI();
  27. System.out.println(uri);
  28. // String getQueryString():获取请求参数(GET方式): username=zhangsan
  29. String queryString = req.getQueryString();
  30. System.out.println(queryString);
  31. //------------
  32. // 获取请求头:user-agent: 浏览器的版本信息
  33. String agent = req.getHeader("user-agent");
  34. System.out.println(agent);
  35. }
  36. @Override
  37. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  38. //获取post 请求体:请求参数
  39. //1. 获取字符输入流
  40. BufferedReader br = req.getReader();
  41. //2. 读取数据
  42. String line = br.readLine();
  43. System.out.println(line);
  44. }
  45. }

Request通用方式获得请求参数

在请求参数的获取方法上GET与POST有所不同:

  • GET:String getQueryString()
  • POST: BufferedReader getReader()

那么如果我们能够采用一种方法同时使GET和POST获得参数,就可以实现两者的通用

Request对此提供了一下方法:

函数 解释
Map<String,String[]> getParameterMap() 获得所有参数Map的集合
String[] getParametervalues(String name) 根据名称获得参数值(数组)
String getParameter(String name) 根据名称获得参数值

我们给出通用方法,并做出解释:

  1. package com.itheima.web.request;
  2. import javax.servlet.*;
  3. import javax.servlet.http.*;
  4. import javax.servlet.annotation.*;
  5. import java.io.IOException;
  6. import java.util.Map;
  7. /**
  8. * request 通用方式获取请求参数
  9. */
  10. @WebServlet("/req2")
  11. public class RequestDemo2 extends HttpServlet {
  12. @Override
  13. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  14. //GET请求逻辑
  15. //System.out.println("get....");
  16. //1. 获取所有参数的Map集合
  17. Map<String, String[]> map = req.getParameterMap();
  18. for (String key : map.keySet()) {
  19. // username:zhangsan lisi
  20. System.out.print(key+":");
  21. //获取值
  22. String[] values = map.get(key);
  23. for (String value : values) {
  24. System.out.print(value + " ");
  25. }
  26. System.out.println();
  27. }
  28. System.out.println("------------");
  29. //2. 根据key获取参数值,数组(我们希望查询参数为hobby的值,在查询中hobby的值为1,2)
  30. String[] hobbies = req.getParameterValues("hobby");
  31. for (String hobby : hobbies) {
  32. System.out.println(hobby);
  33. }
  34. //3. 根据key 获取单个参数值
  35. String username = req.getParameter("username");
  36. String password = req.getParameter("password");
  37. System.out.println(username);
  38. System.out.println(password);
  39. }
  40. @Override
  41. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  42. //POST请求逻辑
  43. // 因为两者可以共用一个方法,所以doPost直接调用doGet即可
  44. this.doGet(req,resp);
  45. /*System.out.println("post....");
  46. //1. 获取所有参数的Map集合
  47. Map<String, String[]> map = req.getParameterMap();
  48. for (String key : map.keySet()) {
  49. // username:zhangsan lisi
  50. System.out.print(key+":");
  51. //获取值
  52. String[] values = map.get(key);
  53. for (String value : values) {
  54. System.out.print(value + " ");
  55. }
  56. System.out.println();
  57. }
  58. System.out.println("------------");
  59. //2. 根据key获取参数值,数组
  60. String[] hobbies = req.getParameterValues("hobby");
  61. for (String hobby : hobbies) {
  62. System.out.println(hobby);
  63. }
  64. //3. 根据key 获取单个参数值
  65. String username = req.getParameter("username");
  66. String password = req.getParameter("password");
  67. System.out.println(username);
  68. System.out.println(password);*/
  69. }
  70. }

请求参数中文化导致乱码问题

当我们的请求参数中如果存在中文数据,可能会出现乱码(Tomcat8以下版本)

我们分别介绍POST和GET的中文乱码解决方案

  1. POST:

首先我们从根本上解释一下为什么会出现乱码:

  • POST底层以getReader()的方式以ISO-8859-1的形式获得输入流
  1. //1. 解决乱码:POST,getReader()
  2. // 默认情况下POST以ISO-8859-1的形式获取流
  3. // POST中可以直接设置字符输入流的编码
  4. // request.setCharacterEncoding() 改变字符输入流的获得格式
  5. request.setCharacterEncoding("UTF-8");
  1. GET:

首先我们从根本上解释一下为什么会出现乱码:

  • 当HTML识别到内容后,会以UTF-8的形式进行编码,并发送给服务端
  • 但服务端在接收到数据后,会以ISO-8859-1的形式进行解码
  • 编码解码方式不同,对中文的处理方式不同,导致中文数据出现乱码
  1. // 我们以一个例子来模拟GET乱码的解决过程
  2. package com.itheima.web.request;
  3. import java.io.UnsupportedEncodingException;
  4. import java.net.URLDecoder;
  5. import java.net.URLEncoder;
  6. public class URLDemo {
  7. public static void main(String[] args) throws UnsupportedEncodingException {
  8. String username = "张三";
  9. // 1.2步模拟了乱码过程;3,4步解决乱码过程
  10. //1. URL编码(HTML传递)
  11. //URLEncoder.encode(username, "utf-8");表示对username进行utf-8形式的编码,形成code
  12. String encode = URLEncoder.encode(username, "utf-8");
  13. System.out.println(encode);
  14. //2. URL解码
  15. //URLDecoder.decode(encode, "ISO-8859-1");表示对encode进行ISO-8859-1形式的解码,形成decode
  16. String decode = URLDecoder.decode(encode, "ISO-8859-1");
  17. System.out.println(decode);
  18. //3. 转换为字节数据,编码
  19. byte[] bytes = decode.getBytes("ISO-8859-1");
  20. //4. 将字节数组转为字符串,解码
  21. String s = new String(bytes, "utf-8");
  22. System.out.println(s);
  23. }
  24. }

因为GET的方法属于通用方法,所以在整个项目中可以直接通过第二种方法来进行GET和POST的中文乱码修改问题

  1. package com.itheima.web.request;
  2. import javax.servlet.*;
  3. import javax.servlet.http.*;
  4. import javax.servlet.annotation.*;
  5. import java.io.IOException;
  6. import java.nio.charset.StandardCharsets;
  7. /**
  8. * 中文乱码问题解决方案
  9. */
  10. @WebServlet("/req4")
  11. public class RequestDemo4 extends HttpServlet {
  12. @Override
  13. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  14. //1. 解决乱码:POST,getReader()
  15. //request.setCharacterEncoding("UTF-8");//设置字符输入流的编码
  16. //2. 获取username
  17. String username = request.getParameter("username");
  18. System.out.println("解决乱码前:"+username);
  19. //3. GET,获取参数的方式:getQueryString
  20. // 乱码原因:tomcat进行URL解码,默认的字符集ISO-8859-1
  21. /* //3.1 先对乱码数据进行编码:转为字节数组
  22. byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
  23. //3.2 字节数组解码
  24. username = new String(bytes, StandardCharsets.UTF_8);*/
  25. username = new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);
  26. System.out.println("解决乱码后:"+username);
  27. }
  28. @Override
  29. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  30. this.doGet(request, response);
  31. }
  32. }

Request请求转发

首先讲解一下请求转发的概念:

  • 请求转发:一种在服务器内部的资源跳转方法
  • 当客户端发送请求后,服务端可以选择把这个请求转发出去或者说是共享出去

实现方式:

  1. req.getRequestDispatcher("资源B地址").forward(req,resp)

实现所需函数:

函数 解释
void setAttribute(String name,Object o) 存储数据到request域(一般在资源A地址存储)
Object getAttribute(String name) 根据key,获得value(一般在资源B地址存储)
void removeAttribute(String name) 根据key,删除该键值对

请求转发特点:

  • 浏览器地址栏路径不发生变化
  • 只能转发到当前服务器的内部资源
  • 一次请求,可以在转发的资源间使用request共享数据

我们给出两个/demo服务器端进行模拟:

  1. // 客户端资源A
  2. package com.itheima.web.request;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.annotation.WebServlet;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.IOException;
  9. import java.nio.charset.StandardCharsets;
  10. /**
  11. * 请求转发
  12. */
  13. @WebServlet("/req5")
  14. public class RequestDemo5 extends HttpServlet {
  15. @Override
  16. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  17. System.out.println("demo5...");
  18. System.out.println(request);
  19. //存储数据
  20. request.setAttribute("msg","hello");
  21. //请求转发
  22. request.getRequestDispatcher("/req6").forward(request,response);
  23. }
  24. @Override
  25. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  26. this.doGet(request, response);
  27. }
  28. }
  1. // 客户端资源B
  2. package com.itheima.web.request;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.annotation.WebServlet;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.IOException;
  9. /**
  10. * 请求转发
  11. */
  12. @WebServlet("/req6")
  13. public class RequestDemo6 extends HttpServlet {
  14. @Override
  15. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  16. System.out.println("demo6...");
  17. System.out.println(request);
  18. //获取数据
  19. Object msg = request.getAttribute("msg");
  20. System.out.println(msg);
  21. }
  22. @Override
  23. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  24. this.doGet(request, response);
  25. }
  26. }

Response介绍

同样,我们也来介绍一下Response的体系结构:

我们在使用Response时,也以HttpServletResponse为主

设置响应数据

和获取数据相同,我们把函数根据响应数据的三部分分别展示:

  1. 响应行:

响应行格式:

  1. HTTP/1.1 200 OK

响应行设置函数:

函数 解释
void setStatus(int sc) 设置响应状态码
  1. 响应头:

响应头格式:

  1. Content-Type:text/html

响应头设置函数:

函数 解释
void setHeader(String name,String value) 设置响应头键值对
  1. 响应体:

响应体格式:

  1. <html><head></head><body></body></html>

响应体设置函数:

函数 解释
PrintWriter getWriter() 获得字符输出流
ServletOutputStream getOutputStream() 获得字节输出流

下面给出代码示例:

  1. package com.itheima.web.response;
  2. import javax.servlet.*;
  3. import javax.servlet.http.*;
  4. import javax.servlet.annotation.*;
  5. import java.io.IOException;
  6. @WebServlet("/resp1")
  7. public class ResponseDemo1 extends HttpServlet {
  8. @Override
  9. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  10. System.out.println("resp1....");
  11. //1.设置响应状态码 302
  12. response.setStatus(302);
  13. //2. 设置响应头 Location
  14. response.setHeader("Location","/request-demo/resp2");
  15. }
  16. @Override
  17. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  18. this.doGet(request, response);
  19. }
  20. }

重定位

首先我们介绍一下重定位:

  • 重定位:一种资源跳转方式
  • 客户端向服务器A发出请求,当该资源A无法满足客户端发出的请求,资源A返回响应(响应码302表示无法处理,并给出响应头location:xxx告诉客户端应该去哪个资源B解决问题),然后客户端再向资源B发送请求,由资源B来设置响应数据

实现方式:

  1. resp.setStatus(302);
  2. resp.setHeader("location","资源B的路径")
  1. resp.sendRedirect("资源B的路径")

重定位特点:

  • 浏览器地址栏路径发生变化
  • 可以重定位到任意位置的资源(服务器内部,外部均可以)
  • 两次请求,不能在多个资源使用request共享数据

下面给出代码示例:

  1. package com.itheima.web.response;
  2. import javax.servlet.*;
  3. import javax.servlet.http.*;
  4. import javax.servlet.annotation.*;
  5. import java.io.IOException;
  6. @WebServlet("/resp1")
  7. public class ResponseDemo1 extends HttpServlet {
  8. @Override
  9. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  10. System.out.println("resp1....");
  11. //重定向
  12. /*//1.设置响应状态码 302
  13. response.setStatus(302);
  14. //2. 设置响应头 Location
  15. response.setHeader("Location","/request-demo/resp2");*/
  16. //简化方式完成重定向
  17. //动态获取虚拟目录
  18. String contextPath = request.getContextPath();
  19. // 这里资源B的路径是虚拟目录+设置名
  20. response.sendRedirect(contextPath+"/resp2");
  21. //response.sendRedirect("https://www.itcast.cn");
  22. }
  23. @Override
  24. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  25. this.doGet(request, response);
  26. }
  27. }

资源路径问题:

浏览器使用:需要加虚拟目录(项目访问路径)

服务端使用:不需要加虚拟目录

目前已学习内容:

resp.sendRedirect("路径") : 加虚拟目录

req.getRequestDispatcher("路径") : 不加虚拟目录

Response响应字符数据

我们可以使用Response对象向客户端发送数据

具体步骤:

  1. 通过Response对象获得字符输出流:
  1. PrintWriter writer = resp.getWriter();
  1. 写数据
  1. writer.write("aaa");

注意:

  • 该流不需要关闭,随着响应结束,response对象销毁,由服务器关闭
  • 中文数据乱码:原因通过Response获取的字符输出流默认编码:ISO-8859-1
  1. resp.setContentType("text/html;charset=utf-8");

代码展示:

  1. package com.itheima.web.response;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.io.PrintWriter;
  9. /**
  10. * 响应字符数据:设置字符数据的响应体
  11. */
  12. @WebServlet("/resp3")
  13. public class ResponseDemo3 extends HttpServlet {
  14. @Override
  15. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  16. response.setContentType("text/html;charset=utf-8");
  17. //1. 获取字符输出流
  18. PrintWriter writer = response.getWriter();
  19. //content-type
  20. //response.setHeader("content-type","text/html");
  21. writer.write("你好");
  22. writer.write("<h1>aaa</h1>");
  23. //细节:流不需要关闭
  24. }
  25. @Override
  26. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  27. this.doGet(request, response);
  28. }
  29. }

Response响应字节数据

我们可以使用Response对象向客户端发送数据

传统具体步骤:

  1. 通过Response对象获得字符输出流
  1. ServletOutputStream outputStream = resp.getOutputStream();
  1. 写数据
  1. outputStream.write(字节数据);

IOUtils工具类使用:

  1. 导入坐标:
  1. <dependency>
  2. <groupId>commons-io</groupId>
  3. <artifactId>commons-io</artifactId>
  4. <version>2.6</version>
  5. </dependency>
  1. 使用即可:
  1. IOUtils.copy(输入流,输出流);

代码展示:

  1. package com.itheima.web.response;
  2. import org.apache.commons.io.IOUtils;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.ServletOutputStream;
  5. import javax.servlet.annotation.WebServlet;
  6. import javax.servlet.http.HttpServlet;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import java.io.FileInputStream;
  10. import java.io.IOException;
  11. import java.io.PrintWriter;
  12. /**
  13. * 响应字节数据:设置字节数据的响应体
  14. */
  15. @WebServlet("/resp4")
  16. public class ResponseDemo4 extends HttpServlet {
  17. @Override
  18. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  19. //1. 读取文件
  20. FileInputStream fis = new FileInputStream("d://a.jpg");
  21. //2. 获取response字节输出流
  22. ServletOutputStream os = response.getOutputStream();
  23. //3. 完成流的copy
  24. /* byte[] buff = new byte[1024];
  25. int len = 0;
  26. while ((len = fis.read(buff))!= -1){
  27. os.write(buff,0,len);
  28. }*/
  29. IOUtils.copy(fis,os);
  30. fis.close();
  31. }
  32. @Override
  33. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  34. this.doGet(request, response);
  35. }
  36. }

结束语

好的,关于Request和Respone的内容就到这了

附录

该文章属于学习内容,具体参考B站黑马程序员陈老师的JavaWeb课程

这里附上链接:01-Request和Response介绍&Request继承体系_哔哩哔哩_bilibili

JavaWeb核心篇(2)——Request和Response的更多相关文章

  1. JavaWeb核心篇(3)——JSP,MVC,三层架构

    JavaWeb核心篇(3)--JSP,MVC,三层架构 在本篇文章中我们会学习到JSP,MVC,三层架构 虽然JSP已经快被时代所淘汰,但是在一些老旧的工作场所还是有在使用,所以了解一下也不为过 至于 ...

  2. javaWeb中 servlet 、request 、response

    1.Servlet (1)Servlet是JavaEE的一个动态web资源开发技 术,就是在服务器上运行的小程序,这个小程序是由服务器调用的,服务器为了能调用这个小程序,就要求这样的程序必须实现一个S ...

  3. Servlet第三篇【request和response简介、response的常见应用】

    response.request对象 Tomcat收到客户端的http请求,会针对每一次请求,分别创建一个代表请求的request对象.和代表响应的response对象 既然request对象代表ht ...

  4. 第十五节:HttpContext五大核心对象的使用(Request、Response、Application、Server、Session)

    一. 基本认识 1. 简介:HttpContext用于保持单个用户.单个请求的数据,并且数据只在该请求期间保持: 也可以用于保持需要在不同的HttpModules和HttpHandlers之间传递的值 ...

  5. JavaWeb学习总结(三)response与request

    一.response response是Servlet.service方法的一个参数,类型为javax.servlet.http.HttpServletResponse.在客户端发出每个请求时,服务器 ...

  6. JavaWeb学习篇之----容器Request详解

    前篇说到了Response容器对象,这篇我们就来看一下Request容器对象,之前也说过了,这个两个容器对象是相对应的,每次用户请求服务器的时候web容器就会给创建这对容器对象,他们是共存亡的,当然R ...

  7. JavaWeb(一)Servlet中的request与response

    一.HttpServletRequest概述 1.1.HttpServletRequest简介 HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP ...

  8. JavaWeb学习笔记四 request&response

    HttpServletResponse 我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应res ...

  9. JavaWeb Request和Response

    1. Request与Response 1.1. Web应用运行机制 到目前为止,我们已经掌握了Web应用程序的运行机制,现在学习的就是Web应用程序运行机制中很重要的内容 —— Request与Re ...

随机推荐

  1. mysql中in的用法详解

    一.基础用法 mysql中in常用于where表达式中,其作用是查询某个范围内的数据. select * from where field in (value1,value2,value3,-) 当 ...

  2. 关于我用python表白成功这件事【表白成功】

    520,并非情人所属, 我们可以表白万物, 不管什么时候, 这都是一个特别的日子, 今天,我要表白所有, 心里有我的人! 在这个充满幸福的日子里, 我要把最美好的祝福, 送给心里有我的每一个人: 祝愿 ...

  3. 浪姐打分看不够?用几行Python代码模拟评委打分

    大家好鸭~我是小熊猫比赛大家都看过吧,每次是不是都对比赛成绩充满期待.特别是浪姐的打分看的简直欲罢不能- 今天就用Python来模拟评委打分,这个案例很短也很简单,很适合新手跟小白练习. 在某次十佳歌 ...

  4. (数据库提权——Redis)Redis未授权访问漏洞总结

    一.介绍 1.Redis数据库 Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key- ...

  5. SSRS筛选器的IN运算(即包含于)用法

    筛选器的IN运算,在Microsoft的官网上没像样儿的例子,不好设置,很容易错 Microsoft上的文档:https://docs.microsoft.com/zh-cn/sql/reportin ...

  6. final关键字概念与四种用法和final关键字用于修饰类和成员方法

    fifinal关键字 概述 学习了继承后,我们知道,子类可以在父类的基础上改写父类内容,比如,方法重写.那么我们能不能随意的继承 API中提供的类,改写其内容呢?显然这是不合适的.为了避免这种随意改写 ...

  7. 大事件回顾 | Eolink 5月重要动态速览!

    在春天和夏天中间悄然而至的 5 月刚刚过去,及时求变,在呼啸而过的时代中保持竞争力的 Eolink 最近又有哪些大动作呢?下面我们梳理了5月以来 Eolink 的重要动态,给大家提供阅览. 01 ** ...

  8. 平衡树——splay 一

    splay 一种平衡树,同时也是二叉排序树,与treap不同,它不需要维护堆的性质,它由Daniel Sleator和Robert Tarjan(没错,tarjan,又是他)创造,伸展树是一种自调整二 ...

  9. 使用JAVA CompletableFuture实现流水线化的并行处理,深度实践总结

    大家好,又见面啦. 在项目开发中,后端服务对外提供API接口一般都会关注响应时长.但是某些情况下,由于业务规划逻辑的原因,我们的接口可能会是一个聚合信息处理类的处理逻辑,比如我们从多个不同的地方获取数 ...

  10. Mybatis源码解读-插件

    插件允许对Mybatis的四大对象(Executor.ParameterHandler.ResultSetHandler.StatementHandler)进行拦截 问题 Mybatis插件的注册顺序 ...