基于注解和配置类的SSM(Spring+SpringMVC+Mybatis)项目详细配置

在上一篇文章中介绍了使用注解和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、创建包:

创建如下:

 

可以看到,除了CityMapper.xml映射文件,在resource目录中已经不存在xml配置文件了,而dao层相关的配置都在config包下的DaoConfig.java类中

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&amp;useUnicode=true&amp;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);
    }
}
原文地址:https://www.cnblogs.com/zhangcaihua/p/12823845.html