6.MVC设计模式
从WEB的开发来讲主要有两种开发模型:
模型一:JSP+JavaBean(DAO);
模型二:JSP+Servlet+JavaBean,MVC设计模式。
如果使用JSP+DAO的开发最大的问题有如下几点:
JSP之中需要编写大量的Java代码,对于程序的美工维护不利。
代码的安全性不高,因为所有的业务的核心逻辑都暴露在外面了。
Servlet纯粹使用了Java编写,不适合输出HTML代码;
Servlet是一个纯粹的Java代码,调用Java程序的是最方便的;
Servlet保存在WEB-INF下,安全性是最高的。
结论:JSP里面不适合编写Java代码,但是适合于输出。Servlets适合编写Java代码,但是不适合输出。
而且Servlet对于数据的请求处理要比JSP更加的细化,并且也可以像JSP一样接收所有的请求参数,
而且可以将需要显示的内容交给JSP完成显示,利用了request属性范围。
结构分析;
对于之前利用了JSP+DAO的方式实现的用户登录操作,其结构非常简单,但是JSP页面需要完成更多的
Java调用。
最好的做法是将所有与逻辑有关的操作交给Servlet完成,假设有一个LoginServlet.
如果此时使用了Servlet进行处理,就可以避免JSP页面之中出现大量的Java逻辑,取而代之的是一些核心的
HTML或JavaScript的代码操作,这样就可以有效的实现显示与Java代码的分离。
MVC设计模式组成:
M(Model):是Java的模型,完成某些独立的功能;
V(View):是负责数据的接收与显示,主要是编写HTML代码,交由美工完成。
C(Control):接收请求参数、数据验证、调用业务层、跳转到显示页面;
避免一个JSP页面直接将请求提交给另外一个*.jsp页面。
开发分析
下面将实现一个登录程序改进,将原始的JSP+DAO的开发模式更换为MVC设计模式。
1.由于Servlet可以直接接收用户请求,所以用户就有可能没有通过前台页面,而直接
访问Servlet,为了避免这种情况出现,往往会在项目之中设置一个错误页,这个错误页指的是出现错误
时统一访问的页面;
在pages目录下建立一个errors.jsp页面,这个页面就是显示错误;
范例:定义pages/erroes.jsp页面,显示错误信息
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>出现错误</title> </head> <body> <h1>出现错误,请联系管理员</h1> </body> </html>
理论上Servlet可以跳转到任何的JSP页面,并且由于需要传递request属性范围,
使用的一定是RequestDispatcher接口实现的服务器跳转,所以这样一来就有可能出现页面路径混乱的情况。
所以为了照顾到数据传递也为了照顾到路径的资源不会因为服务器端跳转而混乱,
那么可以定义一个统一的提示信息页面:forward.jsp,在这个页面里面负责提示信息并且执行客户端跳转。
范例:定义pages/forward.jsp
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+ "://"+request.getServerName()+":" +request.getServerPort()+path; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title></title> </head> <body> <script> alert("<%=request.getAttribute("msg")%>"); window.location="<%=basePath%><%=request.getAttribute(url)%>"; </script> </body> </html>
也就是说由Servlet跳转到forward.jsp的时候必须设置两个属性:msg与url(信息提示后的路径)
建立LoginServlet.java程序,同时还是覆写doGet()和doPost()两个方法。
包名称:lxh.servlet
在web.xml文件中配置此Servlet,一定要记住,login.jsp页面在pages/back目录下,所以LoginServlet
既然为login.jsp的服务,那么就要定义在与之相同的路径下。
<servlet> <servlet-name>loginServlet</servlet-name> <servlet-class>lxh.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>loginServlet</servlet-name> <url-pattern>/pages/back/LoginServlet</url-pattern> </servlet-mapping>
开始编写LoginServlet代码,其中大部分的程序逻辑代码都可以通过check.jsp取得。
public class LoginServlet extends HttpServlet{ public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{ //首先定义一个公共的表示错误路径的页面,一般都设置为errors.jsp String path="/pages/errors.jsp"; String msg=null; String url=null;//表示的是forward.jsp提示信息后的跳转路径 //Servlet的主要功能是可以接收用户的请求数据 String code=request.getParameter("code"); //如果要取得session对象依靠request.getSession()完成; String rand=(String) request.getSession.getAttribute("rand"); //需要验证,因为Servlet可以直接通过路径访问,所以必须对数据验证 if(code!=null&&rand!=null){//通过login.jsp访问的LoginServlet if(rand.equalsIgnoreCase(code)){//验证吗通过 Admin vo=new Admin(); vo.setAid(request.getParameter("aid")); vo.setPassword(new MD5Code().getMD5ofStr(request.getParameter("password"))); try{ if(ServiceFactory.getAdminServiceInstance().login(vo)){ request.getSession().setAttribute("aid",vo.getAid()); msg="登录成功,欢迎您的光临!"; url="/pages/back/admin/index.jsp"; }else{ msg="登录失败,错误的用户名或密码!" url="/pages/back/login.jsp"; } }catch(Exception e){ e.printStackTrace(); } }else{ msg="验证码输入错误,请重新输入!"; } path="/pages/forward.jsp"; } //必须将msg与url的属性保存过去 request.setAttribute("msg",msg); request.setAttribute("url",url); //不管中间如何操作,最终的结果要想显示出来必须跳转到JSP页面上 request.getRequestDispatcher(path).forward(request,response); } public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{ this.doGet(request,response); } }
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ page import="factory"%> <%@ page import="vo"%> <%@ page import="util"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; String loginUrl=basePath+"login.jsp"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>雇员管理程序</title> <link type="text/css" rel="stylesheet" href="css/style.css"> <script src="js/test.js"></script> </head> <body> <% request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); %> <% String msg="验证错误,请重新输入"; String url=loginUrl; //首先进行验证码的判断 String code=request.getParameter("code"); String rand=(String) session.getAttribute("rand"); if(rand.equalsIgnoreCase(code)){//验证吗通过 //如果要进行检查,则必须使用MD5进行密码的加密处理 Admin vo=new Admin(); vo.setAid(request.getParameter("aid")); vo.setPassword(new MD5Code().getMD5ofStr(request.getParameter("password"))); if(ServiceFactory.getAdminServiceInstance().login(vo)){ msg="登录成功,欢迎您的光临!"; url=indexUrl; }else{ msg="登录失败,错误的用户名或密码!" url=loginUrl; } } %> <script> window.alert("<%=msg%>"); window.location="<%=url%>"; </script> </body> </html>
删除掉check.jsp页面,同时修改login.jsp页面的表单提交路径;
String loginUrl=basePath+"pages/back/LoginServlet";
此时页面只负责显示,而且有了Servlet参与之后,页面也相应减少了。
总结:
1.MVC设计模式是一个整个Java EE核心设计模式。
2.一定要清楚MVC设计模式各个组成部分的作用。