Servlet MVC 项目实战实例

来源:互联网 发布:搜狗输入法下载 linux 编辑:程序博客网 时间:2024/05/20 03:06

    MVC的架构模式,一直是JavaEE开发中所遵循的标准,如今很多框架都已经很好的实现了MVC,像大家所熟知的Struts,SpringMVC,JSF等,但是如果没有任何框架的支持,仅仅通过JavaWeb中servlet,jsp等基本知识的运用,可以如何实现MVC的开发模式呢?本文将通过一个实例来讲解Servlet所实现的MVC架构。

    下载项目源码请点击这里:

http://download.csdn.net/download/songdeitao/6802255

    由于本项目在实现的过程中有很多建立的细节,这些都在我之前的博文中有所提及,而在此文中就直接默认所有的问题都已经解决,然后运用了JDBC轻量型封装的DAO框架,对于Servlet中文乱码的解决采取了过滤器的处理,对于Mysql可能遇到的中文乱码问题都已经解决,如果有此方面的疑惑或者问题的话,可以参考一下三篇博文:

资源引入

http://blog.csdn.net/songdeitao/article/details/17711015

http://blog.csdn.net/songdeitao/article/details/17577823

http://blog.csdn.net/songdeitao/article/details/17484635


    下面就来构建整个ServletMVC的实战项目

项目概况

    首先给出JavaWeb项目ServletMVC最终的结构,如图1所示:


              图1

    注:在这个过程中我将主要讲解基于Servlet的MVC架构的搭建过程,对于Dao的封装,mysql的sql语句,实体类的编写等我都不会提及,还请大家参照以上三个链接进行参照,最终的代码大家也可以在我分享的资源中进行下载,在这里我仅仅给出项目中相对重要的代码已经实现原理,有什么问题,我将会和大家共同解决。

    下面给出在发布到Tomcat中后,通过http://localhost:8080/ServletMVC访问后可以实现的效果,如图2所示:


                      图2

在这里,主要的操作步骤如下:

  1. 用户名,生日,会员状态填写后,点击增加信息,成功后,跳到显示所有用户界面(如果没有填写,有相应的后台验证信息),该界面有直接访问所有用户界面的链接,可以直接跳转查看所有用户信息。
  2. 在所有用户显示界面,将有修改,删除,增加用户三个操作,如果点击修改,则跳转到用户修改界面,当然当前修改的信息将直接在修改界面中显示,如果点击删除,将从数据库中删除这条信息,如果点击增加用户,则回到步骤一。
  3. 在用户修改界面,将有确认修改信息和显示所有信息两个操作,如果确认修改,将对数据库中修改的用户进行信息更新,如果显示所有信息,将执行步骤二。

    这个过程中有着action的标识的都是通过基于Servlet所实现的Controller来进行管理,也是MVC中的核心部分,下面将来讲解Servlet实现的MVC的具体原理和实现的步骤。

Servlet MVC实现

    一般情况的MVC实现,都是通过多个继承HttpServlet的类充当Controller,因此需要多个Servlet的编写,在此文中,Controller只有一个类,而通过不同的Action类来执行相应的处理操作,因此在这个过程中,具体的实现原理图如图3所示:


                        图3

在这个过程中,主要的实现原理如下讲解:

比如图2中userAddAction这个过程,

    ActionServlet是一个固定的处理方式的Controller,在方法中首先获取前端将要调用的action名字来确定指向,如userAddAction,前端就要通过userAdd.do?actionName=userAddAction的方式指向调用UserAddAction这个action类,而在ActionServlet中doPost(……)方法中,将获取actionName,即为userAddAction,而Servlet的生命周期中,init()方法是在doPost(……)方法之前执行的,而且只执行一次,这个时候因为已经将actionName对应userAddAction的实例new UserAddAction()添加到了application属性范围及web容器中(只有一个实例),所以就可以通过key->value的形式,获取要调用的action处理类UserAddAction,从而获取一个url,然后根据这个url跳转到相应的显示页面(show.jsp)。

    下面给出这个过程中用到的资源文件:

ActionServlet.java(Controller)

