概述:
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:
<?xml version="1.0" encoding="UTF-8"?> <server> <service> <connector port="8080"></connector> </service> </server>
所建工程:

運行結果:
