快速搭建SSM工程

XML文件配置SSM

创建工程

创建一个普通的maven工程,并添加SpringMVC依赖

1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.6</version>
</dependency>
</dependencies>

添加Spring配置

工程创建成功之后,首先添加 Spring 的配置文件,如下:

applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<context:component-scan base-package="com.cwz" use-default-filters="true">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

</beans>

添加SpringMVC配置

创建 springmvc 的配置文件spring-servlet.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

<context:component-scan base-package="com.cwz" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

<mvc:annotation-driven/>

</beans>

配置web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

</web-app>

测试

添加一个 HelloController进行测试

HelloController.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.cwz.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

@Autowired
HelloService helloService;

@GetMapping("/hello")
public String hello() {
String hello = helloService.hello();
System.out.println("hello = " + hello);
return "hello ssm";
}

}

HelloService.java:

1
2
3
4
5
6
7
8
9
10
11
package com.cwz.controller;

import org.springframework.stereotype.Service;

@Service
public class HelloService {
public String hello() {
return "hello service";
}
}

Java配置SSM

在Spring Boot项目中,正常来说不存在XML配置,这是因为Spring Boot不推荐使用XML,但并非不支持,Spring Boot推荐开发者使用Java配置来搭建框架。在Spring Boot中,大量的自动化配置都是Java配置来实现的。这一套实现方案,我们可以自己做,使用纯Java来搭建一个SSM环境。

环境要求:

  • 使用纯 Java 来搭建 SSM 环境,要求 Tomcat 的版本必须在 7 以上

添加依赖

1
2
3
4
5
6
7
8
9
10
11
12
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.6</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
</dependencies>

添加Spring配置

添加 Spring 的配置文件,如下

1
2
3
4
5
6
7
8
9
10
11
package com.cwz.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

@Configuration
@ComponentScan(basePackages = "com.cwz", useDefaultFilters = true, excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)})
public class SpringConfig {
}

关于这个配置:

  • @Configuration 注解表示这是一个配置类,在我们这里,这个配置的作用类似于 applicationContext.xml
  • @ComponentScan 注解表示配置包扫描,里边的属性和 xml 配置中的属性都是一一对应的,useDefaultFilters 表示使用默认的过滤器,然后又除去 Controller 注解,即在 Spring 容器中扫描除了 Controller 之外的其他所有 Bean 。

添加SpringMVC配置

1
2
3
4
5
6
7
8
9
10
11
package com.cwz.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

@Configuration
@ComponentScan(basePackages = "com.cwz", useDefaultFilters = false, includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class), @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class)})
public class SpringMVCConfig {
}

注意,如果不需要在 SpringMVC 中添加其他的额外配置,这样就可以了。即 视图解析器、JSON 解析、文件上传……等等,如果都不需要配置的话,这样就可以了。

配置web.xml

此时,我们并没有 web.xml 文件,这时,我们可以使用 Java 代码去代替 web.xml 文件,这里会用到 WebApplicationInitializer ,具体定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.cwz.config;

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

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

public class WebInit implements WebApplicationInitializer {
@Override
public void onStartup(javax.servlet.ServletContext servletContext) throws ServletException {
// 首先来加载 SpringMVC 的配置文件
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
// 添加 DispatcherServlet
ctx.register(SpringMVCConfig.class);
ServletRegistration.Dynamic springmvc = servletContext.addServlet("springmvc", new DispatcherServlet(ctx));
// 给 DispatcherServlet 添加路径映射
springmvc.addMapping("/");
// 给 DispatcherServlet 添加启动时机
springmvc.setLoadOnStartup(1);

}
}

WebInit 的作用类似于 web.xml,这个类需要实现 WebApplicationInitializer 接口,并实现接口中的方法,当项目启动时,onStartup 方法会被自动执行,我们可以在这个方法中做一些项目初始化操作,例如加载 SpringMVC 容器,添加过滤器,添加 Listener、添加 Servlet 等。

