基于javaConfig的无配置文件的SSM项目整合

基于javaConfig的无配置文件的SSM项目整合

pom.xml

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.fu</groupId>
    <artifactId>ssm-annotation</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <spring.version>5.1.5.RELEASE</spring.version>
        <mybatis.version>3.4.6</mybatis.version>
        <!-- log4j日志文件管理包版本 -->
        <slf4j.version>1.7.7</slf4j.version>
        <log4j.version>1.2.17</log4j.version>
        <tomcat.version>8.5.46</tomcat.version>
    </properties>

    <dependencies>
<!--    JSON    -->
        <!-- fastJson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>
        <!-- jackson  -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.1</version>
        </dependency>

<!--    servlet    -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- jstl的jar -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

<!--    Spring相关的jar    -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>

<!--    mybatis    -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>

<!--    pageHelper  -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.10</version>
        </dependency>

<!--    mysql数据库驱动    -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

<!--    数据库连接池    -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>

<!--    参数验证    -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.17.Final</version>
        </dependency>

<!--    文件上传    -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>

<!--    Tomcat    -->
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-catalina</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper</artifactId>
            <version>${tomcat.version}</version>
        </dependency>

<!--    单元测试     -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

<!--    日志相关     -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

<!--    lombok   -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <resources>
            <!--需要设置打包的文件 特别是非java文件-->
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
            </resource>
        </resources>

        <plugins>
            <!-- maven中用到的编译插件,指定编译时使用的jdk的版本 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerVersion>1.8</compilerVersion>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

AppConfig.java (spring)

package com.fu.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.*;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.Reader;
import java.util.Properties;

/**
 *  spring 配置类
 */
@Configuration
@ComponentScan(value = "com.fu", excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)})
@MapperScan("com.fu.dao")
@EnableAspectJAutoProxy // 开启 AOP 通知功能
@EnableTransactionManagement // 开启事务管理功能;
public class AppConfig {

    // 配置数据源
    @Bean
    public DataSource dataSource() {
        Properties properties = new Properties();
        try {
            Reader reader = Resources.getResourceAsReader("db.properties");
            properties.load(reader);
        } catch (IOException e) {
            e.printStackTrace();
        }
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.configFromPropety(properties);
        return druidDataSource;
    }

    // 配置和MyBatis的整合
    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        SqlSessionFactory sqlSessionFactory = null;
        // 数据源
        sqlSessionFactoryBean.setDataSource(dataSource());
        // 批量起别名
        sqlSessionFactoryBean.setTypeAliasesPackage("com.fu.bean");
        PathMatchingResourcePatternResolver pr = new PathMatchingResourcePatternResolver();
        try {
            // mapper映射文件
            sqlSessionFactoryBean.setMapperLocations(pr.getResources("classpath:/mapper/*.xml"));
            sqlSessionFactory = sqlSessionFactoryBean.getObject();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sqlSessionFactory;
    }

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

}

WebmvcConfig.java (springmvc)

package com.fu.config;

import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;
import java.util.List;

/**
 * springMVC 配置类
 */
@ComponentScan(value = "com.fu.controller")
@EnableWebMvc   // 让SpringMVC的注解和配置生效, 等同于<mvc:annotation-driven />
public class WebMvcConfig implements WebMvcConfigurer {
    /**
     *  配置视图解析器
     */
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/", ".html");
    }

    /**
     *  配置默认Servlet处理(不拦截静态资源)
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    /**
     * 配置JSON 解析器, 使用fastJson
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 字符串解析器,如果不配置这个字符串解析器,只配置json解析器,当返回值为字符串时,字符串会被转义
        converters.add(new StringHttpMessageConverter());

//      不加以下内容会抛出异常 IllegalArgumentException:内容类型不能包含通配符类型“ * ”
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        List<MediaType> supportedMediaTypes = new ArrayList<>();
        supportedMediaTypes.add(MediaType.APPLICATION_JSON);
        supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
        supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
        supportedMediaTypes.add(MediaType.APPLICATION_PDF);
        supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XML);
        supportedMediaTypes.add(MediaType.IMAGE_GIF);
        supportedMediaTypes.add(MediaType.IMAGE_JPEG);
        supportedMediaTypes.add(MediaType.IMAGE_PNG);
        supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
        supportedMediaTypes.add(MediaType.TEXT_HTML);
        supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
        supportedMediaTypes.add(MediaType.TEXT_PLAIN);
        supportedMediaTypes.add(MediaType.TEXT_XML);
        fastConverter.setSupportedMediaTypes(supportedMediaTypes);
        converters.add(fastConverter);
    }

    /**
     *  配置文件上传解析器
     */
    @Bean("multipartResolver") // name 必须是multipartResolver,否则不生效
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
        // 最大上传大小为 10m
        commonsMultipartResolver.setMaxUploadSize(1024 * 1024 * 10);
