private static final String METHOD_DELETE = "DELETE";
private static final String METHOD_HEAD = "HEAD";
private static final String METHOD_GET = "GET";
private static final String METHOD_OPTIONS = "OPTIONS";
private static final String METHOD_POST = "POST";
private static final String METHOD_PUT = "PUT";
private static final String METHOD_TRACE = "TRACE";
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod();
//GET
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < lastModified) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
//There's no need to override this method. 没有必要~
} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_post_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
注:在javaHttpServlet中,与Tomcat中的dopost方法如出一辙
真正的调用链(妥妥的责任链模式)是
Tomcat与SpringMVC的结合点:
(1)所有配置了路由信息的处理方法最终都是通过反射的方式进行调用的;
(2)在Java8中,反射方法调用最终落脚于NativeMethodAccessorImpl类的native方法:
private static native Object invoke0(Method var0, Object var1, Object[] var2);
在此处与JVM底层交互,实现跨代码衔接执行;
(3)观察到的比较重要的设计模式:职责链模式(ApplicationFilterChain)、委派模式(DelegatingFilterProxy)、
工厂模式、策略模式、代理模式(FilterChainProxy)、外观模式、适配器模式(HandlerAdapter);
(4)Tomcat与SpringMVC的结合点:ApplicationFilterChain与DispatcherServlet(继承于FrameworkServlet);
(5)在集成了Tomcat的SpringBoot项目中,先启动的不是Tomcat,而是Spring,Spring的工厂(默认DefaultListableBeanFactory)
读取注解完成各类Bean(WebApplicationContext、securityFilterChainRegistration、dispatcherServletRegistration、各类FilterInitializer与Filter)
的初始化,放入IoC容器,然后做路由Mapping,创建FilterChain,开启JMX等;
(6)Servlet、Filter是单实例多线程的,成员变量线程不安全,方法内局部变量线程安全;SingleThreadModel采用同步/实例池的方式来确保不会有两个线程同时执行servlet的service方法,但已被弃用,需自行确保成员变量线程安全;
————————————————
版权声明:本文为CSDN博主「wanxu12345678910」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wanxu12345678910/article/details/83352371
ContextLoaderServlet与下文中的ContextLoaderListener功能完全相同
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
HttpServletResponse响应码
监听器: 实现接口、标记
比如MQ,观察者模式,所有的时间监听都会继承 extend java.util.EventListener接口,但里面什么都没有
,称之为mark接口,经典实现:ContextLoaderListener、RequestContextListener(重要)
/**
* A tagging interface that all event listener interfaces must extend.
* @since 1.1
*/
public interface EventListener {
}
/**
* Bootstrap listener to start up and shut down Spring's root {@link WebApplicationContext}.
* Simply delegates to {@link ContextLoader} as well as to {@link ContextCleanupListener}.
*
* <p>As of Spring 3.1, {@code ContextLoaderListener} supports injecting the root web
* application context via the {@link #ContextLoaderListener(WebApplicationContext)}
* constructor, allowing for programmatic configuration in Servlet 3.0+ environments.
* See {@link org.springframework.web.WebApplicationInitializer} for usage examples.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 17.02.2003
* @see #setContextInitializers
* @see org.springframework.web.WebApplicationInitializer
*/
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
}
见名知意既然包含contextLoader必然跟上线文息息相关,在初始化容器时加载配置~
@Override
public void requestInitialized(ServletRequestEvent requestEvent) {
if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {
throw new IllegalArgumentException(
"Request is not an HttpServletRequest: " + requestEvent.getServletRequest());
}
HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();
ServletRequestAttributes attributes = new ServletRequestAttributes(request);
request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
//将请求对象放入ThreadLocal中
LocaleContextHolder.setLocale(request.getLocale());
RequestContextHolder.setRequestAttributes(attributes);
}
重要:Servlet在同一个线程中,当初始化时放到对象里,当请求销毁时,自动将Threadlocal对象销毁,防止了内存泄漏的问题
当有请求到达时,会从线程池中取出一个线程来执行任务,执行完毕后再将线程回收至线程池,这样当前请求不可能拿到上一个请求保存在ThreadLocal对象里的值
@Override
public void requestDestroyed(ServletRequestEvent requestEvent) {
ServletRequestAttributes attributes = null;
Object reqAttr = requestEvent.getServletRequest().getAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE);
if (reqAttr instanceof ServletRequestAttributes) {
attributes = (ServletRequestAttributes) reqAttr;
}
RequestAttributes threadAttributes = RequestContextHolder.getRequestAttributes();
if (threadAttributes != null) {
// We're assumably within the original request thread...
LocaleContextHolder.resetLocaleContext();
RequestContextHolder.resetRequestAttributes();
if (attributes == null && threadAttributes instanceof ServletRequestAttributes) {
attributes = (ServletRequestAttributes) threadAttributes;
}
}
if (attributes != null) {
attributes.requestCompleted();
}
}
/**
* Bootstrap listener to start up and shut down Spring's root {@link WebApplicationContext}.
* Simply delegates to {@link ContextLoader} as well as to {@link ContextCleanupListener}.
*
* <p>As of Spring 3.1, {@code ContextLoaderListener} supports injecting the root web
* application context via the {@link #ContextLoaderListener(WebApplicationContext)}
* constructor, allowing for programmatic configuration in Servlet 3.0+ environments.
* See {@link org.springframework.web.WebApplicationInitializer} for usage examples.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 17.02.2003
* @see #setContextInitializers
* @see org.springframework.web.WebApplicationInitializer
*/
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
}
插播一句:在书写过程中发现某URL响应变慢,在分析SQL时,用到了in查询,执行分析计划用到了索引