App server, Web server: What's the difference?

Q:What is the difference between an application server and a Web server?

A:Taking a big step back, a Web server serves pages for viewing in a Web browser, while an application server provides methods that client applications can call. A little more precisely, you can say that:

A Web server exclusively handles HTTP requests, whereas an application server serves business logic to application programs through any number of protocols.


Let's examine each in more detail.

The Web server

A Web server handles the HTTP protocol. When the Web server receives an HTTP request, it responds with an HTTP response, such as sending back an HTML page. To process a request, a Web server may respond with a static HTML page or image, send a redirect, or delegate the dynamic response generation to some other program such as CGI scripts, JSPs (JavaServer Pages), servlets, ASPs (Active Server Pages), server-side JavaScripts, or some other server-side technology. Whatever their purpose, such server-side programs generate a response, most often in HTML, for viewing in a Web browser.

Understand that a Web server's delegation model is fairly simple. When a request comes into the Web server, the Web server simply passes the request to the program best able to handle it. The Web server doesn't provide any functionality beyond simply providing an environment in which the server-side program can execute and pass back the generated responses. The server-side program usually provides for itself such functions as transaction processing, database connectivity, and messaging.

While a Web server may not itself support transactions or database connection pooling, it may employ various strategies for fault tolerance and scalability such as load balancing, caching, and clustering—features oftentimes erroneously assigned as features reserved only for application servers.

The application server

As for the application server, according to our definition, an application server exposes business logic to client applications through various protocols, possibly including HTTP. While a Web server mainly deals with sending HTML for display in a Web browser, an application server provides access to business logic for use by client application programs. The application program can use this logic just as it would call a method on an object (or a function in the procedural world).

Such application server clients can include GUIs (graphical user interface) running on a PC, a Web server, or even other application servers. The information traveling back and forth between an application server and its client is not restricted to simple display markup. Instead, the information is program logic. Since the logic takes the form of data and method calls and not static HTML, the client can employ the exposed business logic however it wants.

In most cases, the server exposes this business logic through a component API, such as the EJB (Enterprise JavaBean) component model found on J2EE (Java 2 Platform, Enterprise Edition) application servers. Moreover, the application server manages its own resources. Such gate-keeping duties include security, transaction processing, resource pooling, and messaging. Like a Web server, an application server may also employ various scalability and fault-tolerance techniques.

An example

As an example, consider an online store that provides real-time pricing and availability information. Most likely, the site will provide a form with which you can choose a product. When you submit your query, the site performs a lookup and returns the results embedded within an HTML page. The site may implement this functionality in numerous ways. I'll show you one scenario that doesn't use an application server and another that does. Seeing how these scenarios differ will help you to see the application server's function.

Scenario 1: Web server without an application server

In the first scenario, a Web server alone provides the online store's functionality. The Web server takes your request, then passes it to a server-side program able to handle the request. The server-side program looks up the pricing information from a database or a flat file. Once retrieved, the server-side program uses the information to formulate the HTML response, then the Web server sends it back to your Web browser.

To summarize, a Web server simply processes HTTP requests by responding with HTML pages.

Scenario 2: Web server with an application server

Scenario 2 resembles Scenario 1 in that the Web server still delegates the response generation to a script. However, you can now put the business logic for the pricing lookup onto an application server. With that change, instead of the script knowing how to look up the data and formulate a response, the script can simply call the application server's lookup service. The script can then use the service's result when the script generates its HTML response.

In this scenario, the application server serves the business logic for looking up a product's pricing information. That functionality doesn't say anything about display or how the client must use the information. Instead, the client and application server send data back and forth. When a client calls the application server's lookup service, the service simply looks up the information and returns it to the client.

By separating the pricing logic from the HTML response-generating code, the pricing logic becomes far more reusable between applications. A second client, such as a cash register, could also call the same service as a clerk checks out a customer. In contrast, in Scenario 1 the pricing lookup service is not reusable because the information is embedded within the HTML page. To summarize, in Scenario 2's model, the Web server handles HTTP requests by replying with an HTML page while the application server serves application logic by processing pricing and availability requests.

