JavaWeb编年史(青铜时代)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaWeb编年史(青铜时代)相关的知识,希望对你有一定的参考价值。


上一节呢,我们简单阐述了远古时期的JavaWeb开发方案,简单来说就是一个Servlet打天下,不管你送什么请求过来,我都要给你返回一整个页面。整个页面都用java拼接出来,可想而知代码是有多么复杂,多么难以维护。要我说,这个时代的程序员都是全才,说话又好听,我超喜欢跟他们打交道的。因为你既要懂html页面,css美工,还要会java,数据库,所有的活都是他一个人包了,可见有多牛。

但是,如果这时候老板说要改页面,做一些特效和动态效果,不知道程序员看着全部混在一起的代码作何感想?

为了弥补全用Servlet的弊端,Sun公司推出了一个叫做JSP的东西,从此进入JavaWeb编年史的青铜时代。

青铜时代(前期)纯JSP开发

JSP技术,全称是Java Server Page,JSP中采用HTML语言直接生成界面,还可以在界面中使用<% %>脚本标识嵌入Java代码,揪其本质也是最终生成一个Servlet类来编译解析。

说得简单一些,当时的人普遍觉得在Servlet里面写一大堆​​out.println​​实在是有点秀。急切地需要一个模板工具来改变这一惨状,JSP正好符合了需求。

所谓地JSP,本质还是一个Servlet,但是它看起来是一个HTML,而且你可以在HTML中混淆一些Java代码。

这就有趣多了,之前在Servlet完成的业务逻辑,现在可以直接在JSP页面中搞。

说白了,就是省去了写一大堆​​out.println​​​的麻烦,你在jsp中写html,会自动解析成​​out.println​​输出语句。

让我们把昨天的项目复制一份改个名字web2

JavaWeb编年史(青铜时代)_servlet

导入idea,在webapp目录下新建一个book.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>网上书城</title>
</head>
<body>

</body>
</html>

这怎么看都是一个普通的HTML有没有,不要急,我们再去看一个东西,你就知道咋回事了。

找到Tomcat的实际目录,里面有一个work文件夹

JavaWeb编年史(青铜时代)_java_02

打开,是Catalina,再打开,直到找到发布的项目名称。

JavaWeb编年史(青铜时代)_servlet_03

里面有一个book_jsp.java,打开一看

JavaWeb编年史(青铜时代)_mvc_04

JavaWeb编年史(青铜时代)_servlet_05

哇哦,这不就是一个Servlet吗?所以,JSP的本质就是一个Servlet。还有所谓的JSP九大隐式对象,就是这个Servlet里面的变量罢了。

嗯,如果我们用JSP来重写原来的代码,画风就变成了这样。

<%
//模拟书本列表信息
List<String> books = new ArrayList<String>()
add("五年高考三年模拟");
add("王后雄教案");
;
%>

<h1>欢迎来到网上书城!</h1>
<ul>
<% for (String book : books) %>
<li><%=book %></li>
<% %>
</ul>

访问http://localhost:8080/web2_war/book.jsp

JavaWeb编年史(青铜时代)_servlet_06

实现了一样的效果。

但是,从Servlet完全转到JSP只是一定程度上缓解了编写Servlet的困难,并不能解决前后端代码完全混在一起的弊端。

前端开发人员需要看大量他看不懂的后端代码; 同样,servlet开发人员也要在复杂的前端代码中找到其能写servlet代码的地方。

青铜时代(中期)JSP+servlet+JavaBean

为了解决纯JSP开发的痛点,人们的一次有效尝试是进行职责分离,可以看作是MVC模式。

简单来说,MVC就是JSP纯粹当作一个模板引擎来使用(View),Servlet只管请求的转发还有页面跳转的操作(Controller),JavaBean负责数据和业务的提供(Model)。

该模型基于MVC模式,完全实现了页面显示和逻辑分离。模型层为JavaBean实现数据的表示和业务逻辑,视图层为JSP页面,只负责显示功能,控制器为Servlet,负责接收用户的请求,设置JavaBean属性,调用JavaBean完成业务处理,最后将处理结果交给JSP页面显示。

在此模型中,Servlet分担了JSP的大部分工作,将JSP从请求接收和流程控制中解放出来,业务逻辑也交给了JavaBean完成,这种方式充分利用了JSP和Servlet两种技术的优点,JSP更适合前台页面的开发,而Servlet更擅长服务器端程序的编写。

JavaBean并非是一个单纯的存储数据的类,它还提供了一系列用来操作自身数据的API方法。

为了演示MVC的优点,我们对之前的代码进行升级--web3

首先是JavaBean,我们把书本单独封装为一个类。

JavaWeb编年史(青铜时代)_java_07

package model;

import java.util.ArrayList;
import java.util.List;

public class Book
private String name;

/**
* JavaBean必须有一个空构造方法
*/
public Book()



public Book(String name)
this.name = name;


public String getName()
return name;


public void setName(String name)
this.name = name;


public List<Book> listBooks()
return new ArrayList<Book>()
add(new Book("五年高考三年模拟"));
add(new Book("王后雄教案"));
;

这就说MVC中的M(Model)。

然后是Servlet,只做业务处理和跳转

JavaWeb编年史(青铜时代)_java_08

/**
* Servlet只做页面跳转和业务逻辑
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
//获取数据
Book book = new Book();
List<Book> books = book.listBooks();
//将数据(M)嵌入到页面(V),jsp就可以通过EL表达式来获取了
request.setAttribute("books",books);
//请求转发
request.getRequestDispatcher("book.jsp").forward(request,response);


@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
doGet(request,response);

这就说MVC中的C(Controller)。

最后是MVC中的V(View)

<h1>欢迎来到网上书城!</h1>
<ul>
<c:forEach items="$books" var="item">
<li>$item.name</li>
</c:forEach>
</ul>

注意,引入EL表达式需要添加两个依赖:

<!--jstl依赖-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>

jsp页面的头部要加上这个标签。

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

如果EL表达式不生效,page标签要加上这个属性:​​isELIgnored="false"​

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>

验证地址:http://localhost:8080/web3_war/BookServlet

JavaWeb编年史(青铜时代)_java_09

在这种开发模式下,JSP页面中就可以不用任何的<%%>语句了,包括<%=%>全部用EL表达式来代替,列表的遍历和条件判断等(Java中的for循环和if语句)也可以通过JSTL来代替。 这样的话视图层相比较之前的开发模式来说要薄得多的多,JSP中不涉及任何的业务逻辑,前端人员修改样式也十分方便。这里可以理解为JSP为MVC设计模式中的V,即视图。

控制层通过Servlet来实现,获取前台传的参数、控制页面跳转,封装对象、向前台传输对象或者参数。并且可以由自己设计,设法用一个Servlet类实现该模块的所有功能的页面跳转。这里可以理解为Servlet为MVC设计模式中的C,即控制器。

JavaWeb编年史(青铜时代)_servlet_10

青铜时期(后期)经典三层架构

虽然上面的结构已经有了MVC的雏形,但还不是标准的MVC,因为JavaBean过于臃肿,并不能完全作为M层存在。

所以后来又有了经典的三层架构。和MVC时期不同的是,M又做了细化,分化出service层和dao层。

service层用于业务逻辑的处理,dao层则只用于跟数据库打交道,而原来的model层则变薄了,仅仅就是一些属性和get,set方法而已。

很多初学者容易把三层架构和MVC搞混,以为是一个东西,其实不是的哈。

看下三层架构的示意图

JavaWeb编年史(青铜时代)_三层架构_11

三层架构来源于后端开发的一种分层的思想。

引用自百科的解释:

三层架构(3-tier architecture)通常意义上的三层架构就是将整个业务应用划分为:界面层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)。

区分层次的目的即为了“高内聚低耦合”的思想。在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层、业务逻辑层(又或称为领域层)、表示层。

我之前的《文章发布系统》系列教程,采用的就是三层架构模式。

各层的作用如下:

表示层(Controller):主要对用户的请求接受,以及数据的返回,为客户端提供应用程序的访问。

业务逻辑层(Service):主要负责对数据层的操作。也就是说把一些数据层的操作进行组合。

数据访问层(dao):主要看数据层里面有没有包含逻辑处理,实际上它的各个函数主要完成各个对数据文件的操作。而不必管其他操作。

相信各位在初学JavaWeb的时候,对这三层架构都不陌生。当时我们一般就写那种特别简单的crud项目,这就导致我们很不理解为什么明明在controller层就能做完的事情,非要去service层和dao层走一遍。

其实这真的只是因为我们在学习的时候,做的项目太简单了。对于大型的复杂项目,分层是必须的。

让我们来看如何从JSP+servlet+JavaBean时代演变到三层架构时代。

创建service层,新建BookService

JavaWeb编年史(青铜时代)_三层架构_12

创建dao层,新建BookDao

BookDao代码(模拟SQL获取):

public class BookDao 

public List<Book> listBooks()
return new ArrayList<Book>()
add(new Book("五年高考三年模拟"));
add(new Book("王后雄教案"));
;

其实就是把JavaBean的数据获取逻辑搬了过来。 BookService代码:

BookService代码:

public class BookService 
BookDao bookDao = new BookDao();

public List<Book> listBooks()
return bookDao.listBooks();

因为业务比较简单,所以就直接调用dao层的同名方法即可。

这个时候Book类就是一个纯净的JavaBean了,只用来装配数据,没有了业务逻辑。

JavaWeb编年史(青铜时代)_三层架构_13

至于BookServlet,就需要BookService的协助,和原来不同的是,把JavaBean换成了BookSerive:

BookService bookService = new BookService();

/**
* Servlet只做页面跳转和业务逻辑
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
//获取数据
Book book = new Book();
List<Book> books = bookService.listBooks();
//将数据(M)嵌入到页面(V),jsp就可以通过EL表达式来获取了
request.setAttribute("books",books);
//请求转发
request.getRequestDispatcher("book.jsp").forward(request,response);

最后再来一张全图:

JavaWeb编年史(青铜时代)_mvc_14

至此,页面的表现由jsp实现,转发控制由servlet实现,业务逻辑写在业务逻辑层,操作数据库部分写在持久化层(dao层),封装数据放在bean层, 分工明确,各司其职。从servlet一直到三层架构的转变,其实都是为了实现高内聚,低耦合。一步一步将各个功能分配到不同的地方实现。

即便是到了今天,任何javaweb项目中都离不开三层架构的影子,可见其重要性。

可是呢,基于JSP+servlet+JavaBean的三层架构依然存在问题,因为一个项目中可能涉及成百上千个路由,如果每一个路由都配置一个Servlet,会导致servlet过多,转向频繁的问题,流程,配置也不易集中管理。有一个折中的办法,就是在一个Servlet中写多个方法,然后通过携带参数的方式去判断走哪一个方法。但是这个方案并不完美,比如它不太方便做权限控制。为了解决这个问题,就迎来了下一个时代:框架时代。

欲知后事如何,且听下回分解。

以上是关于JavaWeb编年史(青铜时代)的主要内容,如果未能解决你的问题,请参考以下文章

华为操作系统 28 年史

计算机字符编码编年史

云计算与虚拟化技术发展编年史

Atitit. Atiposter 发帖机版本历史 编年史

龙枪编年史

编程语言发展的编年史