实现简单BS架构案例


BS架构简单通俗理解 就是 浏览器–服务器模式,浏览器 充当 我们的客户端。

目录

  • 简单BS架构实现案例
    • 基本原理视图
    • 访问规则
    • 案例要求
    • 改造前
      • 服务端
      • 线程模版类
    • 改造后(优化)
      • 优化策略
      • 服务端
      • 线程模版类
    • 参考视频

简单BS架构实现案例

基本原理视图

  
在这里插入图片描述
  

注:服务器必须给浏览器 响应 HTTP协议 规定的数据格式,否则浏览器不识别 返回的数据

访问规则

服务端若要提供访问服务,就必须遵循浏览器的约定规则,也就是协议

  
在这里插入图片描述
  


案例要求

从浏览器中访问服务器

并立即让服务器响应一个很简单的网页给浏览器

展示网页内容 就是 “12 ITxie_我的IT之路”


改造前

服务端

package com.xie.net.complete.tcp.group.bs;import java.net.ServerSocket;
import java.net.Socket;/*** 目标:完成TCP通信快速入门-服务端开发:要求实现与多个客户端同时进行通信* */
public class Server {public static void main(String[] args) throws Exception {System.out.println("----------服务端启动成功----------");// 创建ServerSocket对象,同时为服务端注册端口号,为后续客户端的请求提供访问位置ServerSocket serverSocket = new ServerSocket(8080);while(true) {// 使用ServerSocket对象,调用accent方法,阻塞等待客户端的连接Socket socket = serverSocket.accept();System.out.println("有人上线了:" + socket.getRemoteSocketAddress());// 新建线程,把此客户端(这里指浏览器)的 通信管道socket,交给 一个独立的线程 负责处理业务new ServerReaderThread(socket).start();}}
}

线程模版类

package com.xie.net.complete.tcp.group.bs;import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
public class ServerReaderThread extends Thread {private Socket socket;public ServerReaderThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {/*** 立即响应一个网页内容:”12 ITxie_我的IT之路“给浏览器渲染(包括html标签的渲染),然后展示给用户观看* */try (OutputStream os = socket.getOutputStream();PrintStream ps = new PrintStream(os)){ps.println("HTTP/1.1 200 OK");ps.println("Content-Type: text/html;charset=UTF-8");// 换行ps.println();ps.println("<div style='color:red;font-size:120px;text-align:center'>12 ITxie_我的IT之路</div>");socket.close();} catch (IOException e) {e.printStackTrace();}}
}

改造后(优化)

优化策略

  
在这里插入图片描述
  

服务端

package com.xie.net.complete.tcp.group.bs.modify;import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** 目标:完成TCP通信快速入门-服务端开发:要求实现与多个客户端同时进行通信。** 优化前面代码,使用线程池解决,其中涉及到了资源合理回收利用问题* 解决高并发问题:* 改造用线程池来提供服务,缓解短时间内大量访问请求可能导致性能瓶颈,然后系统宕机的问题* (引起原因:系统性能跟不上,忙不过来,每产生一个新线程都是会消耗系统资源的,而资源总归有限)* */
public class Server {public static void main(String[] args) throws Exception {System.out.println("----------服务端启动成功----------");// 创建ServerSocket对象,同时为服务端注册端口号,为客户端后续的请求提供访问位置ServerSocket serverSocket = new ServerSocket(8080);/*** 创建线程池,其各参数具体含义:* 参数一:核心线程数量* 参数二:最大线程数量* 参数三:临时线程存活时间* 参数四:参数三的时间单位* 参数五:任务队列,此处用于 缓存 来自通信管道的任务的* 参数六:线程工厂,用于创建核心线程的* 参数七:任务的拒绝策略,此处用到默认策略,直接拒绝的处理方案,当处理不了时,直接抛异常* */// 创建出一个线程池,负责处理通信管道的任务ThreadPoolExecutor pool = new ThreadPoolExecutor(16 * 2, 16 * 2, 0,TimeUnit.SECONDS, new ArrayBlockingQueue<>(8),Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());while(true) {// 使用ServerSocket对象,调用accent方法,阻塞等待客户端的连接Socket socket = serverSocket.accept();System.out.println("有人上线了:" + socket.getRemoteSocketAddress());/*** 把通信管道 交给 任务对象 然后 传递给 线程池对象处理。* 其实,此客户端的 通信管道socket最终也是交给 一个独立的线程 负责处理业务。* 只不过 此线程 处理完任务后 立即被回收 以待复用。*/pool.execute(new ServerReaderRunable(socket));}}
}

线程模版类

package com.xie.net.complete.tcp.group.bs.modify;import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;/*** 包装Socket通信管道的 任务对象模版类,其中 定义 需要处理的任务* */
public class ServerReaderRunable implements Runnable {private Socket socket;public ServerReaderRunable(Socket socket) {this.socket = socket;}@Overridepublic void run() {/*** 立即响应一个网页内容:”12 ITxie_我的IT之路“给浏览器渲染(包括html标签的渲染),然后展示给用户观看* */try (OutputStream os = socket.getOutputStream();PrintStream ps = new PrintStream(os)){ps.println("HTTP/1.1 200 OK");ps.println("Content-Type: text/html;charset=UTF-8");ps.println();ps.println("<div style='color:red;font-size:120px;text-align:center'>12 ITxie_我的IT之路</div>");socket.close();} catch (Exception e) {e.printStackTrace();}}
}

参考视频

黑马磊哥

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/93063.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【红外与可见光图像融合】离散平稳小波变换域中基于离散余弦变换和局部空间频率的红外与视觉图像融合方法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

selenium下载安装 -- 使用谷歌驱动碰到的问题

安装教程参考: http://c.biancheng.net/python_spider/selenium.html 1. 谷歌浏览器和谷歌驱动版本要对应(但是最新版本谷歌对应的驱动是没有的,因此要下载谷歌历史其他版本): 谷歌浏览器历史版本下载: https://www.chromedownloads.net/chrome64win/谷歌浏览器驱动下载: http:…

基于web的医院预约挂号系统/医院管理系统

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&a…

【GESP考级C++】1级样题 闰年统计

GSEP 1级样题 闰年统计 题目描述 小明刚刚学习了如何判断平年和闰年&#xff0c;他想知道两个年份之间&#xff08;包含起始年份和终止年份&#xff09;有几个闰年。你能帮帮他吗&#xff1f; 输入格式 输入一行&#xff0c;包含两个整数&#xff0c;分别表示起始年份和终止…

87、Redis 的 value 所支持的数据类型(String、List、Set、Zset、Hash)---->List相关命令

本次讲解要点&#xff1a; List相关命令&#xff1a;是指value中的数据类型 启动redis服务器&#xff1a; 打开小黑窗&#xff1a; C:\Users\JH>e: E:>cd E:\install\Redis6.0\Redis-x64-6.0.14\bin E:\install\Redis6.0\Redis-x64-6.0.14\bin>redis-server.exe redi…

MySQL约束

文章目录 简单介绍主键约束添加单列主键多列主键删除主键 自增长约束(auto_increment)语法&#xff1a;指定自增字段初始值 非空约束唯一约束(unique)默认约束(default)零填充约束(zerofill) 简单介绍 概念&#xff1a;表中数据的约束条件 作用&#xff1a;表在设计的时候加入…

[学习笔记]ARXML - Data Format

参考AUTOSAR文档&#xff1a; https://www.autosar.org/fileadmin/standards/R22-11/FO/AUTOSAR_TPS_ARXMLSerializationRules.pdfhttps://www.autosar.org/fileadmin/standards/R22-11/FO/AUTOSAR_TPS_ARXMLSerializationRules.pdf 编码 arxml只允许使用UTF-8编码&#xff…

【Java 进阶篇】JDBC ResultSet 遍历结果集详解

在Java数据库编程中&#xff0c;经常需要执行SQL查询并处理查询结果。ResultSet&#xff08;结果集&#xff09;是Java JDBC中用于表示查询结果的关键类之一。通过遍历ResultSet&#xff0c;我们可以访问和操作从数据库中检索的数据。本文将详细介绍如何使用JDBC来遍历ResultSe…

ubuntu 18.04 LTS安装opencv 3.4.16 + opencv_contrib 3.4.16

1.下载 opencv 3.4.16 opencv_contrib 3.4.16 其中&#xff0c;opencv_contrib解压后的多个文件夹复制到opencv内、合并 2.安装 参考博文&#xff1a; https://zhuanlan.zhihu.com/p/650792342 https://zhuanlan.zhihu.com/p/87197806 其中 &#xff08;1&#xff09;cmake前…

2023年中国金刚石工具产量、需求量、市场规模及行业细分产品规模[图]

金刚石工具就是以金刚石为增强体&#xff0c;以金属或聚合物为基体的一类功能复合材料。金刚石工具已经成为当今公认的、唯一有效的硬脆非金属材料加工工具&#xff0c;比如&#xff0c;只有用金刚石刀具能加工超硬的陶瓷&#xff0c;尚无其他代用品。金刚石工具根据其用途的不…

【VIM】初步认识VIM-2

2-6 Vim 如何搜索替换_哔哩哔哩_bilibili 1-6行将self改成this 精确替换quack单词为交

湖南特色农产品销售系统APP /基于android的农产品销售系统/基于android的购物系统

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的APP应运而生&#xff0c;各行各业相继进入信息管理时代&#x…

【QT】自定义组件ui类添加到主ui界面方法

1.添加自定义组件到项目中 add new选择如下 写好类方法&#xff0c;确定即可 2.将新创建的ui类加入到主ui界面 选中新创建ui类的父类空块&#xff0c;右键选择提升为 选择并添加新创建的类

如何搭建团队知识库?试试新的工具和方法吧!

知识本身没有价值&#xff0c;只有被利用的知识才能发挥作用。我们经常见到有许多“宏伟”的团队知识库&#xff0c;但是从来没有人去用…… 搭建团队知识库 没有人用的团队知识库存在的问题是“我们知道所有问题的答案&#xff0c;就是不知道问题是什么”。如何建立团队知识库…

NLP中token总结

Token 可以被理解为文本中的最小单位。在英文中&#xff0c;一个 token 可以是一个单词&#xff0c;也可以是一个标点符号。在中文中&#xff0c;通常以字或词作为 token。ChatGPT 将输入文本拆分成一个个 token&#xff0c;使模型能够对其进行处理和理解 在自然语言处理&#…

vertx的学习总结2

一、什么是verticle verticle是vertx的基本单元&#xff0c;其作用就是封装用于处理事件的技术功能单元 &#xff08;如果不能理解&#xff0c;到后面的实战就可以理解了&#xff09; 二、写一个verticle 1. 引入依赖&#xff08;这里用的是gradle&#xff0c;不会吧&#…

18scala笔记

Scala2.12 视频地址 1 入门 1.1 发展历史 … 1.2 Scala 和 Java Scala Java 编写代码使用scalac编译成.class字节码文件scala .class文件 执行代码 1.3 特点 1.4 安装 视频地址 注意配置好环境变量 简单代码 1.5 编译文件 编译scala文件会产生两个.class文件 使用java…

【初始Linux】上

初始Linux上 一、Linux背景1.1 UNIX发展的历史1.2 UNIX发展的历史 二、开源三、官网Linux官网 四、企业应用现状五、发行版本六、 os概念&#xff0c;定位 本博客简介 初始Linux操作系统初识shell命令 ,了解若干背景知识。使用常用Linux命令了解Linux权限概念与思想,能深度理解…

Java | Maven(知识点查询)

文章目录 Maven知识速查1. Maven概述2. Maven的作用3. Maven的下载4. Maven的环境配置5. Maven 的基础组成5.1 Maven仓库5.1.1 本地仓库配置&#xff1a;5.1.2 中央仓库配置&#xff1a;5.1.3 镜像仓库配置 5.2 Maven坐标 6. Maven项目6.1 手工创建Maven项目6.2 自动构建项目 7…

安卓 kuaishou 设备did和egid 学习分析

did和egid注册 接口 https://gdfp.ksapisrv.com/rest/infra/gdfp/report/kuaishou/android did 是本地生成的16进制 或者 获取的 android_id public static final Random f16237a new Random(System.currentTimeMillis()); public static long m19668a() { return f1623…