【数据库06】web应用程序开发的任督二脉 1

简介: 【数据库06】web应用程序开发的任督二脉

1.应用程序和用户界面

互联网用户和数据库往往不会直接打交道,而是通过应用程序对数据库进行间接访问。

在计算机发展早期,应用程序在大型主计算机上运行,用户通过终端与应用程序交互。

个人计算机的发展导致了带有图形的用户界面GUI的数据库应用的发展。程序在个人计算机上运行,这些代码直接与一个共享的数据库进行通信。这种模式被称为客户-服务器体系结构

ff422b2e49414acf8f3e998e6fdeabf0.jpg

这种模式至少有两个问题:


用户机器可以直接访问数据库,从而带来安全性问题。

维护困难。对应用程序或数据库的任何更改(扩展、更新、修改等)都要求位于客户计算机上的应用程序的所有副本一起更改(重新部署软件)。

现在有两种方法用于避免上述问题。

-browser/server。web浏览器提供前端,通过前端访问后端。这样就不需要单独在客户机安装、维护软件。同时,与c语言编写的程序不同,前端的脚本语言JavaScript可以运行在安全模式下,保证不会导致安全问题。

d0d60f9101c845ee82f86464564c69db.jpg


应用程序安装在独立设备上。这些设备主要是移动设备,它们通过API与后端应用程序进行通信,并不能直接访问数据库。

2.Web基础

2.1 同一资源定位符

统一资源定位符(Uniform Resource Locator)是web上可以访问的每份文档的全球唯一名称。比如:

http://www.acm.org/sigmod

上面的URL由三部分组成,http是超文本传输协议,“https”是“http”的安全版本,并且是当今的首选模式。第二部分是一台具有web服务器的机器名称。第三部分是该机器上文档的路径或者唯一标识。


URL还可以包含位于web服务器上程序的标识,以及传递给该程序的参数。并由该程序返回一个html文档给web服务器。

http://www.google.com/search?q=silberschatz

2.2 超文本标记语言

下图就是一个html创建一个表单的过程

25032837186440efb863b62801d35fbf.jpg

Http定义了两种请求方式,上图所示的get请求将请求参数作为URL的一部分,另外一种请求Post请求则发送一个请求,将参数值作为web服务器和浏览器之间交换的HTTP协议的一部分发送。


有些编辑器支持使用图形界面来直接创建HTML文本编辑器。


CSS支持给html提供样式。


HTML5支持多种形式的输入类型,比如日期和时间选择,文件选择,还支持对输入采取限制(最大值,最小值等)


2.3 web服务器和会话

Web服务器是运行于服务机上的程序,它接收浏览器的请求,根据其提供的参数执行程序,最后将结果以HTML文档的形式将结果传送回去。


下图显示了一个使用三层体系结构搭建的web应用程序。通用网关接口(CGI)标准定义了web服务器如何与应用程序进行通信。使用多层服务器增加了系统的开销,CGI接口为每个请求都启动一个新的进程为之服务,这导致了更大的开销。


因此目前大部分的应用程序将web服务器和应用服务器合二为一,采用两层web应用程序体系结构。

4380898c18b14fb89431ea4f31750d85.jpg


用户通过JDBC或者ODBC来访问数据库时,则会建立一个会话,会话信息会一直保存,直到该会话终止。但是客户端和web服务器之间不存在长连接,往往是连接-请求-响应-关闭连接的方式,这是为了更多的容载海量的用户访问,降低连接限制带来的影响。


尽管连接会关闭,但是web应用程序也需要会话信息来允许有意义的用户交互,对用户进行认证等。它的策略是,会对每一次会话进行一次用户认证,会话的进一步交互无需进行认证。


为了实现会话,需要在客户端存储额外的信息。这些额外的信息通常以cookie的形式维护在客户端,一个cookie是一段包含标识信息的文本,并且与一个名称相关联。例如,google.com可能设置一个名为prefs的cookie,它对用户的偏好设置进行编码,比如语言偏好和每页显示的结果数目,对于每个搜索请求,google.com都能够从用户的浏览器得到这个名为prefs的cookie,然后根据其指定的偏好来显示结果。一个域(Web站点)只允许获取它自己设置的cookie,而不能获取其他域所设置的cookie,而且cookie的名称可以跨域重用。

45aa1f86c1bc41a58f9037d65be0ba07.png

为了跟踪用户会话,服务端会生产一个名为seesionid的cookie,这是一个特殊的cookie,它用于区分不同的会话,因此也会在服务端存储。当一个请求进来时,应用服务器从客户端请求名为seesionid的cookie,如果客户端没有存储该cookie,或者返回的值与服务端存储的有效会话标识不同,就认为该请求不是当前会话的一部分。


a11d2c68f38947f0b8aa1a1e7f475d26.png