需要注意的是:

由于我们在 WebInit 中只是添加了 SpringMVC 的配置,这样项目在启动时只会去加载 SpringMVC 容器,而不会去加载 Spring 容器,如果一定要加载 Spring 容器,需要我们修改 SpringMVC 的配置,在 SpringMVC 配置的包扫描中也去扫描 @Configuration 注解,进而加载 Spring 容器 或者 直接在项目中舍弃 Spring 配置,直接将所有配置放到 SpringMVC 的配置中来完成

测试

添加一个controller:

1
2
3
4
5
6
7
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
}

其他配置

静态资源过滤

静态资源过滤在 SpringMVC 的 XML 中的配置如下:

1
<mvc:resources mapping="/**" location="/"/>

在 Java 配置的 SSM 环境中,如果要配置静态资源过滤,需要让 SpringMVC 的配置继承 WebMvcConfigurationSupport ,进而重写 WebMvcConfigurationSupport 中的方法,如下:

1
2
3
4
5
6
7
8
@Configuration
@ComponentScan(basePackages = "com.cwz")
public class SpringMVCConfig extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/");
}
}

重写 addResourceHandlers 方法,在这个方法中配置静态资源过滤,这里我将静态资源放在 resources 目录下,所以资源位置是 classpath:/ ,当然,资源也可以放在 webapp 目录下,此时只需要修改配置中的资源位置即可。如果采用 Java 来配置 SSM 环境,一般来说,可以不必使用 webapp 目录,除非要使用 JSP 做页面模板,否则可以忽略 webapp 目录。

视图解析器

在 XML 文件中,通过如下方式配置视图解析器:

1
2
3
4
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>

如果通过 Java 类配置也是可以的。

首先为我们的项目添加 webapp 目录,webapp 目录中添加一个 jsp 目录,jsp 目录中添加 jsp 文件,然后引入JSP 的依赖:

1
2
3
4
5
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>

然后,在配置类中,继续重写方法:

1
2
3
4
5
6
7
8
@Configuration
@ComponentScan(basePackages = "com.cwz")
public class SpringMVCConfig extends WebMvcConfigurationSupport {
@Override
protected void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/jsp/", ".jsp");
}
}

接下来,在 Controller 中添加控制器即可访问 JSP 页面:

1
2
3
4
5
6
7
@Controller
public class HelloController2 {
@GetMapping("/hello2")
public String hello() {
return "hello";
}
}

路径映射

有的时候,我们的控制器的作用仅仅只是一个跳转,里边没有任何业务逻辑,像这种情况,可以不用定义方法,可以直接通过路径映射来实现页面访问。如果在 XML 中配置路径映射,如下:

1
<mvc:view-controller path="/hello" view-name="hello" status-code="200"/>

这行配置,表示如果用户访问 /hello 这个路径,则直接将名为 hello 的视图返回给用户,并且响应码为 200,这个配置就可以替代 Controller 中的方法。

如果在Java类配置中:

1
2
3
4
5
6
7
8
@Configuration
@ComponentScan(basePackages = "com.cwz")
public class SpringMVCConfig extends WebMvcConfigurationSupport {
@Override
protected void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/hello3").setViewName("hello");
}
}

此时,用户访问 /hello3 接口,就能看到名为 hello 的视图文件。

JSON配置

SpringMVC 可以接收JSON 参数,也可以返回 JSON 参数,这一切依赖于 HttpMessageConverter。

HttpMessageConverter 可以将一个 JSON 字符串转为 对象,也可以将一个对象转为 JSON 字符串,实际上它的底层还是依赖于具体的 JSON 库。

所有的 JSON 库要在 SpringMVC 中自动返回或者接收 JSON,都必须提供和自己相关的 HttpMessageConverter 。

SpringMVC 中,默认提供了 Jackson 和 gson 的 HttpMessageConverter ,分别是:MappingJackson2HttpMessageConverter 和 GsonHttpMessageConverter 。

