java mvc_JavaWeb中的MVC

不使用什么MVC的案例分析:

利用Servlet与jsp实现登陆请求,数据库查询,以及页面的跳转逻辑

具体流程如下:

08435153f8ddc4e81c1dca7029dc46f1.png

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

目录结构

a1a5aff892ea4cce95b91353be8e315b.png

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

$Title$

${error}

用户名:

密码:

index.jsp

主页

你好${user},欢迎登录

增加需求

通过简单的逻辑判断和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为了满足可重用性,有更多的规范要求

图示:

c6bba3c87177b31707e7aea3396fe491.png

注意:

View与Model层之间不允许直接交互,必须由Controller来调度

Service层

按照这样的层次结构,将servlet用于Controller,在增加一个Bean类,来装载数据,看起来不错,但是没有解决根本的问题,业务逻辑和数据库操作依然挤在Servlet中,必须在对其进行拆分,于是在MVC基础结构上增加Service层,用于处理业务逻辑,你也可以叫它业务逻辑层(business)

看起来就像下面这样:

3cf11def08546e24f2b1e41f101cd254.png

你可能会问,Service属于M还是C,它既不是C也不是M,是我们在MVC基础上扩展出来的,我们经常会在已有模式上扩展新的内容这很正常

使用MVC

现在对之前的程序进行改造

增加JavaBean,其中的属性与对应的表相同,拥有ID,name,password

增加service包,并创建UserService类,用作业务逻辑层

在控制器Servlet中,调用Service来完成业务功能

根据Service的返回结果来决定页面的跳转地址

项目结构:

918d3fd89a136e2df79f67edba5c0952.png

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依然只能处理用户的登录请求

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值