SUN公司推出JSP技术后,同时也推出了两种Web应用程序的开发模式,一种是JSP+JavaBean模式,一种是Servlet+JSP+JavaBean模式。
JSP+JavaBean开发模式的架构图如下图所示:
在JSP+JavaBean架构中,JSP负责控制逻辑、表现逻辑、业务对象(JavaBean)的调用。JSP+JavaBean模式适合开发业务逻辑不太复杂的Web应用程序,在这种模式下,JavaBean用于封装业务数据,JSP既负责处理用户请求,又负责显示数据。
首先分析一下JSP和JavaBean各自的职责,JSP负责显示计算器(calculator)页面,供用户输入计算数据,并显示计算后的结果,JavaBean负责接收用户输入的计算数据并且进行计算,JavaBean具有firstNum、secondNum、result、 operator属性,并提供一个calculate方法。
现在来思考一个问题,firstNum和secondNum的数据类型应该使用什么?使用double类型吗?答案是不可以,若firstNum和secondNum的数据类型为double,那么它们计算的结果是不精确的。例如,有程序如下:
package cn.liayun.domain;
public class Demo1 {
public static void main(String[] args) {
// 浮点数运算只适合科学运算,计算的结果是不精确的
double a = 0.1;
double b = 0.006;
System.out.println(a + b);
}
}
运行以上程序,Eclipse控制台输出结果如下:
可见两数相加结果并不精确。由此得出结论,浮点数运算只适合科学运算,计算的结果是不精确的。
那么到底firstNum和secondNum的数据类型应该使用什么呢?使用BigDecimal这个类。例如,有程序如下:
package cn.liayun.domain;
import java.math.BigDecimal;
public class Demo1 {
public static void main(String[] args) {
// 记住以后要用程序计算精确的货币运算,就一定要用BigDecimal这个类
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.006");
System.out.println(a.add(b).toString());
System.out.println(a.multiply(b).toString());
System.out.println(a.divide(b, 10, BigDecimal.ROUND_HALF_UP));
}
}
运行以上程序,Eclipse控制台输出结果如下:
由此得出结论,以后要用程序计算精确的货币运算,就一定要用BigDecimal这个类。
不只如此,如果两个数无比复杂,也能进行精确的计算,如下例:
package cn.liayun.domain;
import java.math.BigDecimal;
public class Demo1 {
public static void main(String[] args) {
// 记住以后要用程序计算精确的货币运算,就一定要用BigDecimal这个类
BigDecimal a = new BigDecimal("0.134589021832190483290483258423154366546546754743654364326543");
BigDecimal b = new BigDecimal("0.00612313143243254354645654758768679721342431555555555555555543351");
System.out.println(a.add(b).toString());// 两数相加
System.out.println(a.multiply(b).toString());// 两数相乘
System.out.println(a.divide(b, 10, BigDecimal.ROUND_HALF_UP));// 两数相除,结果为四舍五入后,小数点后保留10个有效数字
}
}
CalculatorBean类的代码如下:
package cn.liayun.domain;
import java.math.BigDecimal;
//封装计算器数据的bean
public class CalculatorBean {
private String firstNum = "0";// 字段最好拥有显示值
private char operator = '+';
private String secondNum = "0";
private String result;
public String getFirstNum() {
return firstNum;
}
public void setFirstNum(String firstNum) {
this.firstNum = firstNum;
}
public char getOperator() {
return operator;
}
public void setOperator(char operator) {
this.operator = operator;
}
public String getSecondNum() {
return secondNum;
}
public void setSecondNum(String secondNum) {
this.secondNum = secondNum;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public void calculate() {
BigDecimal first = new BigDecimal(firstNum);
BigDecimal second = new BigDecimal(secondNum);
switch (this.operator) {
case '+': {
this.result = first.add(second).toString();
break;
}
case '-': {
this.result = first.subtract(second).toString();
break;
}
case '*': {
this.result = first.multiply(second).toString();
break;
}
case '/': {
if (second.doubleValue() == 0) {
throw new RuntimeException("被除数不能为0");
}
this.result = first.divide(second, 20, BigDecimal.ROUND_HALF_UP).toString();
break;
}
default:
throw new RuntimeException("运算符只能是:+-*/");
}
}
}
calculator.jsp页面的内容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>计算器title>
head>
<body style="text-align: center;">
<jsp:useBean id="calculatorBean" class="cn.liayun.domain.CalculatorBean">jsp:useBean>
<jsp:setProperty property="*" name="calculatorBean"/>
<%
try {
calculatorBean.calculate();
} catch(Exception e) {
out.write(e.getMessage());
}
%>
<br/>----------------------------------------------------------------------<br/>
计算结果是:
<jsp:getProperty property="firstNum" name="calculatorBean"/>
<jsp:getProperty property="operator" name="calculatorBean"/>
<jsp:getProperty property="secondNum" name="calculatorBean"/>
=
<jsp:getProperty property="result" name="calculatorBean"/>
<br/>----------------------------------------------------------------------<br/>
<br/>
<form action="/day09/calculator.jsp" method="post">
<table width="40%" border="1px" align="center">
<tr>
<td colspan="2">简单的计算器td>
tr>
<tr>
<td>第一个参数td>
<td><input type="text" name="firstNum"/>td>
tr>
<tr>
<td>操作符td>
<td>
<select name="operator">
<option value="+">+option>
<option value="-">-option>
<option value="*">*option>
<option value="/">/option>
select>
td>
tr>
<tr>
<td>第二个参数td>
<td><input type="text" name="secondNum"/>td>
tr>
<tr>
<td colspan="2"><input type="submit" value="计算"/>td>
tr>
table>
form>
body>
html>
在Google Chrome浏览器上访问以上页面,运行效果如下:
在平时的JavaWeb项目开发中,在不使用第三方MVC开发框架的情况下,通常会选择Servlet+JSP+JavaBean开发模式来开发JavaWeb项目,Servlet+JSP+JavaBean组合开发就是一种MVC开发模式,控制器(Controller)采用Servlet、模型(Model)采用JavaBean、视图(View)采用JSP。在讲解Servlet+JSP+JavaBean开发模式之前,先简单了解一下MVC开发模式。
因此,在Web世界里,都是Web客户端发起请求,Web服务器接收、处理并产生响应。一般Web服务器是不能主动通知Web客户端更新了内容的。虽然现在有些技术如服务器推(如Comet)、还有现在的HTML5 websocket可以实现Web服务器主动通知Web客户端。
到此,我们了解了在Web开发时的请求/响应模型,接下来我们看一下标准的MVC模型是什么。
MVC模型是一种架构型的模式,本身不引入新功能,只是帮助我们将开发的结构组织的更加合理,使展示与模型分离、流程控制逻辑、业务逻辑调用与展示逻辑分离。如下图所示:
首先让我们了解下MVC(Model-View-Controller)的概念:
从上图我们还看到,在标准的MVC中模型能主动推数据给视图进行更新(观察者设计模式,在模型上注册视图,当模型更新时自动更新视图),但在Web开发中模型是无法主动推给视图(无法主动更新用户界面)的,因为Web开发是请求-响应模型。
那接下来我们看一下在Web开发里MVC是什么样子,我们称其为Web MVC来区别标准的MVC。
Web MVC中的M(模型)-V(视图)-C(控制器)概念和标准MVC概念一样,我们再看一下Web MVC标准架构,如下图所示:
在Web MVC模式下,模型无法主动推数据给视图,如果用户想要视图更新,需要再发送一次请求(即请求-响应模型)。
Servlet+JSP+JavaBean架构其实可以认为就是我们所说的Web MVC模型,只是控制器采用Servlet、模型采用JavaBean、视图采用JSP,如下图: