JavaWeb13-设计模式案例实现(Java真正的全栈开发)

JavaWeb设计模式&案例

一.JavaWeb的设计模式

1. jsp模式介绍

SUN公司推出JSP技术后,同时也推荐了两种web应用程序的开发模式,一种是JSP+JavaBean模式(model1模式),一种是Servlet+JSP+JavaBean模式(model2模式)。

Model1模式介绍

model1模式各部分功能分析

JSP+JavaBean模式适合开发业务逻辑不太复杂的web应用程序,这种模式下,JavaBean用于封装业务数据,JSP即负责处理用户请求,又显示数据

model1模式的优缺点

优点

简单快捷,对开发人员要求不高

缺点

所有的操作都在jsp页面中,其中访问数据库的API是在jsp页面中完成的,难以维护,不适合做比较复杂应用 ,它只适合中小型项目.

Model2模式介绍

model2模式各部分功能分析

Servlet+JSP+JavaBean(MVC)模式适合开发复杂的web应用,在这种模式下,servlet负责处理用户请求,jsp负责数据显示,javabean负责封装数据。 Servlet+JSP、JavaBean模式程序各个模块之间层次清晰,web开发推荐采用此种模式。

model2模式的优缺点

优点:

维护方便,开发人员各司其职,互不干涉,有利于开发中的分工,有利于组件的重用。比较适合做比较复杂应用,它适合做中大型项目

缺点:

项目开发难度增大,对开发人员的要求也随之提高。

2. javaBean介绍

什么是javaBean

JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性。众所周知,属性名称符合这种模式,其他Java 类可以通过自身机制发现和操作这些JavaBean 的属性。

JavaBean可分为两种:一种是有用户界面(UI,User Interface)的JavaBean;还有一种是没有用户界面,主要负责处理事务(如数据运算,操纵数据库)的JavaBean。JSP通常访问的是后一种JavaBean。而我们在JavaWeb开发中使用JavaBean主要是用于进行数据的运算(数据的封装)

javabena规范写法

Java可重用组件

规范:

公共具体的类

字段私有化

对外提供访问字段的方法

实现序列化接口

提供无参的构造方法

javaBean在model1模式下的使用

njsp:useBean
njsp:setProperty
njsp:getProperty

例如:

username:<input type="text" name="username"><br>
password:<input type="password" name="password"><br>

jsp中使用bean标签来封装数据

<jsp:useBean id="user" class="cn.itcast.doamin.User"></jsp:useBean>
<jsp:setProperty property="*" name="user"/>

通过getProperty标签获取数据

<jsp:getProtery property=’username’ name=’user’/>

要求:页面上组件的名称必须与javaBean的bean属性名称一致.

bean属性是get/set 后面的名称

3. BeanUtils工具类的使用

javaBean在model2模式下的使用(BeanUtils工具使用)

在model1模式下我们使用jsp提供的标签来将数据封装到javaBean中,那么我们在model2模式下,因为jsp已经不在进行功能的处理,只是用于显示数据,这时怎样将数据封装到JavaBean中?

如果我们通过手动封装是可以的,但是如果参数过多,那么代码量很大,这时我们可以通过反射机制来完成请求参数的封装。

1.得到所有请求参数 request.getParameterMap();

2.得到javaBean类的Class对象,得到这个类中所有方法 getDeclaredMethods();

3.判断methods中是否具有 setXxx方法 从map集合的key中获取

4.如果查找到这个方法,通过这个方法的invoke进行调用 method.invoke()方法

Class clazz = user.getClass();
Method[] methods = clazz.getDeclaredMethods();
Set<String> fields = map.keySet();
for (Method m : methods) {
for (String f : fields) {
if(("set"+f).equalsIgnoreCase(m.getName())){
m.invoke(user, map.get(f)[0]);
}
}
}

上述代码我们自己完成会很复杂,在开发中,我们可以使用BeanUtils工具来完成它的底层实现就是通过java中的内省机制(最底层就是反射)来完成的。

BeanUtils工具介绍

Apache组织开发了一套用于操作JavaBean的API,这套API考虑到了很多实际开发中的应用场景,因此在实际开发中很多程序员使用这套API操作JavaBean,以简化程序代码的编写

BeanUtils工具的使用步骤

1.导入jar包

commons-logging-1.1.1.jar

commons-beanutils-1.8.3.jar

2.使用

BeanUtils.populate(javaBean对象, request.getParameterMap());

BeanUtils工具类型转换

在使用BeanUtils工具对数据进行封装时,它是如何做到将请求参数(字符串)封装到javaBean的不同类型的属性上的呢?

BeanUtils默认类型转换介绍

在BeanUtils工具中,有默认的类型转换,我们可以在org.apache.commons.beanutils.converters包下查看到它们提供的默认的类型转换器

BeanUtils自定义类型转换器

在开发中,有很多情况下,数据类型的转换使用BeanUtils工具可能不完全够用,这时我们就可以通过自定义类型转换器来完成操作。步骤如下:

1.创建一个类,实现这个接口org.apache.commons.beanutils.Converter

