实现简单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;表在设计的时候加入…

【kubernetes】kubernetes中的调度

1 调度过程 调度的本来含义是指决定某个任务交给某人来做的过程&#xff0c;kubernetes中的调度是指决定Pod在哪个Node上运行。 k8s的调度分为2个过程&#xff1a; 预选&#xff1a;去掉不满足条件的节点优选&#xff1a;对剩下符合条件的节点按照一些策略进行排序&#xff…

[学习笔记]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…

【Oracle】Oracle系列之十五--存储过程

文章目录 往期回顾前言1. 基本概念&#xff08;1&#xff09;定义&#xff08;2&#xff09;存储过程与函数的区别&#xff08;3&#xff09;存储过程与触发器的区别 2. 创建和使用存储过程&#xff08;1&#xff09;创建存储过程&#xff08;2&#xff09;调用存储过程&#x…

【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…

uboot启动流程-uboot内存分配

一. uboot启动流程 _main 函数中会调用 board_init_f 函数&#xff0c;本文继续简单分析一下 board_init_f 函数。 具体分析 board_init_f函数的第二部分&#xff1a;内存分配代码。 本文继上一篇文章的学习&#xff0c;地址如下&#xff1a; uboot启动流程-涉及board_init…

【C语言数据结构】线性表-顺序存储-动态分配(顺序表)

线性表-顺序存储-动态分配 代码实现 代码实现 #include<stdio.h> #include<stdlib.h> #include<stdbool.h>//线性表初始分配的长度 #define InitSize 3//线性表元素的数据类型 #define ElemType inttypedef struct {//定义线性表的元素数据&#xff0c;虽然…

玩客云Armbian_23.08.0-trunk_Onecloud_bookworm_edge_6.4.14.burn配置

固定IP # interface file auto-generated by buildrootauto lo iface lo inet loopback// 上面是默认的内容,下面是新增的内容,上下之间需要一个空行隔开 // 接口顶格写,属性的前面有一个tab的缩进 # The primary network interfaceauto eth0 iface eth0 inet staticaddress 1…

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

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

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

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

业务拆分——微服务拆分独立出来的步骤

背景介绍 随着公司业务的变化&#xff0c;系统的架构需要不断的调整。当客户的需求不断细化&#xff0c;营销方案的不断调整&#xff0c;产品需要达到更细的粒度&#xff0c;以便产品可以灵活组合进行销售。故此时需要拆分一些公共的业务&#xff0c;作为独立的微服务部署&…