欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于SSM的全注解模式Web项目的环境搭建

程序员文章站 2024-02-25 14:51:51
...

      以往我们用SSM构建Web项目,需要一些配置文件,例如web.xml,spring-*.xml等等,servlet3.0+版本提供了基于注解模式的Web项目构建方式,省去了配置文件。本文主要描述了基于注解方式的Web项目环境搭建。

      既然去掉了配置文件,那么我们需要编写一些配置类,来代替配置文件,构建起基本的项目环境,下面是Web项目基本环境的搭建:

import java.io.IOException;

import javax.sql.DataSource;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import com.alibaba.druid.pool.DruidDataSource;


@Configuration
@PropertySource("classpath:configs.properties")
public class AppRootConfig {
	
	
	public AppRootConfig() {
		System.out.println("AppRootConfig");
	}

	@Bean
	public DruidDataSource getDataSource(
			@Value("${jdbcDriver}")String driver,
			@Value("${jdbcUrl}")String url,
			@Value("${jdbcUser}")String username,
			@Value("${jdbcPassword}")String password){
		DruidDataSource ds=new DruidDataSource();
		ds.setDriverClassName(driver);
		ds.setUrl(url);
		ds.setUsername(username);
		ds.setPassword(password);
		return ds;
	}
	
	@Bean("sqlSessionFactory")
	public SqlSessionFactoryBean getFactory(@Autowired DataSource ds) throws IOException{
		SqlSessionFactoryBean factory=new SqlSessionFactoryBean();
		factory.setDataSource(ds);
		ResourcePatternResolver resolver=new PathMatchingResourcePatternResolver();
		Resource[] mapperLocations=resolver.getResources("classpath:mapper/*.xml");
		factory.setMapperLocations(mapperLocations);
		return factory;
	}
	
	@Bean
	public MapperScannerConfigurer getScanner(){
		MapperScannerConfigurer scanner=new MapperScannerConfigurer();
		scanner.setBasePackage("com.jt.**.dao");
		scanner.setSqlSessionFactoryBeanName("sqlSessionFactory");
		return scanner;
	}
}

这里首先@Configuration表示这是一个配置类,然后加载了一个configs.properties文件,内部定义了数据库连接的相关配置。类中首先利用阿里开发的druid连接池获取数据库连接,接着基于此连接获取了Mybatis中的关键对象sqlSessionFactory,这是Spring关于Mybatis部份的整合,最后注册了一个扫描dao包的扫描器,dao包中用于存放数据持久层的接口,而扫描器扫描后,可以生成这个接口相对应的bean对象,不需要我们再调用getMapper()方法手动获取。

      基本环境搭建完毕,我们需要搭建Servlet环境:

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@ComponentScan("com.jt")
@EnableWebMvc
public class AppServletConfig extends WebMvcConfigurerAdapter{
	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		registry.jsp("/WEB-INF/pages/", ".html");
	}
}

这里首先同样表明它是一个配置类,然后@ComponentScan("com.jt")表示扫描这个包下的所有组件,即包含有类似@Controller,@Configuration,@Bean等注解的部分。@EnaleWebMvc表示启用WebMvc的相关注解和默认配置。这个类继承了WebMvcConfigurerAdapter,从名字可以看出这是一个关于WebMvc配置的类,可以通过重写父类方法的方式为当前项目进行配置。类中加载了一个视图解析器,视图文件的路径是/WEB-INF/pages,文件的类型是.html文件。此外这个类中还可以通过重写addInterceptors()方法添加拦截器。

      配置类准备就绪,既然作为配置类,那么肯定是要在项目启动时就生效,那么怎样让我们的配置类在服务器启动时就自动加载呢?找到下图中的文件,打开以后找到文件中的那个类org.springframework.web.SpringServletContainerInitializer,

基于SSM的全注解模式Web项目的环境搭建基于SSM的全注解模式Web项目的环境搭建

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {

	
	
	@Override
	public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
			throws ServletException {

		List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();

		if (webAppInitializerClasses != null) {
			for (Class<?> waiClass : webAppInitializerClasses) {
				// Be defensive: Some servlet containers provide us with invalid classes,
				// no matter what @HandlesTypes says...
				if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
						WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
					try {
						initializers.add((WebApplicationInitializer) waiClass.newInstance());
					}
					catch (Throwable ex) {
						throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
					}
				}
			}
		}

		if (initializers.isEmpty()) {
			servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
			return;
		}

		servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
		AnnotationAwareOrderComparator.sort(initializers);
		for (WebApplicationInitializer initializer : initializers) {
			initializer.onStartup(servletContext);
		}
	}

}

这个类上的注释@HandlesTypes(WebApplicationInitializer.class),服务器启动时,spring会通过这个类中的onStartup()方法加载WebApplicationInitializer这个接口及其子类,那么我们只需要写一个类实现这个接口,再把我们需要启动时加载的部分放在这个类中即可。

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class AppWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[]{AppRootConfig.class};
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class[]{AppServletConfig.class};
	}

	@Override
	protected String[] getServletMappings() {
		return new String[]{"*.do"};
	}

}

      AbstractAnnotationConfigDispatcherServletInitializer 是WebApplicationInitializer接口的一个实现类,我们写了一个雷,继承了这个实现类,并重写了其中的关键方法,加载了本项目中的配置类。最后的*.do规定了客户端访问时,需要以.do结尾,才能通过前端控制器。