对于安全性要求不高的应用,比如公共新闻站点,cookie可以永久的存储在浏览器端和服务器段。他们识别初用户对一个站点的后续访问,而不需要输入任何验证信息。


对于安全性高的应用,则可能会设置时间限制,在超时后或者用户注销(退出登录)时使会话失效,使会话失效其实就是将会话标识从服务端删除。


3.Servlet

java servlet(Java服务端程序)规范定义了一种用于在WEB/应用服务器与应用程序之间进行通信的应用编程接口。Java的HttpServlet类实现了Servlet API的规范。


3.1 Servlet示例

我们卡妈妈提到了如下的一个表单请求。

25032837186440efb863b62801d35fbf.jpg

现在假设该请求被提交给后端,我们编写下对应的后端处理逻辑代码,看看后端要怎么应对前端的请求

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
@WebServlet("PersonQuery")
public class PersonQueryServlet extends HttpServlet {
  public void doGet(HttpServletRequest request,
           HttpServletResonse response)
      throws ServletException, IOException
      {
        response.setContentType("text/html");
        PrintWriter out = resonse.getWriter();
        ...检查用户是否已登录...
        out.println("<HEAD><TITLE>Query Result</TITLE></HEAD>");
        out.println("<BODY>");
        String persontype = request.getParameter("persontype");
        String name = request.getParameter("name");
        if(persontype.equals("student")) {
          ...寻找具有指定姓名的学生的代码...
          ...使用JDBC与数据库进行通信...
          ...假设已获取到ResultSet rs,并且...
          ...包含属性:ID、姓名与系名...
          String headers = new String[]{"ID","Name","Department Name"};
          Util::resultSetToHtml(rs,headers,out);
        }
        else {
          ...同上,但是对于教师的...
        }
        out.println("</Body>");
        out.close();
      }
}

我们终于知道服务器对HTTP请求的原理了,当服务器接收到请求来执行一个特定的servlet时,servlet的代码被加载到Web/应用服务器中,servlet的任务就是处理这种请求,访问数据库以检索出必要的信息,并动态生成一个HTML页面返回给客户端浏览器。


我们注意到,前端指定了ation = "PersonQuery",而后端则使用注解@WebServlet("PersonQuery")来显示的注释当前servlet是用来处理对PersonQuery的请求的。而且前端的表单指定使用HTTP的Get机制,因此servlet的doGet()方法将会被执行。


每次servlet请求都导致在执行调用的内部生成一个新的线程,因此多个请求就可以被并行处理。


请求将cookie和参数放入一个HttpServletRequest对象 中,后端通过api对其进行提取,根据提取参数执行数据库的查询工作,最后将其通过HttpServletResonse 对象返回。


结果是这样输出给response的,我们通过它获取了一个PrintWriter 对象,将要返回的html通过该对象输出,其中查询到的数据输出的方式是Util.resultSetToHtml()实现的。其参考代码如下。

825e8bbd284344f5b47482330b035df6.jpg


3.2 Sevlet会话

cookie可以用来识别一个请求与前一个请求是否来自同一个浏览器会话。其在后端servlet处理的逻辑是怎么样的呢?


servlet的API中提供了跟踪会话技术的方法。调用HttpServletRequest中的getSession(false)可以获取来自浏览器的HttpSession对象。当该方法被调用是,将会首先要求哦i客户端返回一个具有指定名称的cookie,如果没有该cookie,则说明该请求不是正在进行的会话的一部分。


此时getSession会返回一个空值,引导用户到登入页面。登录页面允许用户提供用户名和密码,登录页面所对象的servlet会验证用户的信息。


如果用户通过认证,登录servlet会话会执行getSession(true),这个方法会创建一个新的会话。为了创建一个新的会话,服务器内部会执行如下任务:在客户端浏览器中设置一个cookie(比如名为sessionId),该cookie用会话标识作为它所关联的值。创建一个新的会话对象,并将会话标识的值与该会话对象相关联。


servlet代码还能够在HttpSession对象中存储和查找(属性,值)对,以便在一个会话内的多个请求之间维持状态。比如,用户通过登录认证并且会话对象被创建之后,可以将userid存储为会话的一个参数,标记该用户已经通过了登录认证:

session.setAttribute("userid",userid)

那么我们只需要取出userid,就可以判断会话用户有没有通过登录认证。如果没有,就可以通过下面的方式让其回到登录页。

b864293aab014934b8080f7096453690.jpg


为了详细说明上面的内容,我们看如下登录案例(转载)。


需要的页面:


login.jsp:登录页面,提供登录表单;


index1.jsp:主页,显示当前用户名称,如果没有登录,显示您还没登录;


index2.jsp:主页,显示当前用户名称,如果没有登录,显示您还没登录;


Servlet:


