我们已经学习了两种Java服务器端技术——JSP和Servlet,比较二者的不同:
HttpServletResponse
对象动态输出HTML内容两种技术有着不同的特点,在不同的场景下有着各自的优势:
既然JSP和Servlet都有自身的适用环境,那么能否扬长避短,让它们发挥各自的优势呢?答案是肯定的——MVC(Model-View-Controller)模式非常适合解决这一问题。
MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller):
在JSP/Servlet开发的软件系统中,这三个部分的描述如下所示:
MVC模式在Web开发中的好处是非常明显,它规避了JSP与Servlet各自的短板,Servlet只负责业务逻辑而不需要动态生成HTML代码;JSP中也不会充斥着大量的Java业务代码。这大大提高了代码的可读性和可维护性。
一个成熟的Web应用可以说就是一个一个的MVC构成。比如最终的博客应用可能会是这种处理流程:
如上图所示:
那么现在我们就让JSP和Servlet双剑合璧吧!
所有的HTTP请求都应该由Servlet进行处理,业务逻辑完成后,再调用相应的JSP文件生成HTML内容并返回到浏览器。在Servlet的方法中,代码的逻辑如下:
/*进行业务逻辑操作,如获取数据*/
//Step 1: 根据你需要导向到的JSP页面(这里以view.jsp为例)创建RequestDispatcher对象
RequestDispatcher dispatcher = request.getRequestDispatcher("view.jsp");
//Step 2: 将请求转发到JSP页面
dispatcher.forward(request, response);
Servlet API中的RequestDispatcher
在这一场景下非常有用,它可以在Servlet中将请求转发(forward)到指定的JSP文件。
除了上面的基本流程,Servlet和JSP相互配合最重要的事情就是传递数据。
通常在Servlet中需要调用业务代码来完成特定的功能并获取结果,同时JSP中动态输出的HTML内容是与这些结果有关的,这就需要将Servlet中的数据传递到JSP中。
在Servlet中,使用HttpServletRequest
的setAttribute()
方法可以在当前请求中以键值对的形式存入数据:
在JSP中可以通过<%= request.getAttribute(name) %>
得到Servlet存入的数据。
还记得你之前用纯Servlet实现的博客列表页面吗?现在我们结合Servlet和JSP来实现一个更加漂亮的博客列表页面,如下图所示:
上图中动态的内容包括每一篇博客的标题、内容摘要和时间,对应Model代码在前面的练习中已经写好了,放在com.tianmaying.model
中,我们复用即可。
Controller由Servlet实现,它负责调用业务逻辑方法获取相关数据,然后将请求分发至指定JSP进行处理。修改BlogsServlet
的代码:
@WebServlet("/blogs")
public class BlogsServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Blog> blogs = blogRepository.getAll();
request.setAttribute("blogs", blogs);
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/list.jsp");
dispatcher.forward(request, response);
}
}
注意request.getRequestDispatcher("/WEB-INF/jsp/list.jsp")
中传入的参数,表示请求转发的JSP地址是/WEB-INF/jsp/list.jsp
,那么我们需要将显示博客列表的JSP页面( 即list.jsp
)放到WebContent/WEB-INF/jsp目录下。
放在WEB-INF目录下的文件,是无法直接通过浏览器访问的。比如上一个练习中,可以通过http://localhost:8080/blog/about.jsp
访问about.jsp
页面,但是http://localhost:8080/blog/WEB-INF/jsp/list.jsp
是无法访问的。所以一些不希望用户能直接访问的文件,应该放在WEB-INF目录下,这样也会更加安全。
在JSP中,就可以通过request.getAttribute("blogs")
来访问Servlet中传递来的数据了(这里只包含核心渲染逻辑代码)
<% for (Blog blog : (List<Blog>)request.getAttribute("blogs")) { %>
<div class="blog-post">
<h3 class="blog-post-title"><a href="./item.html"><%=blog.getTitle() %></a></h3>
<p class="blog-post-meta">2015年2月3日 标签:<a href="#">Web开发</a></p>
<p class="blog-post-content"><%=blog.getContent() %></p>
</div>
<hr>
<% } %>
登录发表评论 登录 注册