package com.steven.controller;import java.io.IOException;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.steven.model.UserAddAction;import com.steven.model.UserDeleteAction;import com.steven.model.UserListAction;import com.steven.model.UserModifyAction;import com.steven.model.UserUpdateAction;import com.steven.util.IModel;/** * 核心处理器类,用来接收客户端的所有请求, 根据请求调用模型实现业务逻辑的处理, 在模型处理完后根据处理结果再进行视图的转发 *  * @author Steven *  */public class ActionServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {// TODO Auto-generated method stubdoPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {// 获取请求提交的参数,该参数用来标识执行的请求处理String cmd = req.getParameter("actionName");// 根据参数获取模型的实例IModel model = (IModel) getServletContext().getAttribute(cmd);// 通过模型对象进行业务逻辑处理,返回视图路径String url = model.execute(req, resp);// 根据视图路径进行页面转发if (url != null) {req.getRequestDispatcher(url).forward(req, resp);} else {// 如果路径出错,跳转到错误页面req.getRequestDispatcher("WEB-INF/jsp/error.jsp").forward(req, resp);}}@Overridepublic void init() throws ServletException {// 获取applicationServletContext application = getServletContext();// 将业务模型的实例写入applicationapplication.setAttribute("userAddAction", new UserAddAction());application.setAttribute("userListAction", new UserListAction());application.setAttribute("userModifyAction", new UserModifyAction());application.setAttribute("userDeleteAction", new UserDeleteAction());application.setAttribute("userUpdateAction", new UserUpdateAction());}}

IModel(Model模型的接口)

IModel.java

package com.steven.util;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 模型接口,所有业务逻辑处理器都应实现该接口 *  * @author Steven *  */public interface IModel {/** * 模型接口 *  * @param request * @return */public String execute(HttpServletRequest request,HttpServletResponse resp);}

实现的Model处理器(UserAddAction)

UserAddAction.java

package com.steven.model;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.List;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.steven.dao.impl.UserDao;import com.steven.entity.User;import com.steven.util.IModel;/** * 实现统一规定的模型 *  * @author Steven *  */public class UserAddAction implements IModel {// 获得数据库操作的DAOprivate UserDao userDao;// 获取日期操作类private Calendar calendar = Calendar.getInstance();public UserAddAction() {userDao = new UserDao();}@Overridepublic String execute(HttpServletRequest request,HttpServletResponse response) {// 获取前台表单提交后的用户名String userName = request.getParameter("userName");// 生日String birthday = request.getParameter("birthday");// 是否是VIPString isVip = request.getParameter("isVip");// 进行转换VIP的boolean类型boolean isVipFlag = isVip.toLowerCase().equals("yes") ? true : false;// 年龄int age = 0;// 创建进行验证的标志信息boolean checkFlag = true;if ("".equals(userName) || userName == null) {request.setAttribute("userNameError", "请填写用户名");checkFlag = false;} else {request.setAttribute("userName", userName);}if (birthday != null && !"".equals(birthday)) {// 得到年龄age = calendar.get(Calendar.YEAR)- Integer.parseInt(birthday.substring(0, 4)) + 1;request.setAttribute("birthday", birthday);} else {checkFlag = false;// 进行后台校验request.setAttribute("birthdayError", "请选择出生日期");}// 如果有没有填的选项,则后台校验不成功,进行跳转if (!checkFlag) {return "index.jsp";}// 穿件要创建的用户User user = null;try {// 生成用户信息user = new User(userName, age, new SimpleDateFormat("yyyy-MM-dd").parse(birthday), isVipFlag);} catch (ParseException e) {e.printStackTrace();}// 将用户添加到数据库中userDao.doCreate(user);// 获取用户集合,进行显示List<User> userList = userDao.findAll();// 设置到request属性范围中request.setAttribute("userList", userList);// 设置跳转后的页面return "WEB-INF/jsp/show.jsp";}}
以及跳转后的视图show.jsp页面

show.jsp(View)

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><%@taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %><%@taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="<%=basePath%>">        <title>User Show</title>    <meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0">    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">-->  </head>    <body>  <c:if test="${not empty userList}"><table style="width: 600px; text-align: center;" cellpadding="0"cellspacing="0" border="1"><tr><th>用户名</th><th>年龄</th><th>生日</th><th>是否是会员</th><th>操作</th></tr><c:forEach items="${userList}" var="user"><tr><td>${user.userName }</td><td>${user.age }</td><td><fmt:formatDate value="${user.birthday}" pattern="yyyy-MM-dd" /></td><td><c:choose><c:when test="${user.isVip}">是</c:when><c:otherwise>不是</c:otherwise></c:choose></td><td><a href="modify.do?actionName=userModifyAction&userId=${user.userId}">修改</a><a href="delete.do?actionName=userDeleteAction&userId=${user.userId}">删除</a></td></tr></c:forEach></table><br/>  <a href="index.jsp">增加用户</a>  </c:if>  <c:if test="${empty userList}">  <h2>暂时还没有任何数据,点击<a href="index.jsp">此处</a>进行增添数据</h2>  </c:if>  </body></html>
因此这就是这个增加用户的功能所要实现的MVC封装架构,当然,对于ActionServlet需要配置web.xml

web.xml

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><%@taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %><%@taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="<%=basePath%>">        <title>User Show</title>    <meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0">    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">-->  </head>    <body>  <c:if test="${not empty userList}"><table style="width: 600px; text-align: center;" cellpadding="0"cellspacing="0" border="1"><tr><th>用户名</th><th>年龄</th><th>生日</th><th>是否是会员</th><th>操作</th></tr><c:forEach items="${userList}" var="user"><tr><td>${user.userName }</td><td>${user.age }</td><td><fmt:formatDate value="${user.birthday}" pattern="yyyy-MM-dd" /></td><td><c:choose><c:when test="${user.isVip}">是</c:when><c:otherwise>不是</c:otherwise></c:choose></td><td><a href="modify.do?actionName=userModifyAction&userId=${user.userId}">修改</a><a href="delete.do?actionName=userDeleteAction&userId=${user.userId}">删除</a></td></tr></c:forEach></table><br/>  <a href="index.jsp">增加用户</a>  </c:if>  <c:if test="${empty userList}">  <h2>暂时还没有任何数据,点击<a href="index.jsp">此处</a>进行增添数据</h2>  </c:if>  </body></html>

            这就是Servlet MVC实现的核心,其他的功能比如显示所有用户,删除用户,修改用户,所对应的action分别编写,Controller只有ActionServlet这个类,而init()方法中要将需要的actionName增加进去。

    从这里很容易看出MVC的主要优缺点

    优点:

  • Controller将Model和View分离,降低耦合度
  • ActionServlet类的重用,以及IModel的统一
  • 维护性高,以后添加相应的功能,只要照着这个模式编写即可,容易理解和编写

    缺点:

  • 这个过程都是根据具体项目实施采取的封装模式,除非使用一些现成的框架,固定住了这个模式,否则没有明确定义
  • 开发前需要准备工作,对于一些轻型开发略显繁琐,复杂性高了,效率低了
  • 所有的控制都有Controller来控制,将显得View和Controller紧密联系,重用性较低

    这就是整个Servlet MVC实现的核心,具体的代码还请参照代码资源

http://download.csdn.net/download/songdeitao/6802255

    在此恭祝大家新年快乐,学习愉快!


10 1
原创粉丝点击