5.MVC

本文详细介绍了MVC模式在Java中的应用,包括前后台交互流程、HTML模板展示及伪静态页面的实现。通过实例展示了如何使用Model-View-Controller设计思想构建动态网站并提升用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MVC流程

  • MVC , 一种常见的设计方法 。M: Model, 数据; V: View, 显示; C: Controller, 控制。 简单地说,Model负责提供数据,而View负责数据的显示。

例子:以MVC的方式来显示列表数据   

列表页模板html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>古诗文网</title>
		<link rel="stylesheet" type="text/css" href="./css/common.css"/>
	</head>
	<body>
		<div class="main">
			<div>
				<p>精选系列</p>
			</div>
			
			<#list poem as p>
				<div class="item" onclick="window.open('view.do?id=${p.id}','_self')">
					${p.title}
				</div>
			</#list>

		</div>
	</body>
</html>

后台流程: 新建 IndexPage 类,映射URL为 /index.do ,在doGet() 里,取得数据,存到model里, 将model交付给显示,利用 freemarker,将model里的数据显示在网页中。 至此,Model 和 View 分离。     http://127.0.0.1:8080/demo/index.do

@WebServlet("/index.do")
public class IndexPage extends HttpServlet
{
	protected Configuration frmkConfig;

	@Override
	public void init() throws ServletException
	{
		// 取得APP所在目录
		File appRoot = new File(getServletContext().getRealPath("/"));

		try
		{
			// 初始化FreeMarker ( 模板库 )
			frmkConfig = new Configuration(Configuration.VERSION_2_3_28);
			frmkConfig.setDirectoryForTemplateLoading(appRoot); // 指定模板根目录
			frmkConfig.setDefaultEncoding("UTF-8");
			frmkConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
			frmkConfig.setLogTemplateExceptions(false);
		} catch (Exception e)
		{
		}
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		Map<String, Object> model = new HashMap<String, Object>();
		try (SqlSession sqlSession = db.MyBatis.sqlSessionFactory.openSession())
		{
			List<Map> rows = sqlSession.selectList("ls.test.getTitleList");
			model.put("poem", rows);
		}

		String view = "index.html";

		Template tp = null;
		try
		{
			tp = frmkConfig.getTemplate(view);
		} catch (TemplateNotFoundException e)
		{
			response.sendError(404, "Cannot find view:" + view);
			return;
		}

		// 处理并返回应答
		response.setContentType("text/html");
		response.setCharacterEncoding("UTF-8");
		Writer writer = response.getWriter();

		try
		{
			tp.process(model, writer);// 输出给客户端
		} catch (TemplateException e)
		{
			e.printStackTrace();
			response.sendError(500, e.getMessage());
		} finally
		{
			writer.close();
		}

	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		doGet(request, response);
	}

}

详情页模板html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>${poem.title}-详情</title>
		<link rel="stylesheet" type="text/css" href="./css/common.css"/>
	</head>
	<body>
		<div class="main">
			 <div>标题:${poem.title}</div>
			 <div>作者:${poem.author}</div>
			 <div>朝代:${poem.dynasty}</div>
			 <div>内容:${poem.content}</div>
		</div>
	</body>
</html>

后台支持    http://127.0.0.1:8080/view.do?id=2

@WebServlet("/view.do")
public class ViewPage extends HttpServlet
{
	protected Configuration frmkConfig;