LoginServlet:在login.jsp页面提交表单时,请求本Servlet。在本Servlet中获取用户名、密码进行校验,如果用户名、密码错误,显示“用户名或密码错误”,如果正确保存用户名session中,然后重定向到index1.jsp;


当用户没有登录时访问index1.jsp或index2.jsp,显示“您还没有登录”。如果用户在login.jsp登录成功后到达index1.jsp页面会显示当前用户名,而且不用再次登录去访问index2.jsp也会显示用户名。因为多次请求在一个会话范围,index1.jsp和index2.jsp都会到session中获取用户名,session对象在一个会话中是相同的,所以都可以获取到用户名!

login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>login.jsp</title>
  </head>
  <body>
    <h1>login.jsp</h1>
    <hr/>
    <form action="/day06_4/LoginServlet" method="post">
    用户名:<input type="text" name="username" /><br/>
        <input type="submit" value="Submit"/>
    </form>
  </body>
</html>

index1.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>index1.jsp</title>
  </head>
  <body>
<h1>index1.jsp</h1>
<%
    String username = (String)session.getAttribute("username");
    if(username == null) {
       out.print("您还没有登录!");
    } else {
       out.print("用户名:" + username);
    }
%>
<hr/>
<a href="/day06_4/index2.jsp">index2</a>
  </body>
</html>

index2.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>index2.jsp</title>
  </head>
  <body>
<h1>index2.jsp</h1>
<%
    String username = (String)session.getAttribute("username");
    if(username == null) {
       out.print("您还没有登录!");
    } else {
       out.print("用户名:" + username);
    }
%>
<hr/>
<a href="/day06_4/index1.jsp">index1</a>
  </body>
</html>

LoginServlet