这个接口就是BeanUtils中所有类型转换器的根接口.

2.重写方法 public Object convert(Class type, Object value)

在这个方法中完成类型转换.

这个方法的返回值就是赋值给javaBean中对应的属性.

type:要转换成的类型

value:表单传递过来的属性值

3.注册类型转换器.

ConvertUtils.register(javaBean对象,要转换成的类型.class);

4. MVC设计模式

MVC模型介绍

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。MVC模式最早被Trygve Reenskaug提出,成为施乐帕罗奥多研究中心(Xerox PARC)的Smalltalk语言发明的一种软件设计模式。MVC可对程序的后期维护和扩展提供了方便,并且使程序某些部分的重用提供了方便。而且MVC也使程序简化,更加直观。

MVC各部分功能

需要注意的是MVC设计模式并不是java语言独有的设计模式,几乎所有的B/S结构的项目都在使用这种设计模式。其中M、V、C分别代表如下含义:

lM:model层,即模型层,用来维护数据以及提供数据访问方法;

lV:view层,即视图层,通常由jsp充当,用于展示模型的部分数据或所有数据的可视化视图;

lC:controller层,即控制层,用于对处理请求。

JavaWeb中的MVC

JSP Model2模式已经可以清晰的看到MVC完整的结构了,在JSP Model2中层次划分的很清晰,如下所示:

Ø JSP:视图层,用来与用户打交道,负责接收用户的数据,以及显示数据给用户;

Ø Servlet:控制层,负责找到合适的模型对象来处理业务逻辑,转发到合适的视图;

JavaBean:模型层,完成具体的业务工作,例如:开启、转账等。

5. JavaWeb三层架构

JavaWeb三层架构介绍

所谓的三层架构是由web层,业务层及数据层组成的,它们分别完成各自的工作,如下所示:

Web层:包含jsp和Servlet等与web相关的内容;

业务层:也称Service层,业务层中不包含JavaWeb的API,它只关心业务逻辑;

数据层:有时候也称为是持久层,其功能主要是负责数据库的访问,简单的说法就是实现对数据表的Select,Insert,Update,Delete的操作。

其中,web层是与web相关的内容,包括jsp和servlet,以及request、response、session、ServletContext等,这些对象只能出现在web层,不能出现在业务层;同样,业务层只关心业务逻辑,例如登录,注册功能,其中注册就是向数据库中插入一条数据,这样在数据层就对应一个方法,因此业务层依赖于数据层,可以这样理解:业务层的一个功能是由数据层的若干个对数据库的操作组成的。而web层将用户输入的数据传递给业务层,业务层处理之后将结果返回给web层,由web层再展示给用户。也就是说web层依赖于业务层。

由于业务层和数据层没有出现JavaWeb的API,因此业务层和数据层是可重用的,甚至可以应用在非web环境中。

JavaWeb三层架构与MVC的区别分析

三层架构是一个分层式的软件体系架构设计,它可适用于任何一个项目。

MVC是一个设计模式,它是根据项目的具体需求来决定是否适用于该项目。

那么架构跟设计模式有什么区别呢?

我们从接手一个项目开始,首先,我们需要进行架构设计,一般我们采用的就是分层式的架构设计,即我们的三层架构。

然后,在确定了架构以后,我们再根据项目的具体需求去考虑是否需要应用一些设计模式,比如是否应用我们的MVC模式,抽象工厂模式等等。

二.案例

1. 注册分析

2. 注册实现

搭建环境

包结构

导入jar包

mysql驱动和BeanUtils

创建数据库/表/User类

create database day13;
use day13;
create table user(
id int primary key auto_increment,
username varchar(20),
password varchar(20),
sex varchar(10),
telephone varchar(20),
email varchar(50),
introduce varchar(100)
);
private Integer id;
private String email;
private String username;
private String password;
private String sex;
private String introduce;
private String telephone;

注册的流程

regist.jsp-->RegistServlet-->UserService-->UserDao

注意问题

注册操作的返回值问题

方案两种:

a.返回一个常量,通过常量判断

b.使用自定义异常

若使用自定义异常,步骤如下:

1.在exception包下创建一个UserRegistException类它就是代表我们注册操作中产生的问题。

2.如果在dao中产生了问题,我们直接向service层抛出一个UserRegistException(msg)

3.在service层,现在不处理,直接抛给servlet,在servlet中可以根据try..catch来判断注册是否成功。

4.如果catch到异常,将异常信息通过request域存储,并请求转发到regist.jsp页面显示错误信息。

后台校验问题

在开发中,对于请求的数据需要做双向校验

客户端需要校验 使用javascript

服务器端需要校验 使用java代码。

因为我们使用Beanutils工具,它帮助我们将请求参数直接封装到了javaBean中,那么我们要做校验,就可以直接在javaBean中创建一个public Map<String,String> validate()方法来校验。

1.在RegistServlet首先通过Beanutils已经将请求参数封装到了User中,那么我们调用User类的validate方法时,这些请求参数在user对象中已经存在了,那么我们在validate方法中使用的username,password等就已经有值了。

2.validate方法返回的是一个Map<String,String>,它的key是

username.msg password.msg 它的value是 用户名不能为空,密码不能为空。

3.当我们在RegistServlet类中调用validate方法后,就会得到一个Map集合,判断集合size==0就可以知道是否有错误信息,如果有,将map集合遍历,将key存储为request域中的name值,将map的value做为request域中的value值。

Request.setAttribute(“username.msg”,”用户不能为空”);

4.当请求转发到regist.jsp页面我们就可以使用el表达式将错误信息取出展示出来。

3. 登录分析

4. 登录实现

记住用户名

实现原理:

1.当用户登陆成功后,将用户名持久化存储到cookie中。

2.当下一次在访问登陆页面后,直接从cookie中获取用户名显示在用户名的文本框中。

实现操作:

1.登陆成功后,判断用户是否勾选了记住用户名操作

Request.getParameter(“saveName”)

判断它的值是否是”ok”

如果是就代表勾选了。

2.如果勾选了,就创建一个cookie

Cookie cookie=new Cookie(“username”,username);

持久化存储 setMaxAge() setPath()

在login.jsp页面上使用

${cookie.username.value}来在用户名文本框上显示信息。

3.根据需求再处理没有勾选的业务逻辑,若需要删除以前记住过用户名,就将cookie删除 setMaxAge(0);

5.扩展详写:

java的三层架构(实际开发)

web

作用:

展示数据 jsp

接受请求参数

调用service处理具体业务

页面跳转

提示信息

service

作用:

处理业务逻辑(调用dao)

dao(data access object)

作用

curd

案例-注册

将用户的信息持久化到数据库中

流程:

regist.jsp-->registServlet-->UserService-->UserDao

添加成功之后跳转到success.jsp

添加失败之后 提示信息,regist.jsp

实现:

前提工作:

数据库和表

create database day13;
use day13;
create table user(
id int primary key auto_increment,
username varchar(20),
password varchar(20),
sex varchar(10),
telephone varchar(20),
email varchar(50),
introduce varchar(100)
);

前台页面

复制图片

将html页面转成jsp

javabean
private Integer id;
private String email;
private String username;
private String password;
private String sex;
private String introduce;
private String telephone;

工具类

jdbcutils

jdbc.properties

jar包

驱动包

beanutils的两个jar包

搭建项目结构:

cn.itcast.web.servlet:存放的是servlet

cn.itcast.service:存放的service

cn.itcast.dao:存放的dao

cn.itcast.domain:存放的javabean

cn.itcast.utils:存放的工具类

原文发布于微信公众号 - Java帮帮(javahelp)

原文发表时间:2017-01-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Seebug漏洞平台

Spring MVC 目录穿越漏洞(CVE-2018-1271)分析

2018年04月05日,Pivotal公布了Spring MVC存在一个目录穿越漏洞(CVE-2018-1271)。Spring Framework版本5.0到...

4462
来自专栏Java后端技术栈

Java多线程编程-(13)-从volatile和synchronized的底层实现原理看Java虚拟机对锁优化所做的努力

对于Java来说我们知道,Java代码首先会编译成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上进行执行。

961
来自专栏java一日一条

Java NIO 核心组件学习笔记

对于I/O操作,根据Oracle官网的文档,同步异步的划分标准是“调用者是否需要等待I/O操作完成”,这个“等待I/O操作完成”的意思不是指一定要读取到数据或者...

1102
来自专栏王磊的博客

Java核心(三)并发中的线程同步与锁

乐观锁、悲观锁、公平锁、自旋锁、偏向锁、轻量级锁、重量级锁、锁膨胀...难理解?不存的!来,话不多说,带你飙车。

1312
来自专栏程序猿DD

死磕Java并发:深入分析synchronized的实现原理

记得刚刚开始学习Java的时候,一遇到多线程情况就是synchronized。对于当时的我们来说,synchronized是如此的神奇且强大。我们赋予它一个名字...

1437
来自专栏北京马哥教育

Python爬虫实战之使用Scrapy爬起点网的完本小说

作者:totcw 来源:http://blog.csdn.net/totcw/article/details/65444660 一.概述 本篇的目的是用scr...

3807
来自专栏QQ音乐技术团队的专栏

打通Android Gradle编译过程的任督二脉

本文主要是基于自己在工作当中的一些Android Gradle实践经验,对gradle相关知识做的一个简单总结和分享,希望对大家有帮助。 首先会讲Gradle大...

1.7K9
来自专栏Java学习123

Python3.4+Django1.7+SQLite3实现增删改查

3765
来自专栏JavaEdge

线程安全与锁优化1 线程安全2 锁优化

3479
来自专栏Java学习之路

Java并发之底层实现原理学习笔记

本篇博文将介绍java并发底层的实现原理,我们知道java实现的并发操作最后肯定是由我们的CPU完成的,中间经历了将java源码编译成.class文件,然后进行...

3586

扫码关注云+社区

领取腾讯云代金券