conanan's blog conanan's blog
首页
关于
  • 分类
  • 标签
  • 归档
  • Java
  • Java Web
  • 工具

    • Maven
  • MySQL
  • Redis
  • Git
  • Vim
  • Nginx
  • Docker
GitHub

Evan Xu

前端界的小学生
首页
关于
  • 分类
  • 标签
  • 归档
  • Java
  • Java Web
  • 工具

    • Maven
  • MySQL
  • Redis
  • Git
  • Vim
  • Nginx
  • Docker
GitHub
  • Jakarta EE

    • Servlet
    • Servlet3
      • ServletContainerInitializer
      • ServletContext 注册三大组件
      • 与 SpringMVC 整合
    • Filter
    • Listener
    • JSP
  • Tomcat

  • Spring

  • SpringMVC

  • SpringBoot

  • SpringDataJPA

  • Test
  • Shiro
  • Thymeleaf
  • Java Web
  • Jakarta EE
conanan
2021-06-21

Servlet3

# Servlet 3.0 及纯注解配置

这章节就是试试,但是在纯注解配置 Mybatis 时失败,令人遗憾。

详细的查看文档,搜索 JCP 并搜 Servlet 下载即可

# ServletContainerInitializer

文档的 8.2.4 章节—Shared libraries(共享库) / runtimes pluggability(运行时可插拔性)

  1. Servlet 容器启动会扫描,当前应用里面每一个 jar 包的 ServletContainerInitializer 的实现
  2. 提供 ServletContainerInitializer 的实现类,必须绑定在 META-INF/services/javax.servlet.ServletContainerInitializer,文件的内容就是 ServletContainerInitializer 实现类的全类名

总结:容器在启动应用的时候,会扫描当前应用每一个 jar 包里面 META-INF/services/javax.servlet.==ServletContainerInitializer== 指定的实现类,启动并运行这个实现类的方法;@HandlesTypes注解用于传入感兴趣的类型。

# ServletContext 注册三大组件

//容器启动的时候会将@HandlesTypes指定的这个类型下面的子类(实现类,子接口等)传递过来;
//传入感兴趣的类型;
@HandlesTypes(value={HelloService.class})
public class MyServletContainerInitializer implements ServletContainerInitializer {

	/**
	 * 应用启动的时候,会运行onStartup方法;
	 *
	 * Set<Class<?>> arg0:感兴趣的类型的所有子类型;
	 * ServletContext arg1:代表当前Web应用的ServletContext;一个Web应用一个ServletContext;
	 *
	 * 1)、使用ServletContext注册Web组件(Servlet、Filter、Listener)
	 * 2)、使用编码的方式,在项目启动的时候给ServletContext里面添加组件;
	 * 		必须在项目启动的时候来添加;
	 * 		1)、ServletContainerInitializer得到的ServletContext;
	 * 		2)、ServletContextListener得到的ServletContext;
	 */
	@Override
	public void onStartup(Set<Class<?>> arg0, ServletContext sc) throws ServletException {
		System.out.println("感兴趣的类型:");
		for (Class<?> claz : arg0) {
			System.out.println(claz);
		}

		//注册组件  ServletRegistration
		ServletRegistration.Dynamic servlet = sc.addServlet("userServlet", new UserServlet());
		//配置servlet的映射信息
		servlet.addMapping("/user");


		//注册Listener
		sc.addListener(UserListener.class);

		//注册Filter  FilterRegistration
		FilterRegistration.Dynamic filter = sc.addFilter("userFilter", UserFilter.class);
		//配置Filter的映射信息
		filter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
	}
}
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
37
38
39

# 与 SpringMVC 整合

查看 Spring 官方文档即可

原理

1、web 容器在启动的时候,会扫描每个 jar 包下的 META-INF/services/javax.servlet.ServletContainerInitializer

2、加载这个文件指定的类 SpringServletContainerInitializer

3、spring 的应用一启动会加载感兴趣的 WebApplicationInitializer 接口的下的所有组件;

4、并且为 WebApplicationInitializer 组件创建对象(组件不是接口,不是抽象类)

1)、AbstractContextLoaderInitializer:创建根容器;createRootApplicationContext();

2)、AbstractDispatcherServletInitializer: 创建一个 web 的 ioc 容器;createServletApplicationContext(); 创建了 DispatcherServlet;createDispatcherServlet(); 将创建的 DispatcherServlet 添加到 ServletContext 中; getServletMappings();

3)、AbstractAnnotationConfigDispatcherServletInitializer:注解方式配置的 DispatcherServlet 初始化器 创建根容器:createRootApplicationContext() getRootConfigClasses();传入一个配置类 创建 web 的 ioc 容器: createServletApplicationContext(); 获取配置类;getServletConfigClasses();

总结:以注解方式来启动 SpringMVC;继承AbstractAnnotationConfigDispatcherServletInitializer;实现抽象方法指定 DispatcherServlet 等的配置信息(和在 web.xml 中功能一致);


定制 SpringMVC;

  1. @EnableWebMvc:开启 SpringMVC 定制配置功能;与<mvc:annotation-driven/>功能一致

  2. 配置组件(视图解析器、视图映射、静态资源映射、拦截器。。。)

    1. 实现WebMvcConfigurer重写全部方法!!!可以配置任何东西。不如下面的实现类方便。
    2. 继承WebMvcConfigurerAdapter(Spring5.0 后过时)
    3. 实现WebMvcConfigurer接口
//web容器启动的时候创建对象;调用方法来初始化容器以前前端控制器
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	//获取根容器的配置类;(Spring的配置文件)   父容器;
	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class<?>[]{RootConfig.class};
	}

	//获取web容器的配置类(SpringMVC配置文件)  子容器;
	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class<?>[]{AppConfig.class};
	}

	//获取DispatcherServlet的映射信息
	//  /:拦截所有请求(包括静态资源(xx.js,xx.png)),但是不包括*.jsp;
	//  /*:拦截所有请求;连*.jsp页面都拦截;jsp页面是tomcat的jsp引擎解析的;
	@Override
	protected String[] getServletMappings() {
		return new String[]{"/"};
	}

    //该方法下的所有过滤器都会映射到DispatcherServlet
    @Override
    protected Filter[] getServletFilters() {
        //编码过滤器
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter("UTF-8",true);
        //解决PUT、DELETE等请求的过滤器
        HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();

        return new Filter[]{characterEncodingFilter,hiddenHttpMethodFilter};
    }

    @Override
    protected WebApplicationContext createServletApplicationContext() {
        return super.createServletApplicationContext();
    }
}
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
37
38
39
@Configuration
@ComponentScan(value="cn.itcast",excludeFilters={
    @Filter(type=FilterType.ANNOTATION,classes={Controller.class})
})//扫描cn.itcast下的除过Controller的所有组件,不能添加useDefaultFilters
@EnableTransactionManagement//开启事务
@PropertySource("classpath:JdbcConfig.properties")//导入外部配置文件
@Configuration
public class RootConfig {

    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;


    @Bean
    public DataSource dataSource(){
        //DriverManagerDataSource dataSource = new DriverManagerDataSource();//使用spring提供的DataSource
        DruidDataSource dataSource = new DruidDataSource();//配置Druid的DataSource
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }

    //配置事务管理器
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }


   /**配置mybatis,执行后总是报NullPointerException,毫无头绪。上面的JdbcTemplate成功了

    //配置SqlSessionFactory,利用org.mybatis.spring提供的SqlSessionFactoryBean
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource){
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();

        //数据源
        sqlSessionFactoryBean.setDataSource(dataSource);

        //pageHelper的拦截器插件配置
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("helperDialect","mysql");
        properties.setProperty("reasonable","true");
        pageInterceptor.setProperties(properties);
        sqlSessionFactoryBean.setPlugins(new Interceptor[]{pageInterceptor});

        return sqlSessionFactoryBean.getObject();  //mybatis-spring整合的文档是这么写的
    }

    //配置Mapper接口扫描
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("cn.itcast.dao");
        return mapperScannerConfigurer;
    } */
}
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
@Configuration
@ComponentScan(value = "cn.itcast.controller", includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)
}, useDefaultFilters = false)//必须添加useDefaultFilters
@EnableWebMvc
public class AppConfig implements WebMvcConfigurer  {

    @Autowired
    private ApplicationContext servletApplicationContext;

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        //模板解析器
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setApplicationContext(this.servletApplicationContext);//必须有
        templateResolver.setPrefix("/templates/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode("HTML");
        templateResolver.setCharacterEncoding("UTF-8");

        //模板引擎
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);

        //Thymeleaf视图解析器
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine);
        viewResolver.setCharacterEncoding("UTF-8");

        registry.viewResolver(viewResolver);

        //registry.jsp("/views/",".jsp");
    }

    //释放静态资源
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    //拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyFirstInterceptor()).addPathPatterns("/**");
    }
}
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
37
38
39
40
41
42
43
44
45
46

以上配置,在 dao 层查询时会报空指针异常,暂时 GG。同样的 xml 配置 OK。我不 OK 了!!!

纯注解配置时由于 Maven 的原因,需要配置如下 plugin

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <warSourceDirectory>WebContent</warSourceDirectory>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
</plugin>
1
2
3
4
5
6
7
8
编辑
上次更新: 2021/06/21, 15:45:42
Servlet
Filter

← Servlet Filter→

最近更新
01
线程生命周期
07-06
02
线程安全理论
06-24
03
并发简史
06-24
更多文章>
Theme by Vdoing | Copyright © 2019-2021 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×