public class LoginServlet extends HttpServlet {
    public void doPost(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException {
       request.setCharacterEncoding("utf-8");
       response.setContentType("text/html;charset=utf-8");
       String username = request.getParameter("username");
       if(username.equalsIgnoreCase("cloud")) {
           response.getWriter().print("用户名或密码错误!");
       } else {
           HttpSession session = request.getSession();
           session.setAttribute("username", username);
           response.sendRedirect("/day06_4/index1.jsp");
       }
    }
}

3.3 Servlet的生命周期

b7562756fdbf449c9419dcc4cab925f6.jpg


servlet的生命周期由部署它的web/应用服务器来控制,当由客户端请求一个特定的servlet时,服务器首先检查是否存在该servlet的一个实例。如果不存在,web服务器就将servlet类加载进java虚拟机,并创建一个servlet类的实例。另外,服务器调用init()方法来初始化该servlet实例。每个servlet实例仅在它被加载的时候被初始化一次。


在确定servlet实例存在后,服务器调用servlet的service方法,并以一个request对象和一个response对象作为参数,在缺省的情况下,服务器创建一个新的线程执行service方法,因此,一个servlet上的多个请求就可以并行执行,而不必等待之前的线程执行完。service方法视情况调用doGet或doPost.


当不再需要的时候,可以通过调用destroy()方法来关闭一个servlet。服务器可以设置一个超时时限,如果在超时时限内没有对一个servlet进行过一个请求,则自动关闭该servlet。超时实现是一个参数,可以根据应用来适当的对它进行设置。

3.4 应用服务器

最知名的servlet应用服务器是Apache的Tomcat。


321d1b88d1074da48b19df407ffb78f3.jpg


开发Servlet的应用程序的最佳方式是使用Idea,eclipse等Ide编辑器,他们内置有Tomcat服务器。


除了最基本的servlet支持之外,应用服务器通常还提供了各种有用的服务,它们允许应用程序被部署或者被停止,并且它们提供了监控应用服务器的功能,包括性能监控。还支持跨多个应用服务器的并行处理,处理对象等。


相关文章
|
1月前
|
存储 移动开发 大数据
HTML5 Web IndexedDB 数据库详解
IndexedDB 是一种高效的浏览器存储方案,允许在本地存储大量结构化数据,支持索引和事务,适用于需要离线和大数据处理的应用。它由数据库、对象仓库等组成,通过键值对存储数据,确保数据一致性和完整性。本介绍展示了如何创建、读取、更新和删除数据,以及事务和错误处理的最佳实践。
|
3月前
|
Java 关系型数据库 MySQL
"解锁Java Web传奇之旅:从JDK1.8到Tomcat,再到MariaDB,一场跨越数据库的冒险安装盛宴,挑战你的技术极限!"
【8月更文挑战第19天】在Linux上搭建Java Web应用环境,需安装JDK 1.8、Tomcat及MariaDB。本指南详述了使用apt-get安装OpenJDK 1.8的方法,并验证其版本。接着下载与解压Tomcat至`/usr/local/`目录,并启动服务。最后,通过apt-get安装MariaDB,设置基本安全配置。完成这些步骤后,即可验证各组件的状态,为部署Java Web应用打下基础。
57 1
|
1月前
|
存储 移动开发 数据库
HTML5 Web IndexedDB 数据库常用数据存储类型
IndexedDB 支持多种数据存储类型,满足复杂数据结构的存储需求。它包括基本数据类型(如 Number、String、Boolean、Date)、对象(简单和嵌套对象)、数组、Blob(用于二进制数据如图像和视频)、ArrayBuffer 和 Typed Arrays(处理二进制数据)、结构化克隆(支持 Map 和 Set 等复杂对象),以及 JSON 数据。尽管不直接支持非序列化数据(如函数和 DOM 节点),但可以通过转换实现存储。开发者应根据具体需求选择合适的数据类型,以优化性能和使用体验。
|
1月前
|
SQL 存储 移动开发
HTML5 Web SQL 数据库详解
Web SQL 数据库是 HTML5 中的一种本地存储技术,允许在浏览器中使用 SQL 语言操作本地数据,支持离线访问和事务处理,适用于缓存数据和小型应用。然而,其存储容量有限且仅部分现代浏览器支持,标准已不再积极维护,未来可能被 IndexedDB 和 localStorage 等技术取代。使用时需谨慎考虑兼容性和发展前景。
|
3月前
|
安全 关系型数据库 数据库
FastAPI数据库操作秘籍:如何通过高效且安全的数据库访问策略,使你的Web应用飞速运转并保持数据完整性?
【8月更文挑战第31天】在构建现代Web应用时,数据库操作至关重要。FastAPI不仅简化了API创建,还提供了高效数据库交互的方法。本文探讨如何在FastAPI中实现快速、安全的数据处理。FastAPI支持多种数据库,如SQLite、PostgreSQL和MySQL;选择合适的数据库可显著提升性能。通过安装相应驱动并配置连接参数,结合ORM库(如Tortoise-ORM或SQLAlchemy),可以简化数据库操作。使用索引、批量操作及异步处理等最佳实践可进一步提高效率。同时,确保使用参数化查询防止SQL注入,并从环境变量中读取敏感信息以增强安全性。
165 1
|
3月前
|
缓存 NoSQL 数据库
Web服务器与数据库优化:提升系统性能的最佳实践
【8月更文第28天】在现代的Web应用中,Web服务器与后端数据库之间的交互是至关重要的部分。优化这些组件及其相互作用可以显著提高系统的响应速度、吞吐量和可扩展性。本文将探讨几种常见的优化策略,并提供一些具体的代码示例。
166 1
|
2月前
|
关系型数据库 Java MySQL
"解锁Java Web传奇之旅:从JDK1.8到Tomcat,再到MariaDB,一场跨越数据库的冒险安装盛宴,挑战你的技术极限!"
【9月更文挑战第6天】在Linux环境下安装JDK 1.8、Tomcat和MariaDB是搭建Java Web应用的关键步骤。本文详细介绍了使用apt-get安装OpenJDK 1.8、下载并配置Tomcat,以及安装和安全设置MariaDB(MySQL的开源分支)的方法。通过这些步骤,您可以快速构建一个稳定、高效的开发和部署环境,并验证各组件是否正确安装和运行。这为您的Java Web应用提供了一个坚实的基础。
54 0
|
3月前
|
开发者 前端开发 Java
架构模式的诗与远方:如何在MVC的田野上,用Struts 2编织Web开发的新篇章
【8月更文挑战第31天】架构模式是软件开发的核心概念,MVC(Model-View-Controller)通过清晰的分层和职责分离,成为广泛采用的模式。随着业务需求的复杂化,Struts 2框架应运而生,继承MVC优点并引入更多功能。本文探讨从MVC到Struts 2的演进,强调架构模式的重要性。MVC将应用程序分为模型、视图和控制器三部分,提高模块化和可维护性。
47 0
|
3月前
|
数据库 开发者 Python
【绝技揭秘】如何用Web2py玩转数据库?打造数据驱动Web应用的五大绝招!
【8月更文挑战第31天】本文通过具体示例介绍如何使用Web2py这款强大的Python Web框架进行数据库操作,创建数据驱动的Web应用。从创建应用、定义数据库模型到实现CRUD操作,逐步演示了如何构建一个简单的博客系统,包括文章列表页和详情页,并提供表单让用户创建新文章。通过本文,你将学会利用Web2py简化数据库交互,提升开发效率。
37 0
|
3月前
|
网络协议 NoSQL 网络安全
【Azure 应用服务】由Web App“无法连接数据库”而逐步分析到解析内网地址的办法(SQL和Redis开启private endpoint,只能通过内网访问,无法从公网访问的情况下)
【Azure 应用服务】由Web App“无法连接数据库”而逐步分析到解析内网地址的办法(SQL和Redis开启private endpoint,只能通过内网访问,无法从公网访问的情况下)