纯Javaconfig搭建SSM工程-从零搭建

浏览量2689

纯javaconfig搭建SSM工程

相信各位同用java的小伙伴对SSM传统的XML配置文件都是感觉挺麻烦的,而且不容易记忆。受广大开发者的需求,在Spring3时代,Spring推出了javaconfig,使得我们可以使用零XML的方式搭建Spring工程。而且Mybatis也可以完全使用注解开发(不过mybatis的xml方式也有他的优点)。因此,对于不喜欢使用XML配置的小伙伴们就可以完全摆脱XML的束缚,而是使用我们熟悉的java代码进行项目搭建。值得一提的是,在SpringBoot中也是大量使用javaconfig实现的自动装配。

环境要求:

  • Spring 5 + Mybatis3
  • Servlet3.0
  • Java8+

一、web.xml的javaconfig

对于传统的java项目来说web.xml是必不可少的,他是程序的入口。然而从Servlet3.0开始,我们只需要实现WebApplicationInitializer接口,当你把实现类写好之后,Servlet 3.0可以自动发现它并对servlet进行初始化(当然也可以是多个实现类),可以说这个接口的实现类一定程度上等价于web.xml的配置。

Spring WebApplicationinitializer启动过程及原理分析

maven依赖

<!-- SpringMVC依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.2.RELEASE</version>
</dependency>
<!-- Servlet依赖 -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

我们一般使用WebApplicationInitializer的实现类AbstractAnnotationConfigDispatcherServletInitializer来进行配置,配置如下:

public class SpringApplicationInitializer
        extends AbstractAnnotationConfigDispatcherServletInitializer {

    // Spring容器,相当于加载 applicationContext.xml
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{ApplicationConfig.class};
    }

    // servletContext, 相当于加载 springmvc.xml
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    // url-mapping
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    //配置与Spring相关的Filter。这里规定Spring MVC的编码为UTF-8。
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);
        return new Filter[] { characterEncodingFilter };
    }
}

二、javaconfig配置Spring

/**
 * Spring配置文件,主要用来配置Spring的Bean
 */
@EnableTransactionManagement
public class ApplicationConfig {

    /**
     * 读取配置文件
     * @return
     */
    @Bean
    public PropertySourcesPlaceholderConfigurer getTestPpc() {
        PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
        return ppc;
    }
}

Spring的配置文件相对简单,主要配置的Spring的事务管理,其中PropertySourcesPlaceholderConfigurer是在后面读取配置文件要用到的一个类,在Spring3以后被官方推荐使用。

三、javaconfig配置SpringMVC

在这里我使用了Spring官方建议的模板引擎thymeleaf,在配置过程中也是遇到了很多的坑。

thymeleaf需要引入如下maven依赖:

<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
    <version>3.0.9.RELEASE</version>
