JavaWeb中的MVC
不使用什么MVC的案例分析:
利用Servlet与jsp实现登陆请求,数据库查询,以及页面的跳转逻辑
具体流程如下:

不做任何结构上的考虑,可以简单的做如下实现:
目录结构

LoginServlet
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.*;
@WebServlet("/Login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);//转发到get 执行相同逻辑
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取参数
String name = req.getParameter("username");
String password = req.getParameter("pwd");
String error = null; //错误信息
boolean flag = false; //是否登陆成功
//验证数据可靠性
if(name == null || password == null || name.equals("") || password.equals("")){
error="用户名和密码不能为空!";
}else {
//查询数据库
try {
Class.forName("com.mysql.jdbc.Driver");
Connection connect = DriverManager.getConnection("jdbc:mysql://127.0.0.1/db1?charsetEncoding=utf-8&user=root&password=admin");
PreparedStatement statement = connect.prepareStatement("select *from user where name = ? and password = ?");
statement.setObject(1,name);
statement.setObject(2,password);
ResultSet set = statement.executeQuery();
if(set.next()){
flag = true;
}else{
error="用户名和密码错误!";
}
} catch (ClassNotFoundException | SQLException e1) {
error = "服务器忙,请稍后再试!";
}
}
if(flag){
//删除已存在的错误信息,避免后续登录页面展示重复展示
req.getSession().removeAttribute("error");
//添加用户名称到session
req.getSession().setAttribute("user",name);
//跳转页面
req.getRequestDispatcher("./index.jsp").forward(req,resp);
}else{
//添加错误信息到session
req.getSession().setAttribute("error",error);
//跳转页面
req.getRequestDispatcher("./login.jsp").forward(req,resp);
}
}
}
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<span style="color: red">${error}</span>
<form action="./Login" method="post">
用户名:<input name="username"/>
<br>
密码:<input name="pwd">
<br>
<input type="submit" value="登录">
</form>
</body>
</html>
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页</title>
</head>
<body>
<h1>你好${user},欢迎登录</h1>
</body>
</html>
增加需求
通过简单的逻辑判断和JDBC就实现了上述需求,接下来我们继续增加需求
假设现在要增加注册功能,可以这样:
- 创建register.jsp
- 创建 RegisterServlet
- 在RegisterServlet,获取参数,链接数据库,处理注册逻辑
思考,这样写有什么问题?
- 按照这样的思路,一个功能就需要一个Servlet,而Servlet的生命周期是非常长的,将会大量消耗内存
- 如果不创建其他Servlet,那只能将所有URL交个同一个Servlet处理,这样的话就不可避免的需要对请求路劲进行判断,以确定客户端要执行的功能
- 每个功能都要重复的进行数据库的相关操作,例如连接数据库,提取结果等,出现了大量重复代码
上述列出的问题,在程序开发中是经常遇到的,所以我们不得不对程序的整体结构进行重新思考和设计
MVC
MVC是一种软件构架模式,所谓模式,就是前辈们给我们总结出的针对固定类型问题的已有解决方案,这写方案是经过大量时间,以及大量项目实践,最终总结出的良好的方案;给开发者,提供了非常好的指导思想,在漫长的技术发展过程中,开发者们总结出了,很多好的模式,如<<23中常见模式>>一书中讲到;
注意:严格来说MVC不属于设计模式,而是构架模式,因为MVC是为程序划分层了次结构,使得程序结构更规范,更合理,降低了耦合度
针对web项目,MVC就是非常通用的构架模式,到底如何去设计一款MVC的程序呢?
MVC分层
为了降低各个功能间的耦合度,提高代码的可维护性,MVC将程序分为了三个层次
M:Model 模型,用于作为数据的载体的Bean,通常不包含复杂逻辑,一个Bean对应数据库一条记录
V:View 视图,用于展示Model中的数据,和处理用户交互
C :Controller 控制器,接受View的输入,根据需要调用Mode,获取数据后再交给View层进行展示
补充POJO和Bean的区别,POJO更加简单只要求由set/get,而Bean为了满足可重用性,有更多的规范要求
图示:

