当前位置: 首页 > news >正文

怎么投诉网站制作公司银川网站建设那家好

怎么投诉网站制作公司,银川网站建设那家好,做国际贸易都用什么网站,网络营销推广怎么做目录 一、线程池 1. 构建线程池的类 2. 创建任务 3. 执行任务 测试 二、URL编码 解决方案 测试 三、如何接收客户端发送的全部信息 解决方案 测试 四、作业 1. 了解工厂模式 2. 了解反射技术 一、线程池 昨天使用了数据库连接池,我们了解了连接池的优…

目录

一、线程池

1. 构建线程池的类

2. 创建任务

3. 执行任务

测试

二、URL编码

解决方案

测试

三、如何接收客户端发送的全部信息

解决方案

测试

四、作业

1. 了解工厂模式

2. 了解反射技术


一、线程池

昨天使用了数据库连接池,我们了解了连接池的优点,那么也可以使用线程池来管理线程,

java自带的线程池的参数有 核心线程数,最大线程数,线程活跃时间,时间单位,任务队列,线程工厂,拒绝策略

为了学习了解线程池,我们先手写一个简单的线程池,只需要做到核心线程可重复利用就行

1. 构建线程池的类

属性:核心线程数,任务队列

方法:获取线程(静态代码块),执行任务(需要的参数:线程任务 Runnable)

为了避免创建多个对象,还需要设置单例模式

package com.shao.net;import java.util.concurrent.LinkedBlockingQueue;public class ThreadPool {// 定义一个成员静态变量,存储单例对象private static ThreadPool instance;// 线程池核心线程数private final static int MAX_THREAD_NUM = 10;// 存放任务的队列private static final LinkedBlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>();static {for (int i = 0; i < MAX_THREAD_NUM; i++) {final int finalI = i;new Thread(new Runnable() {@Overridepublic void run() {/***  线程池的线程,从队列中取出任务,这时线程不在临界区了,自动释放锁,然后执行任务,当执行完任务后,*  因为是while循环,所以会在 synchronized (taskQueue) 等待,*  当锁释放后,并且当前线程被唤醒时,会尝试获取锁,*  如果获取到锁,会进入临界区,如果队列中有任务,则取出,然后执行任务,如果没有,则等待*  等待下次获取到锁,会继续从上次进入等待态的位置继续往下执行,也就是 taskQueue.wait() 开始往下执行* */while (true) {Runnable task = null;synchronized (taskQueue) {System.out.println("线程" + finalI + "准备完成");// 队列为空,等待while (taskQueue.isEmpty()) {try {taskQueue.wait();   // 使当前线程等待,释放锁} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("线程" + finalI + "开始执行");// 从队列中取出任务task = taskQueue.poll();}if (task != null) {// 执行任务task.run();}}}}).start();}}// 私有化构造函数private ThreadPool() {}// 获取对象public static ThreadPool getInstance() {synchronized (ThreadPool.class) {if (instance == null) {instance = new ThreadPool();}return instance;}}public void execute(Runnable task) {// 当方法被调用时,会尝试获取锁,如果获取到锁,则将任务加入队列,并唤醒等待的线程synchronized (taskQueue) {taskQueue.add(task);taskQueue.notify();}}
}

2. 创建任务

这里的任务是之前线程执行的代码,我们把需要线程执行的任务放到一个类里,然后实现Runnable 