//        此为阈值,低于此值,则保存在内存中,如高于此值,则生成硬盘上的临时文件
//        commonsMultipartResolver.setMaxInMemorySize();
        commonsMultipartResolver.setDefaultEncoding("utf-8");
        return commonsMultipartResolver;
    }

    /**
     *  配置 JSR303(Bean Validation) 验证器
     */
    @Bean("messageSource")
    public MessageSource messageSource() {
        ResourceBundleMessageSource resourceBundleMessageSource = new ResourceBundleMessageSource();
        resourceBundleMessageSource.setUseCodeAsDefaultMessage(false);
        resourceBundleMessageSource.setDefaultEncoding("UTF-8");
        resourceBundleMessageSource.setBasenames("ValidationMessages");
        return resourceBundleMessageSource;
    }
    @Bean("validator")
    public LocalValidatorFactoryBean validator() {
        LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
        localValidatorFactoryBean.setProviderClass(HibernateValidator.class);
        localValidatorFactoryBean.setValidationMessageSource(messageSource());
        return localValidatorFactoryBean;
    }
    /**
     * 方法级别的单个参数验证开启
     */
    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        return new MethodValidationPostProcessor();
    }

}

RootConfig.java (WEB)

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

/**
 * web根容器配置类
 *      tomcat启动的时候会自动加载实现了 WebApplicationInitializer 接口的类,运行 onStartup 方法
 */
public class RootConfig implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        // 向web容器中注册 spring 的配置和springMVC的配置
        ac.register(AppConfig.class, WebmvcConfig.class);

        // 配置dispatcherServlet,添加web容器的配置
        DispatcherServlet dispatcherServlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcherServlet", dispatcherServlet);
        // 容器启动的时候加载该servlet
        servlet.setLoadOnStartup(1);
        // 配置dispatcherServlet的映射路径
        servlet.addMapping("/");
    }
}

Main (启动)

import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;

/**
 *  Main线程启动类
 */
public class Main {
    public static void main(String[] args) {
        Tomcat tomcat = new Tomcat();
        tomcat.setPort(8080);
        // contextPath:启动时路径资源名。
        // docBase:webapp的目录。目前只能写绝对路径,解决方法暂未找到
        tomcat.addWebapp("/ssm", "H:\\workspace\\ssm-annotation\\src\\main\\webapp");
        try {
            // 启动
            tomcat.start();
            // 线程阻塞,不阻塞的话,tomcat启动完成之后会关闭
            tomcat.getServer().await();
        } catch (LifecycleException e) {
            e.printStackTrace();
        }
    }
}

AOP 通知

package com.fu.config;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 *  通知类
 * @Aspect 告诉Spring当前类是一个切面类
 */
@Aspect
@Component
public class LogAspectsConfig {

    @Pointcut("execution(* com.fu.service..*(..))")
    public void pointCut() {}

    /*
     * JoinPoint joinPoint 连接点
     *        JoinPoint 一定要出现在参数表的第一位,否则spring识别不出来,会抛出异常
     */
    @Before("pointCut()")
    public void logBefore(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        System.out.println("logBefore..."+ joinPoint.getSignature().getName() +"方法运行...参数为:" + Arrays.toString(args));
    }

    @After("pointCut()")
    public void logAfter(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("logAfter..."+methodName+"方法运行结束...");
    }

    /*
        value = "pointCut()" 切点
        returning = "result" 返回方法运行的结果,使用一个参数(result)接收,参数和方法参数名对应
     */
    @AfterReturning(value = "pointCut()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("logAfterReturning..."+ methodName +"正常返回,返回值是:" + result);
    }