	@Override
	public void init() throws ServletException
	{
		// 取得APP所在目录
		File appRoot = new File(getServletContext().getRealPath("/"));

		try
		{
			// 初始化FreeMarker ( 模板库 )
			frmkConfig = new Configuration(Configuration.VERSION_2_3_28);
			frmkConfig.setDirectoryForTemplateLoading(appRoot); // 指定模板根目录
			frmkConfig.setDefaultEncoding("UTF-8");
			frmkConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
			frmkConfig.setLogTemplateExceptions(false);
		} catch (Exception e)
		{
		}
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		int id = Integer.valueOf(request.getParameter("id"));
		Poem poem = null;
		Map<String, Object> model = new HashMap<String, Object>();
		try (SqlSession sqlSession = db.MyBatis.sqlSessionFactory.openSession())
		{
			poem = sqlSession.selectOne("ls.test.getContent", id);
			model.put("poem", poem);
		}

		String view = "/view.html";

		Template tp = null;
		try
		{
			tp = frmkConfig.getTemplate(view);
		} catch (TemplateNotFoundException e)
		{
			response.sendError(404, "Cannot find view:" + view);
			return;
		}

		// 处理并返回应答
		response.setContentType("text/html");
		response.setCharacterEncoding("UTF-8");
		Writer writer = response.getWriter();

		try
		{
			tp.process(model, writer);// 输出给客户端
		} catch (TemplateException e)
		{
			e.printStackTrace();
			response.sendError(500, e.getMessage());
		} finally
		{
			writer.close();
		}

	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		doGet(request, response);
	}

}
  • 比较 IndexPage 和 ViewPage , 每个 MVC 流程的实现基本相同,除了 view 和 model 还有 url 的不一样。也可以发现,MVC模式下 html 比 REST 好写的多。

MVC与REST对比

REST方式下,请求两次。

MVC方式下请求一次,由后台处理数据、并生成页面返回到浏览器。 浏览器并不知道后台做了这么多事情,在它看来,它只是收到了HTML内容。 

MVC与伪静态

  • 伪静态:看url像是静态页面,实则由Servlet生成的页面。 做成伪静态页面的目的,一般是为了可以被搜索引擎收录。

使用 MVC 生成伪静态页面     http://127.0.0.1:8080/poem/2.html

比较

http://127.0.0.1:8080/view.do?id=2   之前的代码使用这一种方式,下面我们使用伪静态来实现这个页面,让它看起来像一个静态页面。

@WebServlet("/poem/*")
public class ViewPage2 extends HttpServlet
{
	protected Configuration frmkConfig;

	@Override
	public void init() throws ServletException
	{
		// 取得APP所在目录
		File appRoot = new File(getServletContext().getRealPath("/"));

		try
		{
			// 初始化FreeMarker ( 模板库 )
			frmkConfig = new Configuration(Configuration.VERSION_2_3_28);
			frmkConfig.setDirectoryForTemplateLoading(appRoot); // 指定模板根目录
			frmkConfig.setDefaultEncoding("UTF-8");
			frmkConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
			frmkConfig.setLogTemplateExceptions(false);
		} catch (Exception e)
		{
		}
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		// int id=Integer.valueOf(request.getParameter("id"));
		String contextPath = request.getServletContext().getContextPath();
		String requestUri = request.getRequestURI();
		String servletPath = requestUri.substring(contextPath.length());

		System.out.println("contextPath:" + contextPath);// /demo
		System.out.println("requestUri:" + requestUri);// /demo/poem/2.html
		System.out.println("servletPath:" + servletPath);// /poem/2.html

		// String servletPath2=request.getServletPath();// /poem
		int p1 = servletPath.lastIndexOf('/');
		int p2 = servletPath.lastIndexOf('.');
		int id = Integer.valueOf(servletPath.substring(p1 + 1, p2));
		System.out.println("id:" + id);

		Poem poem = null;
		Map<String, Object> model = new HashMap<String, Object>();
		try (SqlSession sqlSession = db.MyBatis.sqlSessionFactory.openSession())
		{
			poem = sqlSession.selectOne("ls.test.getContent", id);
			model.put("poem", poem);
		}

		String view = "/poem/view.html";
		Template tp = null;
		try
		{
			tp = frmkConfig.getTemplate(view);
		} catch (TemplateNotFoundException e)
		{
			response.sendError(404, "Cannot find view:" + view);
			return;
		}

		// 处理并返回应答
		response.setContentType("text/html");
		response.setCharacterEncoding("UTF-8");
		Writer writer = response.getWriter();

		try
		{
			tp.process(model, writer);// 输出给客户端
		} catch (TemplateException e)
		{
			e.printStackTrace();
			response.sendError(500, e.getMessage());
		} finally
		{
			writer.close();
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		doGet(request, response);
	}
}
  • 小技巧

在伪静态实现里,要注意模板文件的路径,与伪路径要一致。  

伪路径:/poem/nnn.html ,模板文件: /poem/view.html   否则,在定义模板时很不方便,相对路径乱套。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值