Java自学之路-Java中级教程-13:SpringMVC的Servlet和Controller内部工作原理

在前面Web工程的web.xml中有个servlet-class标签,配置值为org.springframework.web.servlet.DispatcherServlet,这个类是springMVC的入口。

DispatcherServlet继承了FrameworkServlet,打开spring-webmvc-4.3.9.RELEASE-sources.jar,在这个类的源代码里可以看出public class DispatcherServlet extends FrameworkServlet。


FrameworkServlet又继承了HttpServlet类,并重写了两个重要的方法doGet(HttpServletRequest request, HttpServletResponse response)和doPost(HttpServletRequest request, HttpServletResponse response)。其实Servlet主要作用就是把这两个方法实现了。


@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

processRequest(request, response);
}

/**
 * Delegate POST requests to {@link #processRequest}.
 * @see #doService
 */
@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

processRequest(request, response);
}


下面我们来自定义一个Servlet类,名为PersonServlet,分别实现doGet和doPost方法。


package com.helloworld.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class PersonServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.getWriter().write("servlet get method");
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}

}
在doGet方法里,使用resp.getWriter()获得一个Writer对象,再调用.write("servlet get method")输出一个字符串。在doPost()方法里,直接再调doGet方法,也就是post请求会使用doGet的逻辑。get和post在基础教程里也提到过,两者都是http协议的请求方法,用来处理用户的请求操作。



在web.xml中加入这个新的servlet配置,在servlet标签中,servlet-name为personservlet,servlet-class为com.helloworld.servlet.PersonServlet。在servlet-mapping标签中,对应同样的servlet-name为personservlet,url-pattern为/getPerson。这里的url-pattern和Controller中的@RequestMapping都是配置要访问的url地址的。



重新部署这个Web工程,访问地址http://localhost/calculateWeb/getPerson,浏览器就会输出servlet中的信息“servlet get method”。


下面再改一下PersonServlet,把doGet中的resp.getWriter().write("servlet get method");这句去掉,换成

req.setAttribute("message", "servlet doGet");
req.getRequestDispatcher("/index.jsp").forward(req, resp);
重新部署后再访问,显示也改为了<span font-size:medium;white-space:normal;"="" style="word-wrap: break-word; margin: 0px; padding: 0px;">servlet doGet。这种req.getRequestDispatcher("/index.jsp").forward(req, resp)跳转到jsp显示的方式与前面resp.getWriter()的方式有所不同,但都做到了显示数据,只是这种方式把显示界面用jsp来实现了。


到这里可以看出,Servlet能够做到和Controller实现类似的功能。通过比较也可以看出,Spring的Controller可以更简化配置和代码编写。在没有springMVC之前,早期的Web工程很多都是用原生Servlet实现的,而springMVC框架使用一个DispatcherServlet就可以把请求分发给各个Controller对象,大大简化了Web工程的开发。


用户访问Web工程的某个url,是由DispatcherServlet调用其内部的doDispatch方法来分发请求的。DispatcherServlet的源码中,doDispatch(HttpServletRequest request, HttpServletResponse response)这个方法会调用mv = ha.handle(processedRequest, response, mappedHandler.getHandler());这个语句,跟着进入AbstractHandlerMethodAdapter的handler()方法,执行mv = ha.handle(processedRequest, response, mappedHandler.getHandler());这句,再跟着会进入RequestMappingHandlerAdapter的handleInternal()方法,执行ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod)语句。在这个handleInternal()方法里,有一句mav = invokeHandlerMethod(request, response, handlerMethod);就是把request和response对象传给Controller并调用相应的方法handlerMethod,比如这里handlerMethod就是public java.lang.String com.helloworld.controller.PersonController.helpToDo(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse),这样Java的反射机制就可以把这个PersonController的helpToDo发起执行。这个过程就是springMVC的Controller内部工作原理。


Java视频教程


猜你喜欢

转载自blog.csdn.net/weixin_41239710/article/details/80464133
今日推荐