1 环境搭建
1.1 导入maven坐标
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
1.2 spring的配置类,替代就是applicationContext.xml
package study.wyy.spring.anno.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/***
spring的配置类,替代的就是applicationContext.xml
***/
@Configuration
// 这个包扫描就不要扫描controller,controller的扫描交给spring mvc的配置类*/
@ComponentScan("study.wyy.spring.anno.service")
public class ApplicationContextConfiguration {
}
1.3 spring的配置类,替代就是springmvc.xml
- 开启注解驱动
- 配置视图解析器
- 配置静态资源
@Configuration
// 扫描web层的组件: <context:component-scan base-package="cn.wyy.springmvc.controller" />
@ComponentScan("study.wyy.spring.anno.web")
@EnableWebMvc
public class SpringMvcConfiguration implements WebMvcConfigurer {
/**
* 配置视图解析器:对应当年xml:
* <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
* <!-- 配置逻辑视图的前缀 value的值就是jsp页面的路径-->
* <property name="prefix" value="/WEB-INF/pages/" />
* <!-- 配置逻辑视图的后缀 -->
* <property name="suffix" value=".jsp" />
* </bean>
*/
@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver viewResolver= new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
/****
* <mvc:resources location="/css/" mapping="/css/**"/>
* <mvc:resources location="/js/" mapping="/js/**"/>
* <mvc:resources location="/fonts/" mapping="/fonts/**"/>
*
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/js/**","/images/**","/css/**")
.addResourceLocations("/js/","/images/","/css/")
.resourceChain(true)
.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
}
}
1.4 配置初始化项
之前在web.xml主要配置项:
- 加载spring配置文件,初始化spring容器
- 配置前端控制器,指定加载的springmvc的配置文件,配置映射规则
- 编码过滤器
现在使用Servlet3.0规范,无需web.xml,这些配置,该如何配置呢?
任何要使用Servlet3.0规范且脱离web.xml的配置,在使用时都必须在对应的jar包的META- INF/services 目录创建一个名为javax.servlet.ServletContainerInitializer的文件,文件内容指定具体的ServletContainerInitializer实现类,那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作。
spring已经为我们提供了这么一个实现类:
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer
- SpringServletContainerInitializer实现了ServletContainerInitializer接口
- 通过HandlesTypes注解指定了SpringServletContainerInitializer将会处理哪些初始化器
- WebApplicationInitializer是一个接口,他的实现类就会被传递到SpringServletContainerInitializer的onStartup方法
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException
可见,我们就可以实现WebApplicationInitializer这个接口的onStartup方法,因为这个接口的实现最终会被SpringServletContainerInitializer调用,所以我们就可以同时实现WebApplicationInitializer接口中onStartup方法的来完成之前web.xml的工作
public interface WebApplicationInitializer {
void onStartup(ServletContext servletContext) throws ServletException;
}
我们选择继承这个接口的实现类中的抽象类:AbstractDispatcherServletInitializer
AbstractDispatcherServletInitializer里面有三个抽象方法需要实现,对用的作用就是
- 加载springmvc的配置,初始化servlet容器
- 加载spring的配置,初始化spring ioc容器
- 配置前端控制器的映射规则
现在就剩下一个乱码过滤器配置了,这个就可以通过重写onStartup方法来注册乱码过滤器
代码如下:
package study.wyy.spring.anno.config;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.util.EnumSet;
/**
* @author by wyaoyao
* @Description
* @Date 2021/2/13 11:12 下午
*/
public class Config extends AbstractDispatcherServletInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
// 调用父类的onStartup
super.onStartup(servletContext);
// 创建乱码过滤器对象
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
// 设置字符集
encodingFilter.setEncoding("UTF-8");
// 添加到servlet容器中
FilterRegistration.Dynamic registration = servletContext.addFilter("encodingFilter", encodingFilter);
// 添加映射
/**
* 参数一:EnumSet<DispatcherType> dispatcherTypes: 过滤器可以处理的类型( FORWARD 转发,INCLUDE 包含,REQUEST 请求,ASYNC,ERROR 错误)
*
* 参数二:boolean isMatchAfter
* true: 表示当前过滤器会在声明的过滤器(web.xml配置的过滤球)之后执行
* false:表示当前过滤器会在声明的过滤器(web.xml配置的过滤球)之前执行,这里没有使用web.xml,也就无所谓true,false了
* 但是如果有web.xml,肯定希望乱码过滤器要在之前执行(false)
* 参数三:String... urlPatterns: url拦截规则
*
*/
registration.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.FORWARD,DispatcherType.REQUEST,DispatcherType.INCLUDE),
false,
"/*"
);
/**
对应的就是之前web.xml的这段配置
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
*/
}
/**
创建Servlet容器,创建springmvc容器
*/
@Override
protected WebApplicationContext createServletApplicationContext() {
// 由于是基于注解开发,创建注解开发对应的容器
AnnotationConfigWebApplicationContext acw = new AnnotationConfigWebApplicationContext();
// 注册配置类
acw.register(SpringMvcConfiguration.class);
return acw;
}
/**
限定前端控制器的请求映射
对应web.xml中,配置全段控制器的访问规则
<servlet-mapping>
<servlet-name>xxxxx</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
/**
创建根容器,根容器是不可以访问子容器Servlet容器的bean,也就控制了service层是不能访问controller层的bean
创建springioc容器
*/
@Override
protected WebApplicationContext createRootApplicationContext() {
// 由于是基于注解开发,创建注解开发对应的容器
AnnotationConfigWebApplicationContext acw = new AnnotationConfigWebApplicationContext();
// 注册配置类: 这就要注册spring的配置类
acw.register(ApplicationContextConfiguration.class);
return acw;
}
}
1.5 准备页面
简单准备一个index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>springMVc注解开发</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/hello">访问helloWorld</a>
</body>
</html>
位置就放在webapp下
1.6 准备一个controller
准备一个controller,对应首页中的/hello请求
package study.wyy.spring.anno.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloWorldController {
@RequestMapping("/hello")
public String hello(){
return "success";
}
}
准备一个success.jsp页面,根据配置的视图解析器,将页面放到对应的位置:/WEB-INF/pages
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Success!</h1>
</body>
</html>
整体的一个项目目录:
1.7 启动测试即可
使用idea 集成tomcat启动即可