Caveats

Recently, XML Web services have blurred the line between application servers and Web servers. By passing an XML payload to a Web server, the Web server can now process the data and respond much as application servers have in the past.

Additionally, most application servers also contain a Web server, meaning you can consider a Web server a subset of an application server. While application servers contain Web server functionality, developers rarely deploy application servers in that capacity. Instead, when needed, they often deploy standalone Web servers in tandem with application servers. Such a separation of functionality aids performance (simple Web requests won't impact application server performance), deployment configuration (dedicated Web servers, clustering, and so on), and allows for best-of-breed product selection.



应用服务器有哪些:

BEA  WebLogic  Server,IBM  WebSphere  Application  Server,Oracle9i  Application  Server,jBoss,Tomcat

# 工具模块 import json import logging import os from functools import lru_cache import win32process from win32com.client import Dispatch, DispatchEx, GetActiveObject, constants from .task_handler import * logger = logging.getLogger("root") # stream_handler = logging.StreamHandler(stream=sys.stdout) # stream_handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(filename)s-%(lineno)s %(message)s")) # kotei_web_server的父级目录, 对应生产目录_internal的平级, 也就是diff_agent的下级目录 base_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) # 相当于diff_agent/web-server.log log_file = os.path.join(base_path, "web-server.log") file_handler = logging.FileHandler(filename=log_file, mode="a") file_handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(filename)s-%(lineno)s %(message)s")) # logger.addHandler(stream_handler) logger.addHandler(file_handler) logger.setLevel(logging.INFO) # logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(filename)s-%(lineno)s %(message)s", # filemode="a", filename="web-server.log") def load_json(filename: str) -> dict: try: with open(filename, "r", encoding="utf-8") as f: data = json.loads(f.read()) except FileNotFoundError: data = None return data def get_word_instance(): # 创建 Word 应用程序单例对象 try: pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED) word_app = GetActiveObject("Word.Application") except pythoncom.com_error: bat_path = os.path.join(BASE_DIR, "scripts", "clear_wps.bat") os.system("call %s" % bat_path) time.sleep(1) pythoncom.CoInitialize() word_app = Dispatch("Word.Application") # Word.Application word_app.Visible = True word_app.DisplayAlerts = True return word_app def get_excel_instance(): # 创建 Word 应用程序单例对象 try: pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED) excel = GetActiveObject("Excel.Application") except pythoncom.com_error: bat_path = os.path.join(BASE_DIR, "scripts", "clear_wps.bat") os.system("call %s" % bat_path) time.sleep(1) pythoncom.CoInitialize() excel = Dispatch("Excel.Application") excel.Visible = True excel.DisplayAlerts = True return excel def parse_word_office_ui_layout(word_app, left: int, top: int, width_ratio: float, height_ratio: float): """ office 应用UI窗口布局 :params: word_app, com组件对象 :params: left, UI窗口左上角的x坐标 :params: top, UI窗口左上角的y坐标 :params: width_ratio, UI窗口宽度占屏幕宽度的比率 :params: height_ratio, UI窗口高度占屏幕高度的比率 """ logging.info("start to adjust word office ui position.") # 获取 Word 应用程序的窗口句柄 hwnd = win32gui.FindWindow("OpusApp", None) logging.info("gkb1") if hwnd: # 设置窗口的显示比例(缩放) # 将窗口缩放到屏幕的 50% 大小 screen_width = win32api.GetSystemMetrics(0) logging.info("gkb2") screen_height = win32api.GetSystemMetrics(1) # word UI窗口的宽、高 scale_width = int(screen_width * width_ratio) scale_height = int(screen_height * height_ratio) logging.info("gkb3") # 重新设置UI窗口的位置、大小 win32gui.ShowWindow(hwnd, win32con.SW_RESTORE) logging.info("gkb4") win32gui.SetWindowPos(hwnd, win32con.HWND_TOP, left, top, scale_width, scale_height, win32con.SWP_SHOWWINDOW) # 调整文档视图的缩放比例 logging.info("gkb5") word_app.ActiveWindow.View.Zoom.Percentage = 120 # 设置缩放比例为 120% # 设置为前台窗口 # 获取当前线程和窗口线程 current_thread_id = win32api.GetCurrentThreadId() logging.info("gkb6") window_thread_id, _ = win32process.GetWindowThreadProcessId(hwnd) logging.info("gkb7") # 允许当前进程激活窗口 # import ctypes # user = ctypes.windll.user32 # user.AllowSetForegroundWindow(win32process.GetCurrentProcessId()) # # 激活窗口 # win32gui.SetForegroundWindow(hwnd) def parse_excel_office_ui_layout(excel_app, left: int, top: int, width_ratio: float, height_ratio: float): """ office 应用UI窗口布局 :params: excel_app, com组件对象 :params: left, UI窗口左上角的x坐标 :params: top, UI窗口左上角的y坐标 :params: width_ratio, UI窗口宽度占屏幕宽度的比率 :params: height_ratio, UI窗口高度占屏幕高度的比率 """ logging.info("start to adjust excel office ui position.") # 获取 Excel 应用程序的窗口句柄 hwnd = win32gui.FindWindow("XLMAIN", None) if hwnd: # 设置窗口的显示比例(缩放) # 将窗口缩放到屏幕的 50% 大小 screen_width = win32api.GetSystemMetrics(0) screen_height = win32api.GetSystemMetrics(1) # excel UI窗口的宽、高 scale_width = int(screen_width * width_ratio) scale_height = int(screen_height * height_ratio) # 重新设置UI窗口的位置、大小 win32gui.SetWindowPos(hwnd, win32con.HWND_TOP, left, top, scale_width, scale_height, win32con.SWP_SHOWWINDOW) # # win32gui.SetForegroundWindow(hwnd) def init_com(data: dict): """ 初始化COM组件,打开文档,并调整文档窗口布局 """ # 任务函数 logging.info("start to init com component for parsed data.") fext = data.get("fext") filename = data.get("filename") # # 分别处理word、excel的打开 if fext in [".doc", ".docx", ".docm"]: global WORD_OFFICE_TYPE word = get_word_instance() # 判断当前文档是否已经打开 if word.Documents.Count: for idx in range(word.Documents.Count): doc = word.Documents.Item(get_document_index(word, idx)) if doc.FullName == filename: logging.info("当前目标word文档已激活.") doc.Activate() break else: word.Documents.Open(filename) logging.info("当前目标word文档已打开.") else: word.Documents.Open(filename) logging.info("当前目标word文档已打开.") # 调整word应用窗口的布局 parse_word_office_ui_layout(word, 0, 0, 0.5, 0.963) elif fext in [".xls", ".xlsx", ".xlsm"]: excel = get_excel_instance() if excel.Workbooks.Count: for idx in range(excel.Workbooks.Count): cur_wb = excel.Workbooks.Item(get_document_index(excel, idx)) # if cur_wb.FullName == filename: base_cur, _ = os.path.splitext(cur_wb.FullName) base_target, _ = os.path.splitext(filename) if os.path.normcase(base_cur) == os.path.normcase(base_target): logging.info("当前目标excel文档已激活.") cur_wb.Activate() break else: excel.Workbooks.Open(filename) logging.info("当前目标excel文档已打开.") else: excel.Workbooks.Open(filename) logging.info("当前目标excel文档已打开.") # 调整excel应用的窗口布局 parse_excel_office_ui_layout(excel, 0, 0, 0.5, 0.963) return def find_window(title: str): """ 根据窗口标题查找窗口句柄。 如Aily-Chat""" # 默认无效句柄 hwnd = 0 # 回调函数 def callback(inner_hwnd, extra): nonlocal hwnd window_title = win32gui.GetWindowText(inner_hwnd) if win32gui.IsWindowVisible(inner_hwnd) and title == window_title: hwnd = inner_hwnd # 枚举所有窗口 win32gui.EnumWindows(callback, None) return hwnd def adjust_fronend_ui(title: str): """ 根据窗口标题,调整前端UI的布局。""" hwnd = find_window(title) if hwnd == 0: logging.info("find front UI window with win_title failed.") return # 获取屏幕的宽高 screen_width = win32api.GetSystemMetrics(0) screen_height = win32api.GetSystemMetrics(1) # 解析时,占屏幕右半边 if "解析结果" in title or "Parsing Result" in title or "解析結果" in title: logging.info("start to adjust parsed front UI.") # 恢复窗口 win32gui.ShowWindow(hwnd, win32con.SW_RESTORE) # 设置窗口位置 win32gui.SetWindowPos(hwnd, win32con.HWND_TOP, screen_width // 2 - 8, 0, screen_width // 2, int(screen_height * 0.963), win32con.SWP_SHOWWINDOW ) logging.info("adjust parsed front UI succeed.") # 差分时,占屏幕下半边 elif title.startswith("差分结果") or title.startswith("Difference Result") or title.startswith("差分結果"): logging.info("start to adjust diff front UI.") # 恢复窗口 win32gui.ShowWindow(hwnd, win32con.SW_RESTORE) # 设置窗口位置 win32gui.SetWindowPos(hwnd, win32con.HWND_TOP, 0, screen_height // 2 - 8, screen_width, screen_height // 2 - 30, win32con.SWP_SHOWWINDOW ) logging.info("adjust diff front UI succeed.") elif "Aily-Chat" in title: logging.info("start to adjust Aily-Chat UI.") # 恢复窗口 win32gui.ShowWindow(hwnd, win32con.SW_RESTORE) # 设置窗口位置 win32gui.SetWindowPos(hwnd, win32con.HWND_TOP, screen_width // 2, 0, screen_width // 2, int(screen_height * 0.963), win32con.SWP_SHOWWINDOW ) logging.info("adjust Aily-Chat UI succeed.") def is_doc_opened(word, file): """ 当前word文档是否已打开 """ if word.Documents.Count: for idx in range(word.Documents.Count): cur_doc = word.Documents.Item(get_document_index(word, idx)) # if cur_doc.FullName == file: base_cur, _ = os.path.splitext(cur_doc.FullName) base_target, _ = os.path.splitext(file) if os.path.normcase(base_cur) == os.path.normcase(base_target): return True return False def is_wb_opened(excel, file): """ 当前的工作簿文件是否已打开 """ if excel.Workbooks.Count: for idx in range(excel.Workbooks.Count): cur_wb = excel.Workbooks.Item(get_document_index(excel, idx)) # if cur_wb.FullName == file: base_cur, _ = os.path.splitext(cur_wb.FullName) base_target, _ = os.path.splitext(file) if os.path.normcase(base_cur) == os.path.normcase(base_target): return True return False def is_office_running(stream): """ 判断当前excel或者word应用是否在运行 """ try: # 从数据流中取出app app = pythoncom.CoGetInterfaceAndReleaseStream(stream, pythoncom.IID_IDispatch) logging.info("从数据流中解析出office实例.") app = Dispatch(app) # 访问一个属性 _ = app.Visible return True except pythoncom.com_error as e: import traceback logging.error(e.args[0]) print(traceback.format_exc()) return False def close_office_document(path: str): """ 根据绝对路径文件名称关闭文档 """ _, ext = os.path.splitext(path) if ext in [".doc", ".docx", ".docm"]: logging.info(f"start to close {path} word document.") try: pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED) logging.info("m1") word_app = GetActiveObject("Word.Application") logging.info("m2") logging.info(f"start to close {hasattr(word_app, 'Documents')} word document.") # 防御性检查 if not getattr(word_app, 'Documents', None) or word_app.Documents.Count == 0: logging.info("gm1") word_app.Quit() logging.info("gm2") pythoncom.CoUninitialize() logging.info("gm3") bat_path = os.path.join(BASE_DIR, "scripts", "clear_wps.bat") logging.info("gm4") logging.info(f"kill_office {bat_path}") # os.system("call %s" % bat_path) os.system(f'"{bat_path}"') return # 遍历所有的打开的文档,找到目标文档,并关闭 if word_app.Documents.Count: logging.info("m3") for idx in range(word_app.Documents.Count): logging.info("m4") cur_doc = word_app.Documents.Item(get_document_index(word_app, idx)) logging.info("m5") base_cur, _ = os.path.splitext(cur_doc.FullName) base_target, _ = os.path.splitext(path) logging.info(f"gg {base_cur} excel workbook.") logging.info(f"mm {base_target} excel workbook.") logging.info(f"shiver {os.path.normcase(base_cur) == os.path.normcase(base_target)} excel workbook.") if os.path.normcase(base_cur) == os.path.normcase(base_target): cur_doc.Close(False) # word_app.Quit() logging.info(f"close {path} word document succeed.") if word_app.Documents.Count == 0: logging.info("m6") word_app.Quit() pythoncom.CoUninitialize() # if word_app: # word_app.Quit() # pythoncom.CoUninitialize() bat_path = os.path.join(BASE_DIR, "scripts", "clear_wps.bat") os.system("call %s" % bat_path) # except pythoncom.com_error: # bat_path = os.path.join(BASE_DIR, "scripts", "clear_wps.bat") # os.system("call %s" % bat_path) # 捕获所有异常并打印 except Exception as e: logging.error(f"Error occurred while closing Word document: {e}", exc_info=True) # exc_info=True 会打印完整的堆栈信息 bat_path = os.path.join(BASE_DIR, "scripts", "clear_wps.bat") os.system("call %s" % bat_path) elif ext in [".xls", ".xlsx", ".xlsm"]: logging.info(f"start to close {path} excel workbook.") try: pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED) excel_app = GetActiveObject("Excel.Application") if excel_app.Workbooks.Count: for idx in range(excel_app.Workbooks.Count): cur_book = excel_app.Workbooks.Item(get_document_index(excel_app, idx)) base_cur, _ = os.path.splitext(cur_book.FullName) base_target, _ = os.path.splitext(path) if os.path.normcase(base_cur) == os.path.normcase(base_target): cur_book.Close(False) # excel_app.Quit() logging.info(f"close {path} excel workbook succeed.") if excel_app.Workbooks.Count == 0: excel_app.Quit() pythoncom.CoUninitialize() bat_path = os.path.join(BASE_DIR, "scripts", "clear_wps.bat") os.system("call %s" % bat_path) except pythoncom.com_error: bat_path = os.path.join(BASE_DIR, "scripts", "clear_wps.bat") os.system("call %s" % bat_path) else: raise ValueError("不是有效的文件.") if __name__ == '__main__': # file_path = r"C:\Users\ningw9354\Desktop\flask_backend\static\parsed_data\demo.json" # load_json(file_path) path = r"E:\3 三期脱敏数据\line19\before\line19变更前.docx" word = get_word_instance() doc = word.Documents.Open(path) cursor = word.Selection # 3331 3339 for para in doc.Paragraphs: # print("text:", [para.Range.Text]) if "3.2. 常数变更" in para.Range.Text: start = para.Range.Start # cursor.Start = start cursor.GoTo(Which=1, What=1, Count=8) end = para.Range.End left = para.Range.Information(5) top = para.Range.Information(6) width = para.Range.Information(7) print("start:", left, top, width, (end - start) * 5) shape = doc.Shapes.AddShape(1, left, top, width + 100, (end - start) * 6) shape.Line.Weight = 1 shape.Line.ForeColor.RGB = 255 shape.Fill.Visible = 0 para.Range.ScrollIntoView(True) # print("para:", para.Range.Information(13)) # print("para:", para.Range.Information(14)) 这个文件里有吗
09-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值