概述:
B/S 架构的全称为 Browser/Server,即浏览器/服务器结构。 Browser 指的是 Web 浏览器,极少数业务逻辑在前端实现,主要的业务逻辑在服务器端现,
Browser 客户端,WebApp 服务器端和 DB 端构成所谓的三层架构。 B/S 架构的系统无须特别安装,只有 Web 浏览器即可。B/S 架构中,显示逻辑交给了
Web浏览器,业务处理逻辑放在了 WebApp 上,这样就避免了庞大的胖客户端,减少了客户端的压力。因为客户端包含的逻辑很少,因此也被成为瘦客户端。
优点:
( 1) 客户端无需安装,有 Web浏览器即可。
( 2) BS架构可以直接放在广域网上,通过一定的权限控制实现多客户访
问的目的,交互性较强。
( 3) BS架构无需升级多个客户端,升级服务器即可。
缺点:
( 1) 在跨浏览器上, BS架构不尽如人意。
( 2) 表现要达到 CS架构的程度需要花费不少精力。
( 3) 在速度和安全性上需要花费巨大的设计成本,这是 BS架构的最大问题。
B/S架构图:
B/S 架构的系统参与者:第一: Web 客户端 Browser
第二: Web 服务器 Server
第三: WebApp
第四:数据库服务器
B/S 架构的系统中参与者之间的接口与协议:
第一: Web 客户端 Browser 和 Web 服务器端 Server 之间是 W3C 制定的 HTTP 协议。
第二: Web 服务器和 Web 应用之间是 SUN 制定的 Servlet 接口。
第三: Web 应用中的小 java 程序和数据库服务器之间是 SUN 制定的 JDBC 接口。
B/S架构:多线程访问服务器
BootStrap:
package com.bjpowernode.core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import com.bjpowernode.util.Logger;
/**
* 程序主入口
* @author
* @version 1.0
* @since 1.0
*/
public class BootStrap {
public static void main(String[] args) {
//程序入口
start();
}
private static void start() {
/**
* 程序启动入口
*/
Logger.log("httpserver start");
ServerSocket serverSocket = null;
Socket clientSocket = null;
BufferedReader br = null;
try {
//记录开启时间
long start = System.currentTimeMillis();
//从server.xml配置文件中获取端口号:8080
int port = ServerParser.getPort();
Logger.log("httpserver-port:" + port);
//创建服务端套接字,并且绑定端口号:8080
serverSocket = new ServerSocket(port);
//记录结束时间
long end = System.currentTimeMillis();
Logger.log("httpserver started:" + (end - start) + "ms");
while(true){
//开始监听网络,此时程序处于等待状态,等待接收
clientSocket = serverSocket.accept();
new Thread(new HandlerRequest(clientSocket)).start();
}
//接受客户端消息
/*br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//打印消息
String temp = null;
while((temp = br.readLine()) != null){
System.out.println(temp);
}*/
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally{
//关闭资源
if(br != null){
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(clientSocket != null){
try {
clientSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(serverSocket != null){
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
DateUtil:
package com.bjpowernode.util;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 日期处理类
* @author
* @version 1.0
* @since 1.0
*
*/
public class DateUtil {
private DateUtil(){
}
/**
* 获取系统当前时间
* @return Strinng [yyyy-MM-dd HH:mm:ss SSS]
*/
public static String getNowTime(){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
Date nowTime = new Date();
return dateFormat.format(nowTime);
}
}
Logger:
package com.bjpowernode.util;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 记录日志
* @author
* @version 1.0
* @since 1.0
*/
public class Logger {
//工具类的方法往往都是静态的,直接通过类名调用即可,不需要创建对象
//工具类的构造方法往往是私有的,但不是必须的
private Logger(){
}
/**
* 记录普通日志
* @param info
*/
public static void log(String info){
/*SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//获取系统当前时间
Date nowTime = new Date();
String strTime = dateFormat.format(nowTime);*/
System.out.println("[INFO]" + DateUtil.getNowTime() + "" + info);
}
}
LoggerTest:
package com.bjpowernode.util;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 记录日志
* @author
* @version 1.0
* @since 1.0
*/
public class Logger {
//工具类的方法往往都是静态的,直接通过类名调用即可,不需要创建对象
//工具类的构造方法往往是私有的,但不是必须的
private Logger(){
}
/**
* 记录普通日志
* @param info
*/
public static void log(String info){
/*SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//获取系统当前时间
Date nowTime = new Date();
String strTime = dateFormat.format(nowTime);*/
System.out.println("[INFO]" + DateUtil.getNowTime() + "" + info);
}
}
package com.bjpowernode.core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import com.bjpowernode.util.Logger;
public class HandlerRequest implements Runnable {
private Socket clientSocket;
public HandlerRequest(Socket clientSocket) {
this.clientSocket = clientSocket;
}
@Override
public void run() {
// 负责处理客户端发送的请求
BufferedReader br = null;
Logger.log("httpserver 线程Thread-Name:" + Thread.currentThread().getName());
try {
// 接受消息
br = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
// 打印消息
String temp = null;
while ((temp = br.readLine()) != null) {
System.out.println(temp);
}
} catch (Exception e) {
e.printStackTrace();
} finally{
//关闭资源
if(br != null){
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(clientSocket != null){
try {
clientSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
package com.bjpowernode.core;
import java.io.File;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
/**
* 解析server.xml配置文件
* @author
* @version 1.0
* @since 1.0
*/
public class ServerParser {
public static int getPort(){
//默认值
int port = 8080;
try{
//创建解析器
SAXReader saxReader = new SAXReader();
//通过解析器的read方法将配置的文件读取到内存中去
Document document = saxReader.read(new File("conf/server.xml"));
//获取connector节点元素对象的xpath路径:/server/service/connector
//获取connector节点元素对象的xpath路径:server//connector
//获取connector节点元素对象的xpath路径://connector
Element connectorElt = (Element) document.selectSingleNode("//connector");
//获取port属性对象的值
port = Integer.parseInt(connectorElt.attributeValue("port"));
} catch(Exception e){
e.printStackTrace();
}
return port;
}
}
server.xml:
所建工程:
运行结果: