上一节呢,我们简单阐述了远古时期的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

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

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

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

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

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

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

哇哦,这不就是一个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

实现了一样的效果。

但是,从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,我们把书本单独封装为一个类。

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,只做业务处理和跳转

/*** 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);}@Overrideprotected 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

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

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

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

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

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

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

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

看下三层架构的示意图

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

引用自百科的解释:

三层架构(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

创建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了,只用来装配数据,没有了业务逻辑。

至于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);
}

最后再来一张全图:

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

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

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

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

JavaWeb编年史(青铜时代)相关推荐

  1. JavaWeb编年史(远古时期)

    目录 远古时代:纯Servlet 背景 servlet初体验 纯Servlet的缺点 源码下载 作为一个Java程序员,我们更多耕耘的是JavaWeb项目,简单来说就是做网站或者业务系统.随着互联网时 ...

  2. 这几个过时Java技术不要再学了

    Java 已经发展了近20年,极其丰富的周边框架打造了一个繁荣稳固的生态圈. Java现在不仅仅是一门语言,而且还是一整个生态体系,实在是太庞大了,从诞生到现在,有无数的技术在不断的推出,也有很多技术 ...

  3. AppStore编年史 iOS游戏开发者的变迁路

    http://ipad.66u.com/yxzb/20140627_29184.html 智能机游戏市场发展不过三四年,其间的形态与格局变化,却已沧海桑田.AppStore编年史带大家走进iOS游戏开 ...

  4. 游戏运维编年史|可能是目前最详细的游戏运维指南(转载附链接)

    游戏运维编年史|可能是目前最详细的游戏运维指南 2016年4月5日 12:28  互联网   width="280" height="24" scrolling ...

  5. 游戏运维编年史:可能是目前最详细游戏运维指南

    游戏运维编年史:可能是目前最详细游戏运维指南 从端游到页游再到手游,15年来中国网游在世界上都有着举足轻重的地位.但是再好的游戏如果出现连接.延迟等问题时也会造成巨大损失,这时游戏运维便发挥了举足轻重 ...

  6. 游戏运维编年史|可能是目前最详细的游戏运维指南

    一直以来,中国网游在世界上都处于举足轻重的地位.从最早的端游到页游再到手游,不仅市场用户 爆发式增长,近15年来网游技术的发展也是无比迅速.和单机游戏不同,网游除了游戏制作本身以外还牵涉到服务器端,再 ...

  7. javaWeb——Servlet

    Servlet 系统架构 B/S结构的系统通信原理(没有涉及到Java小程序) 关于WEB服务器软件 实现一个最基本的web应用(这个web应用中没有java小程序) 对于一个动态的web应用来说,一 ...

  8. JavaWeb笔记01

    文章目录 JavaWeb(狂神说Java) 1.基本概念 1.1前言 1.2web应用程序 1.3静态web 1.4 动态web 2.web服务器 2.1技术讲解 2.2web服务器 3.Tomcat ...

  9. 使用maven搭建ssm框架的javaweb项目

    目前主流的javaweb项目,常会用到ssm(Spring+Spring MVC+Mybatis)框架来搭建项目的主体框架,本篇介绍搭建SSM框架的maven项目的实施流程.记之共享! 一.SSM框架 ...

  10. javaweb学习总结(二十三)——jsp自定义标签开发入门

    一.自定义标签的作用 自定义标签主要用于移除Jsp页面中的java代码. 二.自定义标签开发和使用 2.1.自定义标签开发步骤 1.编写一个实现Tag接口的Java类(标签处理器类) 1 packag ...

最新文章

  1. iOS使用支付宝支付步骤
  2. 谷歌称居家办公影响工作效率!2021 年将回归线下办公
  3. 分享阿里云SLB-负载均衡的实现基本原理架构
  4. OpenNebula 入门安装配置
  5. dlib人脸检测功能介绍
  6. 邓公数据结构C++语言版学习笔记——二叉树
  7. 信息学奥赛一本通 2064:【例2.1】交换值
  8. MATLAB——PLOT绘图
  9. 同质化代币和非同质化代币 区别对比
  10. Atitit.软件仪表盘(8)--os子系统--资源占用监测
  11. 电路设计_示波器接地常识
  12. 常用的端口号(port number)
  13. 程序员的奋斗史(三十一)——人在囧途之应聘篇(一)
  14. FM收音机ic FM发射模块SX6116
  15. VMware Fusion安装cloudera manager
  16. python把四个图画在一个窗口_Python 多个图同时在不同窗口显示的实现方法
  17. 智能语音计算器(四)
  18. 景安服务器 磁盘挂载 步骤教程
  19. python模块之HTMLParser简介
  20. 域名中不应出现下划线

热门文章

  1. 嵌入式高速串行并行技术_推荐(张锋)
  2. 涡旋电磁波:无线通信的革命
  3. php扩展引擎手册,模板引擎-THINKPHP 5.0 手册最新版
  4. JSX、JSX的介绍、JSX特点、JSX的语法、XML基本语法
  5. 实验9 面向对象程序设计方法
  6. ubuntu16.04系统下配置caffe的GPU环境,训练mobileNet-SSD并在EAIDK-310嵌入式上推理
  7. 外设/* 面包板套件使用
  8. 常见经典音频运放(一般作前级用)
  9. 【系统分析师之路】第二十一章 复盘系分专业英语
  10. mysql 统计每天、每周、每月、每年数据