简单MVC理解与实现
MVC基本概念
MVC大家不陌生,包含模型(Model)、视图(View)、控制器(Controller),其中模型用于基本业务逻辑的实现,视图用于响应结果的表示,控制器用于模型控制和请求分派。先放上一张介绍MVC组件和功能的图,可以了解三个组件的关系与职能:
简单MVC实现
Servlet运行在容器(Tomcat)中,容器允许一个组件调用另一个组件。下图是《Head First Servlet&JSP》中推荐啤酒的例子,实现MVC的基本思想,其中Servlet为控制器,调用模型并得到结果信息,保存到请求对象中,然后将请求分派给JSP。
MVC调用过程:
- 客户端体请求;
- 容器接收请求,并根据请求URL和web.xml映射到对应的Servlet;
- Servlet调用对应的模型,处理实际业务逻辑;
- 模型处理完后,返回结果信息;
- Servlet将模型返回的结果作为属性值封装到请求对象中;
- 通过“请求分配”的功能,调用指定的视图(JSP等);
- 视图调用请求对象中模型返回的结果,生成页面返回给容器;
- 容器将结果反馈给客户端。
前端提交请求页面
客户端可以选择啤酒特征中的颜色作为条件进行查询,如下图:
代码实现如下,通过表单form声明以POST方式提交请求数据,并由SelectBeer.do处理:
1 <html> 2 <body> 3 <h1 align = "center">Beer Selection Page</h1> 4 <form method = "POST" 5 action = "SelectBeer.do"> 6 Select beer characteristics<p> 7 Color: 8 <select name = "color" size = "1"> 9 <option value = "light">light</option> 10 <option value = "amber">amber</option> 11 <option value = "brown">brown</option> 12 <option value = "dark">dark</option> 13 </select> 14 <br><br> 15 <center> 16 <input type = "SUBMIT"> 17 </center> 18 </form> 19 </body> 20 </html>
根据web.xml实现映射Servlet
1 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 4 http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 5 version="3.1" 6 metadata-complete="true"> 7 8 <servlet> 9 <servlet-name>Ch3 Beer</servlet-name> 10 <servlet-class>com.example.web.BeerSelect</servlet-class> 11 </servlet> 12 <servlet-mapping> 13 <servlet-name>Ch3 Beer</servlet-name> 14 <url-pattern>/SelectBeer.do</url-pattern> 15 </servlet-mapping> 16 </web-app>
一个Servlet对应三个名字:URL名、部署名和完全限定名。其中URL名是面向客户端的,由客户端进行调用;布署名是部署服务时秘密的内部名,可随意定义;完全限定名是对应真实Servlet。他们通过<servlet>和<servlet-mapping>进行映射和声明。上边URL为“/SelectBeer.do”,部署名为Ch3 Beer,安全限定名为com.example.web.BeerSelect。
接收请求的Servlet控制器
1 package com.example.web; 2 3 import javax.servlet.*; 4 import javax.servlet.http.*; 5 import java.io.*; 6 import java.util.*; 7 import com.example.model.*; 8 9 public class BeerSelect extends HttpServlet{ 10 11 public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ 12 13 String c = request.getParameter("color"); 14 BeerExport beerExport = new BeerExport(); 15 List<String> result = beerExport.getBrands(c); 16 17 request.setAttribute("styles",result); 18 19 RequestDispatcher view = request.getRequestDispatcher("result.jsp"); 20 view.forward(request,response); 21 } 22 }
BeerServlet继承自HttpServlet,可以接收HTTP请求。重写doPost方法接收表单数据、调用模型获取结果、将结果封装到请求对象中,并通过“请求分派”调用result.jsp,生成页面返回。
模型
1 package com.example.model; 2 3 import java.util.*; 4 5 public class BeerExport{ 6 7 public List<String> getBrands(String color){ 8 List<String> brands = new ArrayList<>(); 9 switch (color){ 10 case "amber": 11 brands.add("Jack Amber"); 12 brands.add("Red Moose"); 13 break; 14 default: 15 brands.add("Jail Pale Ale"); 16 brands.add("Gout Stout"); 17 break; 18 } 19 return brands; 20 } 21 }
模型就是普通类,实现具体业务逻辑。
视图
1 <%@ page import = "java.util.*" %> 2 <html> 3 </body> 4 <h1 align="center"> Beer Recommendations JSP</h1> 5 <p> 6 <% 7 List<String> brands = (List)request.getAttribute("styles"); 8 Iterator it = brands.iterator(); 9 while(it.hasNext()){ 10 out.print("<br>try: "+it.next()); 11 } 12 %> 13 </body> 14 </html>
JSP是另一种Servlet,只是将原来写在Servlet中的HTML抽离出来,在第一次请求到来时转换为Servlet进行实例化。其将调用请求对象中的模型返回结果,生成页面。
返回给客户端的页面
其中,http://localhost:8080/Beer-v1/SelectBeer.do中,Beer-v1是Web应用上下文的根。
总结
- MVC基本思想和调用过程
- 简单MVC实现
- 学习servlet相关概念:url映射、servlet实例实现等。