注意:
View与Model层之间不允许直接交互,必须由Controller来调度
Service层
按照这样的层次结构,将servlet用于Controller,在增加一个Bean类,来装载数据,看起来不错,但是没有解决根本的问题,业务逻辑和数据库操作依然挤在Servlet中,必须在对其进行拆分,于是在MVC基础结构上增加Service层,用于处理业务逻辑,你也可以叫它业务逻辑层(business)
看起来就像下面这样:

你可能会问,Service属于M还是C,它既不是C也不是M,是我们在MVC基础上扩展出来的,我们经常会在已有模式上扩展新的内容这很正常
使用MVC
现在对之前的程序进行改造
- 增加JavaBean,其中的属性与对应的表相同,拥有ID,name,password
- 增加service包,并创建UserService类,用作业务逻辑层
- 在控制器Servlet中,调用Service来完成业务功能
- 根据Service的返回结果来决定页面的跳转地址
项目结构:

UserLoginServlet:
package com.xx.controller;
import com.xx.exceptions.LoginException;
import com.xx.models.UserBean;
import com.xx.services.UserService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
@WebServlet("/Login")
public class UserLoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取参数
String name = request.getParameter("username");
String pwd = request.getParameter("pwd");
UserBean reqBean = new UserBean(name,pwd);
//实例化业务逻辑对象
UserService service = new UserService();
try {
//调用对应方法 根据结构跳转页面
UserBean resBean = service.CheckLogin(reqBean);
request.getSession().setAttribute("user",resBean.getName());
response.sendRedirect(request.getServletContext().getContextPath() +"/index.jsp");
} catch (LoginException e) {
request.getSession().setAttribute("error",e.getMessage());
response.sendRedirect(request.getServletContext().getContextPath() +"/login.jsp");
}
}
}
UserService:
package com.xx.services;
import com.xx.exceptions.LoginException;
import com.xx.models.UserBean;
import java.sql.*;
public class UserService {
public UserBean CheckLogin(UserBean userBean) throws LoginException {
//验证参数有效性
if (userBean.getPassword() == null || userBean.getPassword() == null ||
userBean.getPassword().equals("") || userBean.getName().equals("")){
throw new LoginException("用户名和密码不能为空");
}
UserBean bean = null;
//查询数据库
try {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/db1?characterEncoding=utf8&user=root&password=admin");
PreparedStatement preparedStatement = connection.prepareStatement("select *from user where name = ? and password = ?");
preparedStatement.setObject(1, userBean.getName());
preparedStatement.setObject(2, userBean.getPassword());
ResultSet set = preparedStatement.executeQuery();
if (set.next()) {
bean = new UserBean();
bean.setId(set.getInt(1));
bean.setName(set.getString(2));
bean.setPassword(set.getString(3));
}else {
throw new LoginException("用户名或密码错误!");
}
}catch (SQLException | ClassNotFoundException e){
e.printStackTrace();
throw new LoginException("服务器忙,(数据库炸了)",e);
}
return bean;
}
}
UserBean仅包含构造器,和setget方法
LoginException,也只是简单的继承了Exception
小结:
MVC是Web应用常用的设计模式,其增强了代码的扩展性,可维护性,降低了各组件的耦合度
在上述案例中通过MVC分层,代码结构得到了优化,但是细心的你可能已经发现了,
- 业务逻辑层Service中夹杂着与数据库相关的所有代码,导致代码冗余.重复代码问题依然没有得到解决
- UserLoginServlet依然只能处理用户的登录请求
JavaWeb中的MVC的更多相关文章
- JavaWeb中的MVC 下
代码较多,请先略过代码,看懂逻辑在研究代码 引入 回顾上一节中的项目,最终的层次结构: 在MVC上中,我们分析了MVC设计模式具备的优点,以及不足,并在其基础上增了Service层用于处理业务逻辑,但 ...
- MVC的设计模式在JavaWeb中的实现
JSP开发模式 jsp开发模式的发展 1.模式1:(适合小型项目的技术的开发) a.第一版本号,纯jsp(封装数据.处理数据,显示数据) b.第二版本号,Jsp+JavaBean. ...
- JavaWeb中监听器+过滤器+拦截器区别、配置和实际应用
JavaWeb中监听器+过滤器+拦截器区别.配置和实际应用 1.前沿上一篇文章提到在web.xml中各个元素的执行顺序是这样的,context-param-->listener-->fil ...
- javaWeb中的文件上传下载
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- 转:攻击JavaWeb应用[5]-MVC安全
转:http://static.hx99.net/static/drops/tips-347.html 攻击JavaWeb应用[5]-MVC安全 园长 · 2013/07/25 13:31 注:这一节 ...
- 生活中的MVC模式,一个吃货的理解。
以下是生活中对于MVC模式的领悟,虽然可笑,轻喷. 2015年 8月 26日 M => Model 模型 我认为叫做模具更好的理解.批量加工生产具有相同特征的东西. ...
- 【干货理解】理解javascript中实现MVC的原理
理解javascript中的MVC MVC模式是软件工程中一种软件架构模式,一般把软件模式分为三部分,模型(Model)+视图(View)+控制器(Controller); 模型:模型用于封装与应用程 ...
- 二十七、EFW框架BS系统开发中的MVC模式探讨
回<[开源]EFW框架系列文章索引> EFW框架源代码下载V1.3:http://pan.baidu.com/s/1c0dADO0 EFW框架实例源代码下载:http://p ...
- 在JavaWeb中使用Log4j步骤
在JavaWeb中使用Log4J指南.每次在开始写一个项目的时候都忘记Log4J如何配置.所以写个步骤,作为记录. 第一步 下载Log4J jar包 从Apache Logging Services ...
随机推荐
- Delphi - 手把手教你基于D7+Access常用管理系统架构的设计与实现 (更新中)
前言 从事软件开发工作好多年了,学的越深入越觉得自己无知,所以还是要对知识保持敬畏之心,活到老,学到老! 健身和代码一样都不能少,身体是革命的本钱,特别是我们这种高危工种,所以小伙伴们运动起来!有没有 ...
- openstack网络(四)-虚机流量分析
几种网络名词解释 使用LinuxBridge时虚机流量分析 VLAN FLAT Local VXLAN 使用OVS时虚机流量分析 几种网络名词解释 1.local网络:local网络是与其他网络和节点 ...
- UESTC1977-图书馆(AC自动机应用)
M - 图书馆 Time Limit: 2000 MS Memory Limit: 256 MB Submit Status 电子科技太学图书馆创建于1956年,馆舍总面积66974平方米,各 ...
- SSM 轻量级框架构建:图书管理系统
一.接业务,作分析 1.大致业务要求 1.1 使用 SSM( Spring MVC + Spring + MyBatis )实现图书信息管理系统, MySQL5.5 作为后台数据库,该系统包括查询图书 ...
- Kerberos+SSH安装配置使用教程
一.背景说明 最早听说KDC和Kerberos应该是大三的<应用密码学>,当时感觉这套对称密钥分发机制比非对称密钥的PKI分发机制要好理解.但几年下来由于现实中使用SSL的场景比较比(主要 ...
- 文件(图片)转base64
普通图片转base64 function getBase64(url, callback){ var canvas = document.createElement('canvas'),//创建can ...
- 页面导入样式时,使用link和@import有什么区别
link和@import两种导入样式表的方法比较 link属于HTML标签,而@import是CSS提供的 页面被加载的时候,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载 ...
- java基础-初识类
一 前言 在 <[java基础]-谈谈对面向对象理解 >一文中已经知道什么是对象,如何创建对象:这篇文章主讲对象的类型,简称类: 二 类介绍 2.1 类 每个对象都有一个类型,通常在所有的 ...
- 《Java基础知识》Java集合(Collection)
作为一个Developer,Java集合类是我们在工作中运用最多的.最频繁的类.相比于数组(Array)来说,集合类的长度可变,更加适合于现代开发需求: Java集合就像一个容器,可以存储任何类型的数 ...
- 骚年,如果你还不懂一些java常识?中了奖也无法兑换
今天下午约着几个朋友一起去看叶问4,结果碰到了一个有趣的事情,正好和java有关所以写一篇文章来记录一下. 事件:我和朋友小李.小王一起去看电影 时间:2019/12/21 地点:H市某家电影院 起因 ...