package com.shao.net;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;public class MyTask implements Runnable {private InputStream is;private OutputStream os;public MyTask(InputStream is, OutputStream os) {this.is = is;this.os = os;}@Overridepublic void run() {// 定义一个字节数组,存放客户端发送的请求信息byte[] bytes = new byte[1024];// 读取客户端发送的数据,返回读取的字节数int len = 0;try {len = is.read(bytes);if (len == -1) {return;}// 将读取的字节数组转换为字符串String msg = new String(bytes, 0, len);// 调用HttpRequest类解析请求信息HttpRequest httpRequest = new HttpRequest(msg);// 拼接请求的静态资源的路径// 路径是相对路径,从模块的根路径开始String filePath = "webs/" + httpRequest.getRequestModule();HttpResponse httpResponse = new HttpResponse(os, httpRequest);// 响应数据httpResponse.response(filePath);} catch (IOException e) {e.printStackTrace();}}
}

3. 执行任务

初始化线程池,来一个用户连接时,就创建一个任务,然后交给线程池,线程池取出一条线程执行任务的 run 方法

package com.shao.net;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;public class Tomcat {// 初始化线程池ThreadPool threadPool = ThreadPool.getInstance();public Tomcat() {ServerSocket ss = null;try {ss = new ServerSocket(8080);while (true) {// 调用accept()方法阻塞等待,直到有客户端连接到服务器,返回一个Socket对象用于与该客户端通信Socket socket = ss.accept();System.out.println("客户端连接成功");// 获取Socket对象的输入流,用于读取客户端发送的数据InputStream is = socket.getInputStream();// 获取Socket对象的输出流,用于向客户端发送数据OutputStream os = socket.getOutputStream();// 创建一个任务对象,将输入输出流作为参数传过去MyTask myTask = new MyTask(is, os);// 把任务作为参数传递给ThreadPool的execute()方法,启动一个线程执行MyTask对象中的run()方法threadPool.execute(myTask);}} catch (IOException e) {e.printStackTrace();} finally {//关闭连接通道try {ss.close();} catch (IOException e) {e.printStackTrace();}}}
}

测试

二、URL编码

在HTTP请求中,如果参数包含中文字符,会进行URL编码,以避免乱码或传输错误。URL编码是一种将URL中的非ASCII字符(如中文字符)转换为可以在Web浏览器和服务器之间传输的格式的过程。

URL编码会将非ASCII字符转换为十六进制编码,以便于在HTTP请求中安全传输。

‌URL编码的基本原理‌: URL编码将非ASCII字符(如中文字符)转换为"%"后跟两位十六进制数字的形式。例如,空格在URL编码中通常被转换为"%20"。对于中文字符,它们会被转码为以"%E"开头,后面跟着若干位十六进制数字的字符串。

解决方案

在接收到请求信息后,先进行解码,然后再解析信息

URLDecoder.decode(需要解码的字符串, 字符集或编码方式)

在 MyTask 类中添加

测试

三、如何接收客户端发送的全部信息

目前,我们的 Tomcat 最多只能一次接收 1KB,因为定义的字节数组只有1024个字节

但是,如果客户端发送的请求参数非常非常多呢?超过了 1024 个字节了怎么办?

把字节数组定义的大一点?不行的,因为网络传输一次最多传输 8KB,超过 8KB 就会分批传输,接收参数时也需要分批接收

那怎么判断参数已经接收完?

参数有很多一般是使用POST方法,而POST方法的请求头有 Content-Length 的字段,表示请求体的总长度

我们来试一下,打印一下请求的参数信息

这里可以看到 Content-Length 的值是 26,表示请求体的参数长度为26字节,图中显示参数的长度为 25,因为解析后没有显示参数连接符 & 

我们来使用 Apipost 来压力测试一下,参数很多是什么样子

可以看到,只读取到了一部分 出师表 的内容,而且还有乱码,这是因为没有完整读取一个 汉字的字节,UTF-8 编码中一个汉字需要 3 个字节

解决方案

package com.shao.net;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class MyTask implements Runnable {private InputStream is;private OutputStream os;private int totalLength;private StringBuilder sb;public MyTask(InputStream is, OutputStream os) {this.is = is;this.os = os;}@Overridepublic void run() {// 定义一个字节数组,存放客户端发送的请求信息byte[] bytes = new byte[1024];// 读取客户端发送的数据,返回读取的字节数int len = 0;try {// 第一次读取请求信息len = is.read(bytes);if (len == -1) {return;}// 将读取的字节数组转换为字符串String msg = new String(bytes, 0, len);// 调用HttpRequest类解析请求信息HttpRequest httpRequest = new HttpRequest(msg);/**  如果已读取的数据长度等于请求体的总长度,并且请求方法是 POST,说明请求体可能还没有读取完,需要读取剩余的数据* */if (bytes.length == len && "POST".equals(httpRequest.getRequestMethod())) {// 创建一个StringBuilder对象,用于拼接请求信息sb = new StringBuilder();sb.append(msg);// 获取 POST 请求方法中的请求体的总长度String length = httpRequest.getRequestHeaderParams().get("Content-Length");if (length != null) {totalLength = Integer.parseInt(length);}// 调用方法,读取剩余的请求体数据msg = getNotReadMsg(httpRequest, bytes, msg);}// 把请求信息进行URL解码,然后根据 UTF-8 进行编码String decodedMsg = URLDecoder.decode(msg, "utf-8");// 调用HttpRequest类解析请求信息httpRequest = new HttpRequest(decodedMsg);// 拼接请求的静态资源的路径// 路径是相对路径,从模块的根路径开始String filePath = "webs/" + httpRequest.getRequestModule();HttpResponse httpResponse = new HttpResponse(os, httpRequest);// 响应数据httpResponse.response(filePath);} catch (IOException e) {e.printStackTrace();}}/*** 读取剩余的请求体数据*/private String getNotReadMsg(HttpRequest httpRequest, byte[] bytes, String msg) throws IOException {int len;// 获取请求的参数HashMap<String, String> requestBodyParams = httpRequest.getRequestBodyParams();// 请求参数的数量int size = requestBodyParams.size();// 计算第一次读取到的请求体中参数的长度Set<Map.Entry<String, String>> entries = requestBodyParams.entrySet();int partLength = 0;for (Map.Entry<String, String> entry : entries) {partLength += (entry.getKey() + "=" + entry.getValue()).length();}// 减去第一次读取到的请求体中参数的长度,如果存在多个参数,需要考虑到 '&' 的个数if (size > 1) {totalLength -= (partLength + (size - 1));} else {totalLength -= partLength;}// 判断是否还有数据没有读完while (totalLength > 0) {// 第二次读取请求信息len = is.read(bytes);// 如果读取的字节数大于0,表示读取到数据了if (len > 0) {// 将读取的字节数组转换为字符串msg = new String(bytes, 0, len);// 拼接字符串sb.append(msg);// 减去读取的字节数totalLength -= len;} else {break;}}// 转成字符串格式返回return sb.toString();}
}

测试

可以看出已经全部读取到了,第二个参数也读取到了

四、作业

1. 了解工厂模式

优化 Dao,现在在 Service 层,调用Dao层都要 new 一下,这样就比较占内存,比如调用的都是 UserDao,那么只需要创建一次 UserDao 的对象就行了

2. 了解反射技术

优化 Servlet ,通过配置文件可以动态的创建 Servlet 对象

http://www.yayakq.cn/news/942658/

相关文章:

  • 微网站免费建站系统wordpress 4.4.9 漏洞
  • 兰州优化网站公司做网站推广怎么跟客户沟通
  • 做兼职设计去哪个网站好外贸出口工艺品怎么做外贸网站
  • 如何在中国建设银行网站转账河北怀来县建设局网站
  • 包头手机网站制作大气有内涵的公司名字
  • 做网站哪家强网上做调查问卷赚钱的网站
  • 无锡网站建设书生商友网页实时翻译器
  • 网站建设有哪些名词手机上如何建立wordpress
  • 网站建设管理情况自查报告怎么给网站做手机端
  • 建设网站需要哪些元素wordpress js代码放哪
  • 邢台兼职网站有哪些?小广告发布
  • 邢台提供网站设计公司哪家专业网站备案需要审核多久
  • 网站标题 逗号网页设计代码浮动效果
  • 做网站价格报价费用多少钱国外私人网站
  • 深圳建设品牌网站全球优秀网页设计机构
  • 青岛网站制作排名贵阳做网站电话
  • 珠海建站前端是做什么的?
  • 静态后台管理网站模板校园网站开发背景
  • 广州技术支持 骏域网站建设简阳电力建设立项网站
  • 免费网站备案号码打字赚钱平台 学生一单一结
  • 舞蹈网站模板网页版传奇世界羽翼升级
  • 赤坎网站制作广告公司管理系统软件
  • 杂志媒体网站建设方案赤城seo网站优化排名
  • 广州市专注网站建设公司玉溪市建设局网站
  • 网站团队建设情况合作建站方案
  • 景德镇网站制作wordpress文章点赞插件
  • 谢岗做网站如何做网站推广自己产品
  • 合肥网站 技术支持 上诚科技太谷网站建设
  • 网站主题栏目分类广东网站优化公司
  • django可以做多大的网站生产公司简介模板