正因为如此,我们在 SpringMVC 中,如果要使用 JSON ,对于 jackson 和 gson 我们只需要添加依赖,加完依赖就可以直接使用了。具体的配置是在 AllEncompassingFormHttpMessageConverter 类中完成的。

如果开发者使用了 fastjson,那么默认情况下,SpringMVC 并没有提供 fastjson 的 HttpMessageConverter ,这个需要我们自己提供,如果是在 XML 配置中,fastjson 除了加依赖,还要显式配置 HttpMessageConverter,如下:

1
2
3
4
5
6
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
</bean>
</mvc:message-converters>
</mvc:annotation-driven>

在 Java 配置的 SSM 中,我们一样也可以添加这样的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration
@ComponentScan(basePackages = "com.cwz")
public class SpringMVCConfig extends WebMvcConfigurationSupport {
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
converter.setDefaultCharset(Charset.forName("UTF-8"));
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setCharset(Charset.forName("UTF-8"));
converter.setFastJsonConfig(fastJsonConfig);
converters.add(converter);
}
}

然后,就可以在接口中直接返回 JSON 了,此时的 JSON 数据将通过 fastjson 生成。

初始SpringBoot

我们刚开始学习 JavaWeb 的时候,使用 Servlet/JSP 做开发,一个接口搞一个 Servlet ,很头大,后来我们通过隐藏域或者反射等方式,可以减少 Servlet 的创建,但是依然不方便,再后来,我们引入 Struts2/SpringMVC 这一类的框架,来简化我们的开发 ,和 Servlet/JSP 相比,引入框架之后,生产力确实提高了不少,但是用久了,又发现了新的问题,即配置繁琐易出错,要做一个新项目,先搭建环境,环境搭建来搭建去,就是那几行配置,不同的项目,可能就是包不同,其他大部分的配置都是一样的,Java 总是被人诟病配置繁琐代码量巨大,这就是其中一个表现。那么怎么办?Spring Boot 应运而生,Spring Boot 主要提供了如下功能:

  • 为所有基于 Spring 的 Java 开发提供方便快捷的入门体验。
  • 开箱即用,有自己自定义的配置就是用自己的,没有就使用官方提供的默认的。
  • 提供了一系列通用的非功能性的功能,例如嵌入式服务器、安全管理、健康检测等
  • 没有代码生成,也不需要XML配置

创建一个 Spring Boot 项目

直接使用IntelliJ IDEA创建或者直接创建一个Maven工程。

在pom.xml中添加如下依赖:

1
2
3
4
5
6
7
8
9
10
11
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

添加成功后,再在 java 目录下创建包,包中创建一个名为 App 的启动类,如下:

1
2
3
4
5
6
7
8
9
10
11
@EnableAutoConfiguration
@RestController
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@GetMapping("/hello")
public String hello() {
return "hello";
}
}

@EnableAutoConfiguration 注解表示开启自动化配置。

然后执行这里的 main 方法就可以启动一个 Spring Boot 工程了。

@Configuration注解

@SpringBootApplication是一个组合注解,里面涉及到了@SpringBootConfiguration注解,@SpringBootConfiguration里面又是@Configuration。

@Configuration表示MyConfig类是一个配置类,在配置了中提供bean就可以了。

spring容器启动的时候会默认加载一些后置的处理器,有一个处理器是ConfigurationClassPostProcessor,这个类就是专门处理带有@Configuration注解的类。

有两个for循环,第一个for循环会找到所有带有@Configuration注解的类,把它们保存到configBeanDefs变量中。

第二个for循环实际上是对这个类做了一个增强,相当于替换了原来的class,使用了代理类。

在代理方法调用的时候涉及到BeanMethodInterceptor类的intercept方法,对于已经创建的对象就不再重复创建了。

springboot项目启动类

@SpringBootApplication注解主要包括了@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个注解。

@EnableAutoConfiguration是开启自动化配置,@ComponentScan是包扫描