</dependency>
@Configuration
@EnableWebMvc
@ComponentScan("top.vergessen")
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public ClassLoaderTemplateResolver templateResolver(){
        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        templateResolver.setPrefix("/static/");
        templateResolver.setSuffix(".html");
        // HTML是默认值, 为了清楚起见, 在此处添加
        templateResolver.setTemplateMode(TemplateMode.HTML);
        // 默认情况下, 模板缓存为true。如果您想要设置为false
        templateResolver.setCacheable(true);
        return templateResolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine(){
        // SpringTemplateEngine自动应用SpringStandardDialect
        // 并启用Spring自己的MessageSource消息解析机制。
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        templateEngine.setEnableSpringELCompiler(true);
        return templateEngine;
    }

    /**
     * Thymeleaf中的视图和视图分解器
     */
    @Bean
    public ViewResolver viewResolver(){
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine());
        viewResolver.setCharacterEncoding("UTF-8");
        return viewResolver;
    }

    /**
     * 路径映射    访问 /hello3 跳转到 hello
     * @param registry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/hello3").setViewName("hello.html");
    }

    /**
     * 静态资源路径
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
        registry.addResourceHandler("/img/**").addResourceLocations("/img/");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/");
    }
}

编写一个Controller实验一下:

@RestController
public class HelloController {

    @GetMapping("/")
    public ModelAndView hello(){
        ModelAndView mod = new ModelAndView("hello");
        mod.addObject("hello","Hello JavaConfig!");
        return mod;
    }
}

输出结果如下

使用到的静态页面:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>
    <div th:text="${hello}"></div>
</body>
</html>

四、javaconfig配置Mybatis

在这里我使用的是国产开源的Mybatis-plus他是Mybatis的一个超集,完全适配原生Mybatis,并在Mybatis的基础上增加了免sql语句的单表增删改查,既保留了Mybatis的优点有提升了Mybatis的使用效率。

官网 视频教程 讲的很详细,没了解过的小伙伴可以入个门

maven依赖:

<!--Mybatis-Plus-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus</artifactId>
    <version>3.3.1</version>
</dependency>
<!--Mysql jdbc驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>
<!-- Spring jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.2.RELEASE</version>
</dependency>
<!--阿里巴巴开源 druid 连接池-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.22</version>
</dependency>

在这里我们使用了阿里的druid连接池

@PropertySource("classpath:jdbc.properties")读取配置文件,使用@Value注入数据

jdbc.properties:

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/ssm
jdbc.user=root
jdbc.password=root
@Configuration
@MapperScan("top.vergessen.mapper")
@PropertySource("classpath:jdbc.properties")
public class DaoConfig {  
  
    @Value("${jdbc.driverClass}")
    private String driverClass;  
  
    @Value("${jdbc.user}")  
    private String user;  
  
    @Value("${jdbc.password}")  
    private String password;  
  
    @Value("${jdbc.jdbcUrl}")  
    private String jdbcUrl;  
  
    @Bean
    public DataSource dataSource() {
        // 使用 druid 连接池
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClass);  
        dataSource.setUsername(user);  
        dataSource.setPassword(password);  
        dataSource.setUrl(jdbcUrl);  
        return dataSource;  
    }  
  
    @Bean  
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());  
    }  
  
    @Bean  
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        // 注意这里使用的是 MybatisSqlSessionFactoryBean(Mybatis-plus提供)
        MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());  
        return sessionFactory.getObject();  
    }  
}  

创建实体类Phone

@TableName("phone")
public class Phone {

    @TableId
    private long id;
    private String brand;
    private long price;
    /* getter setter略,建议使用lombok */
}

创建Mapper,Mybatis-plus的Mapper接口需要继承BaseMapper,然后就可以获得MP提供的单表增删改查能力.

public interface PhoneMapper extends BaseMapper<Phone> {
}

在Controller中添加(为了演示方便,Service层就略去了):

@Autowired
private PhoneMapper phoneMapper;

@GetMapping("phone")
public List<Phone> getPhone(){
    List<Phone> phoneList = phoneMapper.selectList(null);
    phoneList.forEach(System.out::println);
    return phoneList;
}

像上面代码一样我们直接返回java对象肯定是不行的,但是我们可以通过配置SpringMVC的消息转换器把返回的java对象自动转成JSON对象,以便于前端使用,为此我们需要引入fastjson或者其他的JSON解析器

<!-- FastJson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.58</version>
</dependency>

并在SpringMVC配置文件中添加如下代码:

/**
 * JSON 配置 使返回的java对象自动转成JSON字符串
 * @param converters
 */
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
    fastJsonConverter.setDefaultCharset(Charset.forName("UTF-8"));
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    fastJsonConfig.setCharset(Charset.forName("UTF-8"));
    fastJsonConverter.setFastJsonConfig(fastJsonConfig);
    converters.add(fastJsonConverter);
}

启动项目,运行,访问/phone(使用了Chrome的):

五、使用SpringMVC的拦截器

编写拦截器类:

public class TestInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        System.err.println(requestURI + " 正在访问...");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        String requestURI = request.getRequestURI();
        System.err.println(requestURI + " 访问中...");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        String requestURI = request.getRequestURI();
        System.err.println(requestURI + " 访问结束");
    }
}

然后在SpringMVC中注册该拦截器:

/**
 * 注册拦截器
 */
@Bean
public HandlerInterceptor handlerInterceptor(){
    return new TestInterceptor();
}

/**
 * 配置拦截器
 * @param registry
 */
@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(handlerInterceptor())
        .addPathPatterns("/**")         // 拦截的路径
        .excludePathPatterns("/"); // 不拦截的路径
}

访问/phone:

可以见到我们配置的拦截器在访问过程中的执行顺序

六、项目的运行环境

我是用的是IDEA运行本地的tomcat,配置如下:

我也有使用maven的tomcat插件,但是不知道为什么控制台打印输出的中文字符都是乱码,我进行字符集配置也没有生效,所以使用的本地tomcat进行的测试。

评论

添加一条评论