    @AfterThrowing(value = "pointCut()", throwing = "throwable")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable throwable) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("logAfterThrowing..."+ methodName +"方法出现异常,异常信息为:" + throwable);
    }

    /*
        环绕通知和异常通知同时使用,如果使用 try{}catch(){} 方式捕获异常,
            则需要把异常信息重新抛出,否则异常通知不生效(捕获不到异常)
     */
    @Around("pointCut()")
    public Object logAround(ProceedingJoinPoint point) throws Throwable {
        Object result = null;
        System.out.println("logAround...Before...");
        result = point.proceed();
        System.out.println("logAround...After...result = " + result);
        return result;
    }
}

AOP 切面方式配置事务

package com.fu.config;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;

/**
 *  AOP 切面方式配置事务
 */
@Aspect
@Component
public class TransactionAdviceConfig {
    private static final String AOP_POINTCUT_EXPRESSION = "execution(* com.fu.service..*(..))";

    @Autowired
    private PlatformTransactionManager transactionManager;

    // 配置事务拦截器
    @Bean
    public TransactionInterceptor transactionInterceptor() {
        TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
        transactionInterceptor.setTransactionManager(transactionManager);
        // 设置事务属性
        DefaultTransactionAttribute tx_REQUIRED = new DefaultTransactionAttribute();
        tx_REQUIRED.setIsolationLevel(-1);    // 事务隔离级别:默认为 ISOLATION_DEFAULT(-1)
        tx_REQUIRED.setPropagationBehavior(0);   // 事务传播行为:默认为 PROPAGATION_REQUIRED(0)
        DefaultTransactionAttribute tx_REQUIRED_READONLY = new DefaultTransactionAttribute();
        tx_REQUIRED_READONLY.setReadOnly(true);     // 是否只读,默认为 false
        // 设置 NameMatchTransactionAttributeSource 名称匹配事务属性来源
        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
        source.addTransactionalMethod("add*", tx_REQUIRED);
        source.addTransactionalMethod("save*", tx_REQUIRED);
        source.addTransactionalMethod("insert*", tx_REQUIRED);
        source.addTransactionalMethod("delete*", tx_REQUIRED);
        source.addTransactionalMethod("update*", tx_REQUIRED);
        source.addTransactionalMethod("exec*", tx_REQUIRED);
        source.addTransactionalMethod("set*", tx_REQUIRED);
        source.addTransactionalMethod("get*", tx_REQUIRED_READONLY);
        source.addTransactionalMethod("query*", tx_REQUIRED_READONLY);
        source.addTransactionalMethod("find*", tx_REQUIRED_READONLY);
        source.addTransactionalMethod("list*", tx_REQUIRED_READONLY);
        source.addTransactionalMethod("count*", tx_REQUIRED_READONLY);
        source.addTransactionalMethod("is*", tx_REQUIRED_READONLY);
        // 设置 TransactionInterceptor 事务拦截器
        transactionInterceptor.setTransactionAttributeSource(source);
        return transactionInterceptor;
    }

    // 设置切入点
    @Bean
    public Advisor txAdviceAdvisor() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
        return new DefaultPointcutAdvisor(pointcut, transactionInterceptor());
    }

}

JSR 303 验证异常解析器

package com.fu.common;

import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Iterator;

/**
 *  配置常用异常处理器
 */
@ControllerAdvice
@Component
public class CommonExceptionHandler {

    /**
     * 处理 JSR303 校验不通过异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public JsonResult constraintViolationException(ConstraintViolationException exception) {
        // 验证不通过的信息
        Iterator<ConstraintViolation<?>> iterator = exception.getConstraintViolations().iterator();
        StringBuilder str = new StringBuilder();
        while (iterator.hasNext()) {
            str.append(iterator.next().getMessage());
            str.append("\n");
        }
        System.out.println(str);
        return new JsonResult(100, str.toString());
    }
}

全局异常解析器

package com.fu.common;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *  全局异常处理器
 */
@Component
public class GlobalExceptionHandler implements HandlerExceptionResolver {


    private Logger logger = Logger.getLogger(getClass());
    /**
     * 处理所有不可知的异常,全局异常处理器,跳转到错误页面。所有未处理的异常,都会被处理。
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest,
            HttpServletResponse httpServletResponse, Object o, Exception e) {
        logger.error("Catch-exception");
        e.printStackTrace();
        return new ModelAndView("500");
    }
}
发布了21 篇原创文章 · 获赞 5 · 访问量 2056

猜你喜欢

转载自blog.csdn.net/fan521dan/article/details/103814716
今日推荐