免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1230 | 回复: 0
打印 上一主题 下一主题

简单的MVC流程 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-05-06 11:46 |只看该作者 |倒序浏览
根据MVC的设计思想,自己动手做一个简单的MVC流程。从而加深对Spring MVC的理解。
我们知道MVC(Model-View-Controller)即模型-视图-控制器, Struts,Spring MVC都是采用了这种模式。
根据MVC的设计思想,一个完整的HTTP请求需要经过以下几步。
1,所有的HTTP请求都将映射到一个Servlet上。
2, Servlet根据URL选择合适的Controller来处理请求,获得返回的ModeView。
3, Servlet将Model绑定到Request中,然后交给View渲染。
4, View将渲染后的页面返回给用户,完成请求处理。
由于存在多个控制器,如果直接用Servlet作为控制器,则需要实现多个Servlet,这会导致非常复杂的配置和大量的重复代码。因此,通常将Servlet作为一个请求入口,或者称之为前置控制器,然后根据URL选择一个合适的控制器处理。
下面,我们在Eclipse中建立一个SimpleMVC项目,自己动手实现一个最简单的MVC流程.
我们知道所有的请求会映射到一个Servlet上,然后这个Servlet根据URL与控制器的映射关系在选择合适的控制器来处理。所有我们可以先抽象出一个Controller接口。所有的控制器都实现这一接口,这也面向接口编程的好习惯。
public interface Controller {
    //只有一个方法.处理请求的方法
    ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response);
}
Controller需要返回视图和将要由视图渲染的Model。视图通常是JSP页面,因此,返回JSP页面的路径即可,而Model可以简单地使用Map来实现。由于一个方法只能返回一个对象,因此,有必要将Model和View一起返回。设计ModelAndView如下。
public class ModelAndView {
    private String view;
    private Map model;
    public ModelAndView(String view, Map model) {
       this.view = view;
       this.model = model;
    }
    public String getView() {
       return view;
    }
    public Map getModel() {
       return model;
    }
}
下面设计具体的控制器。我们先设计一个LoginController,这是用来处理登录请求的控制器。
public class LoginController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest request,
           HttpServletResponse response) {
       String username = request.getParameter("username");
        String password = request.getParameter("password");
        if("123".equals(username) && "123".equals(password)) {
            // 登录成功,将转入/welcome.jsp:
            Map model = new HashMap();
            model.put("username", username);
            model.put("password", password);
            model.put("time", new Date().toString());
            return new ModelAndView("/welcome.jsp", model);
        }
        // 登录失败,将转入/loginFailed.jsp:
        Map error = new HashMap();
        error.put("message", "Login failed.");
        error.put("time", new Date().toString());
        return new ModelAndView("/loginFailed.jsp", error);
    }
}
这个控制器实现了Controller接口,当我们以
http://xxxxxx/login.do
这种请求时。
Servlet根据url映射关系(下面会说到)会调用LoginController来处理。
String username = request.getParameter("username");
取得/login.do?username=xxx这种形式传来的参数。进行用户名密码验证,如果成功就返回model(返回页面展示用的数据)和view(返回的页面名称),我们在这里用Map封装了返回的数据并和view(/welcome.jsp)一起返回给前置控制器(Servlet),最终由前置控制器来完成将页面传回给用户。
    接下来我们设计另一个控制器LogoutController,主要用来处理用户退出
public class LogoutController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest request,
           HttpServletResponse response) {
        Map model = new HashMap();
        model.put("message", "loguot success...");
        model.put("time", new Date().toString());
        // 返回的JSP视图路径是"/logout.jsp":
        return new ModelAndView("/logout.jsp", model);
    }
}
    这个控制器和上面一样,也是返回一个model和view.view其实就是返回给用户的页面。Model就是页面上要用来显示的数据。
    接下来我们设计最重要的前端控制器servlet,它主要用来处理请求转发,根择不同的url选择合适的控制器来进行处理。我们给这个控制器命保为DispatcherServlet;
public class DispatcherServlet extends HttpServlet {
    private ServletContext context;
    private Map controllers;
    //初始化DispatcherServet
    public void init(ServletConfig config) throws ServletException {
       context = config.getServletContext();
       // 将URL和对应的Controller关联起来:
       controllers = new HashMap();
       //login.do的请求将交由LoginController控制器处理
       controllers.put("/login.do", new LoginController());
       //logou.do的请求将交由LogoutController控制器处理
       controllers.put("/logout.do", new LogoutController());
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException {
       String contextPath = request.getContextPath();
       String uri = request.getRequestURI().substring(contextPath.length());
       Controller controller = controllers.get(uri);
       ModelAndView mv = controller.handleRequest(request, response);
       // 将Model绑定到Request中:
       Map model = mv.getModel();
       Set keys = model.keySet();
       for (String key : keys)
           request.setAttribute(key, model.get(key));
       // 获得JSP视图的路径:
       String jsp = mv.getView();
       // 转发给JSP视图渲染:
       context.getRequestDispatcher(jsp).forward(request, response);
      
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException {
       // POST请求的处理方式和GET一样:
       doGet(request, response);
    }
}
从代码中可以看出DispatcherServlet继承HttpServet。
里面的初始化方法中(init),创建了一个Map,controllers.put("/login.do", new LoginController());这句说明了url和控制器的映射关系。当/login.do的请求过来时。就会用LoginController来进行处理
String contextPath = request.getContextPath();
取得当前系统的路径。如你的访问是http://localhsot:8080/SampleMvc/login.do,那么会返回/SampleMvc。
String uri = request.getRequestURI().substring(contextPath.length());
request.getRequestURI()取得当前系统请求的url,如你的访问是http://localhsot:8080/SampleMvc/login.do,那么会返回/SampleMvc/login.do。
调用.substring方法后就得到了/login.do.还记得我们上面controllers.put("/login.do", new LoginController())这句吗,这样我们得到了/login.do的请求,servlet根据此关系就能知道调用那个控制器来处理了

Controller controller = controllers.get(uri);
ModelAndView mv = controller.handleRequest(request, response);
得到具体的控制器。调用控制器进行处理后返回model和view。接下来把model中的数据绑定在request中,供页面展示这此数据。
context.getRequestDispatcher(jsp).forward(request, response);返回页面给用户
web.xml中的配置
       dispatcherservlet
       com.lee.DispatcherServlet
   
   
       dispatcherservlet
       *.do
所有以.do结尾的请求都提交到DispatcherServlet,
接下来我们可以分别用
http://localhost/SampleMvc/login.do?username=123&password=123
http://localhost/SampleMvc/login.do
http://localhost/SampleMvc/logout.do
来进行测试。我们发现在根据传入不同的请求会跳到不同的控制器,返回不同的页面。这就是我们要达到的目的。通过这个实例。我想你应该对mvc更加了解了。
项目在附件中;


文件:
SampleMvc.rar
大小:
382KB
下载:
下载


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/67919/showart_677464.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP