锁定老帖子 主题:简单的MVC框架流程
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-05-06
根据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<String, Object> model; public ModelAndView(String view, Map<String, Object> model) { this.view = view; this.model = model; } public String getView() { return view; } public Map<String, Object> 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<String, Object> model = new HashMap<String, Object>(); model.put("username", username); model.put("password", password); model.put("time", new Date().toString()); return new ModelAndView("/welcome.jsp", model); } // 登录失败,将转入/loginFailed.jsp: Map<String, Object> error = new HashMap<String, Object>(); 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<String, Object> model = new HashMap<String, Object>(); 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<String, Controller> controllers; //初始化DispatcherServet public void init(ServletConfig config) throws ServletException { context = config.getServletContext(); // 将URL和对应的Controller关联起来: controllers = new HashMap<String, Controller>(); //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<String, Object> model = mv.getModel(); Set<String> 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 { 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中的配置 <servlet> <servlet-name>dispatcherservlet</servlet-name> <servlet-class>com.lee.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>dispatcherservlet</servlet-name> <url-pattern>*.do</url-pattern </servlet-mapping> 接下来我们可以分别用 http://localhost/SampleMvc/login.do?username=123&password=123和 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-05-08
兄弟你太有才了。
|
|
返回顶楼 | |
发表时间:2008-05-08
貌似 “雪峰”的东西。
|
|
返回顶楼 | |
浏览 5551 次