1、传统的Java Bean + Servlet模式
之前的web开发大多是都是基于javabean+控制业务逻辑的servlet来实现的,但是这样的实现方式会有一定的缺陷,举个例子:我们有这样的一个员工子信息登记页面,每个员工都有自己的属性,例如:姓名、电话、邮箱等等。我们需要编辑这样的一个员工的javabean,然后再用业务逻辑层去获取登记信息(用request的各种get方法),最后再交给数据库去处理。
在这里我们可以去思考这样的一个事情,如果当你写好了这个web项目,有一天你的项目经理告诉你,我们的员工登记信息可不可以增加一个属性,比如爱好,那我们在加这样的一个属性,需要修改哪些东西呢?
需要修改注册页面,这个是肯定的,还要修改javabean中的属性的set和get方法,最后还要去修改servlet的业务逻辑处理,显而易见,为了添加一个属性,这是相当麻烦的,那么怎么能只去修改登记页面,而不用去修改相关的业务逻辑呢?
我们用一个例子来实现这一点。
2、打破传统模式
我们先来看一下目标:
有如下的一个员工登记表,在填写完信息之后,点击保存,跳转到servlet,然后在后台将信息输出(数据库的之后再写)。
再去看看后台输出的信息,类似于下面效果:
接下来我们看看代码的实现。
3、代码的实现
我们可以这样去思考这个登记信息页面,我们无非是去获取控件的值,看看这些控件,获得对应的name,name对应的value,除了复选框的值是一些length大于1的字符串数组,其余控件的值都是length=1的字符串数组,我们去写一个继承HttpServlet的BaseServlet类,这个类是我们自己写的一个实现了一些具体的业务逻辑的类,然后我们再根据具体的跳转的Servlet去继承这个我们自己写的BaseServlet,这样就能去实现该有的方法。
jsp页面
<%@ page language="java" pageEncoding="GBK"%>
<html>
<head>
<title>员工表</title>
</head>
<body>
<form action="/Demo01/PersonServlet" method="post">
<table border="1" align="center" width="55%">
<caption>
员工管理
<hr width="160">
</caption>
<tr>
<td>姓名</td>
<td>
<input type="text" name="pname" autofocus="autofocus" required="required">
</td>
</tr>
<tr>
<td>身份证</td>
<td>
<input name="pnumber">
</td>
</tr>
<tr>
<td>生日</td>
<td>
<input type="date" name="pdate">
</td>
</tr>
<tr>
<td>性别</td>
<td>
<!-- 单选按钮 按照名称分组,组内单选 -->
<input type="radio" name="psex" checked="checked" value="1">男
<input type="radio" name="psex" value="2">女
</td>
</tr>
<tr>
<td>手机号码</td>
<td>
<input type="text" name="ptel">
</td>
</tr>
<tr>
<td>电子邮件</td>
<td>
<input type="email" name="pemail">
</td>
</tr>
<tr>
<td>工资</td>
<td>
<!-- H5 新增数值控件 -->
<input type="number" step="0.01" name="psal">
</td>
</tr>
<tr>
<td>民族</td>
<td>
<!-- 下拉列表 -->
<select name="minzu">
<option value="01">汉族</option>
<option value="02">满族</option>
<option value="03">蒙族</option>
<option value="04">藏族</option>
<option value="05">维族</option>
</select>
</td>
</tr>
<tr>
<td>爱好</td>
<td>
<!-- 复选框 -->
<input type="checkbox" name="ah" value="1">抽烟
<input type="checkbox" name="ah" value="2">喝酒
<input type="checkbox" name="ah" value="3">吃肉
<input type="checkbox" name="ah" value="4">背床
</td>
</tr>
<tr>
<td>备注</td>
<td>
<!-- 大文本域 -->
<textarea rows="5" cols="45" name="pmemo"></textarea>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" name="next" value="保存">
</td>
</tr>
</table>
</form>
</body>
</html>
BaseServlet代码
package com.neusoft.web;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
public abstract class BaseServlet extends HttpServlet {
protected Map<String,Object> createDto(HttpServletRequest request){
//1、获取页面中所有的控件,并以键值对的形式保存到map中
Map<String,String[]> tem = request.getParameterMap();
//2、定义页面数据的封装对象
Map<String,Object> Dto = new HashMap();
//3、获取tem中所有的key的集合
Set<String> KeySet = tem.keySet();
//4、循环遍历每一个key
for(String key:KeySet){
String val[] = tem.get(key);
//如果key对应的value的值是1,就说明这是一个单选控件
if(val.length == 1){
//单选框的value是1,所以只有一个元素,直接封装到Dto中,
Dto.put(key, val[0]);
}
else{
//如果不是1,说明这是一个复选的框件
Dto.put(key, val);
}
}
return Dto;
}
}
PersonServlet代码,具体的跳转的Servlet
package com.neusoft.web;
import java.io.IOException;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/PersonServlet")
public class PersonServlet extends BaseServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取页面数据
Map<String,Object> Dto=this.createDto(request);
System.out.println(Dto);
}
}
3、有关继承的一些注意点
在上面的BaseServlet,我们加上了一个abstract关键字,使其变为抽象类,可是我们为什么去继承抽象的类的?
我们去看一个例子:
public class A extends Object{
public A(){
super();
System.out.println("A");
}
}
class B extends A{
public B(){
super();
System.out.println("B");
}
}
class C extends B{
public C(){
super();
System.out.println("C");
}
}
class D extends C{
pulic D(){
super();
System.out.println("D");
}
}
class test{
public void main(String[] args){
D();
}
}
上述这段代码的输出是A、B、C、D
我们这里要思考一个问题:实例化D为什么会输出ABCD?这里的思想其实是向上查找,向下初始化。
具体的含义就是实例化某个具体的类的时候,会先去向上去查找每个类的父类,直到查找到Object类(所有的类的默认父类),然后从最上面的父类的构造方法向下一直去初始化,也就是说,我们在初始化一个类的时候,会初始化其父类,这个是非常的浪费内存资源的所以我们只要将父类加上abstract抽象类关键字,这样抽象类就不会去初始化了,只会去初始化最下面的子类,节省资源。