在上一篇文章中介绍了使用注解和xml配置文件对项目进行配置,在这篇文章中将xml配置文件中的配置信息都改成使用注解或者配置类的形式。
基于注解和xml配置的SSM(Spring+SpringMVC+Mybatis)项目详细配置
第一步、配置pom.xml
在一个ssm项目中,可能需要用到的依赖比较多,在这里先列举出来:
<!-- 属性配置 --> <properties> <!-- 设置项目的编码 --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- 设置java的版本为1.8--> <java.version>1.8</java.version> <!-- 源码编译的版本为1.8--> <maven.compiler.source>1.8</maven.compiler.source> <!-- 目标字节码的版本为1.8--> <maven.compiler.target>1.8</maven.compiler.target> <!-- 指定编译器版本为1.8--> <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> <!-- 依赖的版本号 --> <spring.version>5.1.5.RELEASE</spring.version> <junit.version>4.12</junit.version> <mysql.version>5.1.47</mysql.version> <mybatis.version>3.5.2</mybatis.version> <mybatis.spring.version>2.0.3</mybatis.spring.version> <druid.version>1.1.20</druid.version> <project.version>1.0-SNAPSHOT</project.version> <servlet.version>4.0.1</servlet.version> <jackson.version>2.10.0</jackson.version> <pagehelper.version>5.1.10</pagehelper.version> <logback.version>1.2.3</logback.version> </properties> <!-- 添加依赖 --> <dependencyManagement> <dependencies> <!-- 测试 --> <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- mysql驱动 --> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- spring --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <!-- spring mvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- spring jdbc --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <!-- druid连接池 --> <!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <!-- 事务管理 --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.1.5.RELEASE</version> </dependency> <!-- mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <!-- mybatis整合插件 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${mybatis.spring.version}</version> </dependency> <!-- Jackson --> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> <!-- servlet --> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> <scope>provided</scope> </dependency> <!-- 分页插件 --> <!-- pagehelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>${pagehelper.version}</version> </dependency> <!-- 日志框架 --> <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <!-- 日志 --> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> </dependencies> </dependencyManagement>
第二步、dao层配置
在dao层中,主要就是配置连接池,mybatis和分页插件
1、创建包:
创建如下:
DaoConfig.java:在这里配置了数据源和SqlSessionFactoryBean。
/** * 标识当前类是配置类 */ @Configuration /** * 等同于配置文件中<mybatis:scan/> */ @MapperScan("edu.nf.clazz.dao") public class DaoConfig { /** * 配置 * @return * @throws SQLException */ @Bean(initMethod = "init", destroyMethod = "close") public DataSource dataSource() throws SQLException { DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&encoding=utf-8"); ds.setUsername("root"); ds.setPassword("root"); ds.setFilters("stat"); ds.setInitialSize(5); ds.setMaxActive(200); ds.setMinIdle(5); ds.setMaxWait(60000); ds.setMinEvictableIdleTimeMillis(300000); ds.setTimeBetweenEvictionRunsMillis(60000); ds.setTestWhileIdle(true); ds.setTestOnBorrow(false); ds.setPoolPreparedStatements(false); ds.setTestOnReturn(false); ds.setValidationQuery("select 1"); return ds; } @Bean public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){ SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); //注入数据源 factoryBean.setDataSource(dataSource); //设置实体包的别名 factoryBean.setTypeAliasesPackage("edu.nf.ch06.entity"); //指定mapper映射文件的路径 PathMatchingResourcePatternResolver resource = new PathMatchingResourcePatternResolver(); factoryBean.setMapperLocations(resource.getResource("classpath:mapper/CityMapper.xml")); //配置分页插件 PageInterceptor pageInterceptor = new PageInterceptor(); Properties props = new Properties(); props.setProperty("helperDialect", "mysql"); props.setProperty("supportMethodsArguments", "true"); props.setProperty("rowBoundsWithCount", "true"); pageInterceptor.setProperties(props); factoryBean.setPlugins(pageInterceptor); return factoryBean; } }
对于CityDao.java,City.java两个类和CityMapper.xml映射文件与上一篇基于配置文件的内容一致,可以查阅上一篇文章。
第三步、service层配置
1、创建包:
可以看到,使用配置类配置的话,就可以不再使用xml配置文件,可以在ServiceConfig.java类中配置,其他的包结构都不变。
ServiceConfig.java:在这个配置类中主要配置了事务管理和启用了AdpectJ注解处理器。
@Configuration @ComponentScan("edu.nf.clazz.service") @Import(DaoConfig.class) /** * 开启事务注解,等同于配置文件<tx:annotation-driven/> */ @EnableTransactionManagement /** * 启用AspectJ注解处理器,等同于xml中的<aop:aspectj-autoproxy/> * 面向切面编程 */ @EnableAspectJAutoProxy public class ServiceConfig { /** * 配置事务管理,并注入数据源 * @return * @throws SQLException */ @Bean public PlatformTransactionManager txManager(DataSource dataSource) throws SQLException { return new DataSourceTransactionManager(dataSource); } }
在这里,CityService.java、CityServiceImpl.java、DataAccessExcetption.java三个类都不变,除了CityAspect.java类我使用了另一种配置,在上面的ServiceConfig.java配置类中配置了@EnableAspectJAutoProxy注解,所以在CityAspect.java中就用注解的方式配置切面通知。(spring-study ch14-ch15)
AbstractAspect.java:
public class AbstractAspect { /** *声明一个切入点,@Pointcut标注在方法上 * execution(访问修饰符 方法返回值 包名.类名.方法名(参数类型)) * execution是切入到方法级别的 */ @Pointcut("execution(* edu.nf.clazz.service.impl.CityServiceImpl.*(..))") protected void pointcut(){ } }
CityAspect.java:
@Component /** * @Aspect:标识当前类是切面类。 */ @Aspect public class CityAspect extends AbstractAspect { /** * 前置通知 * @param jp 连接点,通过这个连接点可以获取目标方法。 * pointcut()指的是切入点注解所标注的方法名 * 想用不同的通知可以使用不同的切入点 * 如:@Before("execution(* edu.nf.clazz.service.impl.CityServiceImpl.getCity(..))") */ @Before("pointcut()") public void before(JoinPoint jp){ System.out.println("前置通知,目标方法参数:" + jp.getArgs()[0]); } /** * 环绕通知 * @param pjp * @return * @throws Throwable */ @Around("pointcut()") public Object around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("环绕通知前..."); //获取目标方法的Method对象 MethodSignature ms = (MethodSignature) pjp.getSignature(); Method method = ms.getMethod(); System.out.println("当前调用的目标方法:" + method.getName()); //调用目标方法 Object returnVal = pjp.proceed(); System.out.println("环绕通知后..."); return returnVal; } /** * 后置通知 * @param returnVal 目标对象的返回值 */ @AfterReturning(value = "pointcut()", returning = "returnVal") public void afterReturning(String returnVal){ System.out.println("后置通知,返回参数:" + returnVal); } /** * 异常通知 * @param e 目标方法产生的异常信息 */ public void afterThrowing(Throwable e){ System.out.println("异常通知:异常信息:" + e.getMessage()); } /** * 最终通知 */ @After("pointcut()") public void after(){ System.out.println("最终通知..."); } }
第四步、controller层配置
1、创建包:
MvcConfig.java:这个配置类主要配置了视图解析器和静态资源处理器
@Configuration /** * 扫描controller包 */ @ComponentScan(basePackages = "edu.nf.clazz.controller") /** * 启用mvc注解处理驱动, * 等同于配置文件中的<mvc:annotation-driver/> */ @EnableWebMvc public class MvcConfig implements WebMvcConfigurer { /** * 启用默认servlet处理静态资源 * @param configurer */ @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } /** * 配置内部资源试图解析器 * @return */ @Bean public InternalResourceViewResolver viewResolver(){ InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/jsp/"); viewResolver.setSuffix(".jsp"); return viewResolver; } }
WebInit.java:这个配置类相对于取代了web.xml配置文件,在这里可以指定父子容器的配置类、DispatcherServlet的请求映射url和动态注册Filter,这里注册了字符编码过滤器
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer { /** * 指定DaoConfig.class配置类,也就是父容器的配置类 * @return */ @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{ServiceConfig.class}; } /** * 指定spring mvc的配置类(MvcConfig.class),也就是子容器的配置类 * @return */ @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{MvcConfig.class}; } /** *指定DispatcherServlet的请求映射url * @return */ @Override protected String[] getServletMappings() { return new String[]{"/"}; } /** * onStartup中动态注册字符过滤器 * @param servletContext * @throws ServletException */ @Override public void onStartup(ServletContext servletContext) throws ServletException { //配置字符过滤器 FilterRegistration.Dynamic encodingFilter = servletContext.addFilter("encodingFilter", new CharacterEncodingFilter()); encodingFilter.setInitParameter("encoding", "utf-8"); encodingFilter.setInitParameter("forceEncoding", "true"); encodingFilter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD), false, "/*"); super.onStartup(servletContext); } }