接上篇文章,上篇文中讲到了上下文与监听器的简单分析,接下来详细介绍请求与响应的细节。
ContextLoaderServlet与下文中的ContextLoaderListener功能完全相同
1
2
3
4
5
6
7
8
|
<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(重要)
1
2
3
4
5
6
7
|
/**
* A tagging interface that all event listener interfaces must extend.
* @since 1.1
*/
public interface EventListener {
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/**
* 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必然跟上线文息息相关,在初始化容器时加载配置~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@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对象里的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@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();
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/**
* 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查询,执行分析计划用到了索引
Servlet on Springboot
组件声明注解:
servletContext—ApplicationContext
组件扫描:ServletComponentScan
熟悉波~ 是不是应用跟Springboot的@ComponentScan如出一辙
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ServletComponentScanRegistrar.class)
public @interface ServletComponentScan {
/**
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
* declarations e.g.: {@code @ServletComponentScan("org.my.pkg")} instead of
* {@code @ServletComponentScan(basePackages="org.my.pkg")}.
* @return the base packages to scan
*/
@AliasFor("basePackages")
String[] value() default {};
/**
* Base packages to scan for annotated servlet components. {@link #value()} is an
* alias for (and mutually exclusive with) this attribute.
* <p>
* Use {@link #basePackageClasses()} for a type-safe alternative to String-based
* package names.
* @return the base packages to scan
*/
@AliasFor("value")
String[] basePackages() default {};
/**
* Type-safe alternative to {@link #basePackages()} for specifying the packages to
* scan for annotated servlet components. The package of each class specified will be
* scanned.
* @return classes from the base packages to scan
*/
Class<?>[] basePackageClasses() default {};
}
|
配置声明:@interface 暴露SpringBean @Bean
事件:Event
filter:
webFilter
OncePerRequestFilter:只调用一次且是线程安全的
而其子类得
ApplicationContextHeaderFilter调用的dofilter方法就是我们上面提到的真正在请求中执行的filter
激活Springbootweb
文无第一,武无第二,没有最好的技术框架或体系,只有最适合当下业务的框架或体系
谈谈你对技术的理解:天上飞的理念,必定有落地的实现
组装SpringApplicationBuilder
你看看这名字就知道他以后干啥的,并且它包含了太多太多的东西,
SpringApplication和ApplicationContext实例的生成器,基本包含了所有的SpringbootApplacation特性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
private final SpringApplication application;
private ConfigurableApplicationContext context;
private SpringApplicationBuilder parent;
AtomicBoolean是不是的看看
private final AtomicBoolean running = new AtomicBoolean(false);
private final Set<Class<?>> sources = new LinkedHashSet<>();
private final Map<String, Object> defaultProperties = new LinkedHashMap<>();
private ConfigurableEnvironment environment;
private Set<String> additionalProfiles = new LinkedHashSet<>();
private boolean registerShutdownHookApplied;
private boolean configuredAsChild = false;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
@SpringBootApplication
public class TestProfiles {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestProfiles.class)
.properties("spring.config.location=classpath:/test-profiles.yml")
.properties("spring.profiles.active=oracle")
.run(args);
// 输出变量
System.out.println(context.getEnvironment().getProperty("jdbc.driver"));
// 启动第二个Spring容器,指定端口为8848
ConfigurableApplicationContext context2 = new SpringApplicationBuilder(TestProfiles.class)
.properties("spring.config.location=classpath:/test-profiles.yml")
.properties("spring.profiles.active=mysql")
.properties("server.port=8848")
.run(args);
// 输出变量
System.out.println(context2.getEnvironment().getProperty("jdbc.driver"));
}
}
|
Springboot自动装配
/META-INF/spring.factories
XXXAotuConfigration
NIO不是异步IO而是非阻塞IO
java9推崇模块化
ClassLoader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public static void main(String[] args) {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
while (true) {
System.out.println(contextClassLoader.getClass().getName());
ClassLoader parent = contextClassLoader.getParent();
if (parent == null) {
break;
}
}
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader.getClass().getName());
}
|
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
评论(0)