不使用什么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中常见模式>>
一书中讲到的;
针对web项目,MVC就是非常通用的设计模式,那如何去设计一款MVC的程序呢?
MVC分层
为了降低各个功能间的耦合度,提高代码的可维护性,MVC将程序分为了三个层次
M:Model 模型,用于作为数据的载体的Bean,通常不包含复杂逻辑,一个Bean对应数据库一条记录
V:View 视图,用于展示Model中的数据,处理用户交互,从而更新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依然只能处理用户的登录请求
follow me,seeyou next Blog;
来源:https://www.cnblogs.com/yangyuanhu/p/12039682.html