如果需要使用MVC相关注解,需要在Spring核心配置文件applicationContext.xml
中开启注解驱动
<!-- 开启MVC注解支持 -->
<mvc:annotation-driven></mvc:annotation-driven>
注意:@Controller
、@Service
、@Repository
等注解并非SpringMVC声明,而是由Spring声明。
@RequestMapping
注解的作用就是将请求和处理请求的控制器方法关联起来,建立映射关系。
可以用来标识类和方法,当标识类的时候,则为设置该类中所有控制器方法的基础请求路径与其他请求限制;当标识方法的时候,则为设置该控制器方法的请求路径与其他请求限制。
@Controller
@RequestMapping("/info")
public class InfoController{
@RequestMapping("/test")
public String test(){
return "test";
}
}
如上代码所示,test()
方法映射的路径为/info/test
value属性必须设置,表示通过请求路径映射,是一个字符串类型的数组,表示该请求映射能够匹配多个请求地址所对应的请求,等同于path
属性
@RequestMapping({"/info","/infomation"})
public class InfoController{}
通过请求的请求方式映射,例如常见的GET
、POST
,method属性是一个RequestMethod
类型的数组,表示该请求映射能够匹配多种请求方式的请求
若当前请求的请求地址满足请求映射的value属性,但是请求方式不满足method属性,则浏览器报错405:Request method 'POST' not supported
@RequestMapping(
value = "/testRequestMapping",
method = {RequestMethod.GET, RequestMethod.POST}
)
public String testRequestMapping(){
return "success";
}
这两个属性都是用来指定Content-Type
的
produces指定返回值类型,不仅可设置返回值类型,还可设定返回值的字符编码
consumes指定可以处理请求的提交内容类型
@RequestMapping(
value = "/pets",
method = RequestMethod.GET,
produces="application/json;charset=utf-8",
consumes="application/json"
)
通过请求的请求参数匹配请求映射,params属性是一个字符串类型的数组,可以通过四种表达式设置请求参数和请求映射的匹配关系
"param"
:要求请求映射所匹配的请求必须携带param请求参数"!param"
:要求请求映射所匹配的请求必须不能携带param请求参数"param=value"
:要求请求映射所匹配的请求必须携带param请求参数且param=value
"param!=value"
:要求请求映射所匹配的请求必须携带param请求参数但是param!=value
如果请求不满足params属性,此时页面回报错400:Parameter conditions "username, password!=123456" not met for actual request parameters: username={admin}, password={123456}
通过请求的请求头信息匹配请求映射,headers属性是一个字符串类型的数组,可以通过四种表达式设置请求头信息和请求映射的匹配关系
"header"
:要求请求映射所匹配的请求必须携带header请求头信息"!header"
:要求请求映射所匹配的请求必须不能携带header请求头信息"header=value"
:要求请求映射所匹配的请求必须携带header请求头信息且header=value
"header!=value"
:要求请求映射所匹配的请求必须携带header请求头信息且header!=value
若当前不满足headers属性,此时页面显示404错误,即资源未找到。
SpringMVC基于@RequestMapping
做为元注解派生除了特定请求方式的注解,例如@GetMapping
、@PostMapping
、@PutMapping
等,例如@GetMapping
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(
method = {RequestMethod.GET}
)
public @interface GetMapping {}
这些注解使用方式和@RequestMapping
一样,只是不可以声明在类上
是将请求参数(?
传参)和控制器方法的形参创建映射关系,作用于控制层方法形参
指定为形参赋值的请求参数的参数名
设置是否必须传输此请求参数,默认值为true
若设置为true时,则当前请求必须传输value所指定的请求参数,若没有传输该请求参数,且没有设置defaultValue属性,则页面报错400:Required String parameter 'xxx' is not present
;若设置为false,则当前请求不是必须传输value所指定的请求参数,若没有传输,则注解所标识的形参的值为null
不管required属性值为true或false,当value所指定的请求参数没有传输或传输的值为""
时,则使用默认值为形参赋值
是将请求头信息和控制器方法的形参创建映射关系,共有三个属性:value、required、defaultValue,用法同@RequestParam
是将Cookie数据和控制器方法的形参创建映射关系,共有三个属性:value、required、defaultValue,用法同@RequestParam
可以获取请求体,需要在控制器方法设置一个形参,使用@RequestBody
进行标识,当前请求的请求体就会为当前注解所标识的形参赋值,但是使用时需要额外引入HttpMessageConverter
,例如解析JSON则需要引入jackson依赖
用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体响应到浏览器
如果是对象类型,则需要配置类型转换器HttpMessageConverter
,否则可能会报500:No converter found for return value of type
,常见的就是使用jackson
@RestController注解是springMVC
提供的一个复合注解,标识在控制器的类上,就相当于为类添加了@Controller
注解,并且为其中的每个方法添加了@ResponseBody
注解
完全注解开发也就是替换掉Spring核心配置文件applicationContext.xml
以及web.xml
文件,采用配置类的方式对DispatcherServlet、Spring、SpringMVC进行配置
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 配置自动扫描注解路径 -->
<context:component-scan base-package="top.ygang.*"></context:component-scan>
<!-- 开启MVC注解支持 -->
<mvc:annotation-driven></mvc:annotation-driven>
<!--
将静态资源交给SpringMVC处理
location:指的是静态资源存放路径,多个路径可以使用逗号分隔
mapping:指的是以static开头的url资源路径
-->
<mvc:resources mapping="/static/**" location="/static/"></mvc:resources>
<!-- 视图解析器、设置controller转发、重定向路径默认前缀后缀,可选 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
context:component-scan
可以使用注解@ComponentScans
注解替换mvc:annotation-driven
可以使用SpringMVC提供的注解@EnableWebMvc
替换InternalResourceViewResolver
,可以在配置类自己往Spring容器中注入一个即可mvc:resources
,则需要依靠实现org.springframework.web.servlet.config.annotation.WebMvcConfigurer
接口的不同方法进行配置@Configuration
@ComponentScan("top.ygang.springmvc_demo")
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {
// 配置视图解析器
@Bean
public InternalResourceViewResolver internalResourceViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/");
resolver.setSuffix(".jsp");
return resolver;
}
// 配置静态资源处理方式,等价于mvc:resources
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
// 引入DelegatingWebMvcConfiguration类
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
是一个Spring MVC框架提供的注解,它的作用是启用Spring MVC框架的默认配置,例如消息转换器,格式化器和验证器等。它还启用了Spring MVC的注解驱动,这样就可以使用注解来处理HTTP请求和响应。
实现WebMvcConfigurer
接口其实是Spring MVC内部的一种配置方式,采用JavaBean
的形式来代替传统的xml
配置文件形式进行针对框架个性化定制,可以自定义一些Handler
,Interceptor
,ViewResolver
,MessageConverter
。
使用时需要创建一个配置类(使用@Configuration
注解)并实现WebMvcConfigurer
接口
在Spring Boot 1.5版本都是靠重写WebMvcConfigurerAdapter
的方法来添加自定义拦截器,消息转换器等。SpringBoot 2.0 后,该类被标记为@Deprecated
(弃用)。官方推荐直接实现WebMvcConfigurer
或者直接继承WebMvcConfigurationSupport
,
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer{
//根据需求重写方法
}
配置拦截器
addInterceptor
:需要一个实现HandlerInterceptor
接口的拦截器实例addPathPatterns
:用于设置拦截器的过滤路径规则;
addPathPatterns("/**")
对所有请求都拦截excludePathPatterns
:用于设置不需要拦截的过滤规则@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TestInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/js/**","/css/**","/images/**");
}
控制页面访问规则,例如下面,访问/infomation
即可访问/info.jsp
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/infomation").setViewName("info");
}
配置静态资源处理方式,等价于mvc:resources
addResoureHandler
:指的是对外暴露的访问路径addResourceLocations
:指的是内部文件放置的目录@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
注册一个默认的Handler:DefaultServletHttpRequestHandler
,这个Handler也是用来处理静态文件的,它会尝试映射/
。
等价于:mvc:default-servlet-handler
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
配置视图解析器,默认会自动找Spring容器中的InternalResourceViewResolver
实例
@Bean
public InternalResourceViewResolver internalResourceViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/");
resolver.setSuffix(".jsp");
return resolver;
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.viewResolver(internalResourceViewResolver());
}
配置跨越相关
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.allowCredentials(true)
.allowedHeaders("*")
.maxAge(3600);
}
配置自定义消息转换器,例如使用fastjson作为json消息转换器
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//创建fastJson消息转换器
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
//创建配置类
FastJsonConfig fastJsonConfig = new FastJsonConfig();
//修改配置返回内容的过滤
fastJsonConfig.setSerializerFeatures(
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteNullStringAsEmpty
);
fastConverter.setFastJsonConfig(fastJsonConfig);
//将fastjson添加到视图消息转换器列表内
converters.add(fastConverter);
}
在Servlet3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer
接口的类,如果找到的话就用它来配置Servlet容器。
Spring提供了这个接口的实现,名为SpringServletContainerInitializer
,这个类反过来又会查找实现WebApplicationInitializer
的类并将配置的任务交给它们来完成。Spring3.2引入了一个便利的WebApplicationInitializer
基础实现,名为AbstractAnnotationConfigDispatcherServletInitializer
,当我们的类扩展了AbstractAnnotationConfigDispatcherServletInitializer
并将其部署到Servlet3.0容器的时候,容器会自动发现它,并用它来配置Servlet上下文。
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
/**
* 指定spring的配置类
* @return
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
/**
* 指定SpringMVC的配置类
* @return
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
/**
* 指定DispatcherServlet的映射规则,即url-pattern
* @return
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
/**
* 乱码过滤器
* @return
*/
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
encodingFilter.setForceRequestEncoding(true);
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
return new Filter[]{encodingFilter, hiddenHttpMethodFilter};
}
}