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 ...
随机推荐
- 全栈项目|小书架|微信小程序-实现搜索功能
效果图 上图是小程序端实现的搜索功能效果图. 从图中可以看出点击首页搜索按钮即可进入搜索页面. 布局样式是:搜索框 + 热搜内容 + 搜索列表. 搜索框使用 lin-ui 中的 Searchbar组件 ...
- 基于webpack实现多html页面开发框架五 开发环境配置 babel配置
一.解决什么问题 1.开发环境js.css不压缩,可在浏览器选中代码调试 2.开发环境运行http服务指向打包后的文件夹 3.babel输出浏览器兼容的js代码 二.需要 ...
- Unity3d 与 Objective-C 数据交互,持续更新中
Unity 3D是用于3D游戏编程的语言,它是一个用C\C++编写的强大的库.而在游戏中经常要接入用OC编写的SDK,这就涉及到了Unity3d 和 OC之间的数据交互.XCode是完成兼容C语言的. ...
- [TimLinux] Python如何运行程序
1. Python解释器安装 访问官方网站:https://www.python.org/, 在首页标签中找到“Downloads”,根据不同的操作系统,选择相应的下载源文件即可. 2. 源码安装 在 ...
- windows系统安装git
一.下载git的安装包 git官网的下载地址:https://git-scm.com/download/win 选择自己的机型进行安装. 二.安装配置 一直点下一步就可以 安装完毕之后,打开电脑命令窗 ...
- BZOJ2809 dispatching(左偏树)
在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级.为保密,同时增强忍者们的 ...
- FlyWay工作原理
本文译自Flyway官方文档,原文地址https://flywaydb.org/getstarted/how 当你最开始将FlyWay指向一个空数据库时. 它会试着去查找schema历史表,如果此时数 ...
- layui扩展组件,下拉树多选
项目介绍 项目中需要用到下拉树多选功能,找到两个相关组件moretop-layui-select-ext和wujiawei0926-treeselect,但是moretop-layui-selec ...
- JVM系列三(垃圾收集器).
一.概述 1. 哪些内存需要回收 上篇文章 我们介绍了 Java 内存运行时区域的各个部分,其中程序计数器.虚拟机栈.本地方法栈三个区域随线程而生,随线程而灭,在这几个区域内就不需要过多考虑回收的问题 ...
- 【Java Web开发学习】Spring JPA
[Java Web开发学习]Spring JPA 转载:https://www.cnblogs.com/yangchongxing/p/10082864.html 1.使用容器管理类型的JPA JND ...