springboot整合springmvc

学习springmvc和springboot的自动配置我们必须对springmvc的组件足够了解,起码知道怎么用。Springmvc的组件基本都被springboot来做了自动的配置。

一、springboot的自动解管理

中央转发器(DispatcherServlet)

控制器

视图解析器

静态资源访问

消息转换器

格式化

静态资源管理

1.中央转换器

以前需要配置的xml现在无需配置

中央转发器被springboot自动接管,不再需要我们在web.xml中配置,我们现在的项目也不是web项目,也不存在web.xml,

复制代码
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\

2.控制器

控制器Controller在springboot的注解扫描范围内自动管理。

扫描的过程,为什么能被扫描到?

springboot里面有一个注解:@SpringBootApplication,这个注解的底层注解替我完成了一些事情:只要保证控制器所在的位置和启动类在同包或其子包下加上扫描注解就能被扫描到,为什么,因为@SpringBootApplication里面有一个注解@ComponentScan,但是这个注解只能达到扫描的作用,得提前告诉这个注解扫描谁,谁来告诉他,@ComponentScan里面有一个excludeFilters,过滤器,去排查我应该扫描哪些包,底层通过反射的方式拿到启动类所在的包,那么就会把启动类所在包及其子包下的所有东西扫描到,替换掉了原始方式的spring在配置文件里配置ComponentScan指定路径的方式

3.视图解析器自动管理

视图解析器原来也是在springmvc的配置文件里配置的:

xml 复制代码
<bean id="de" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"></property>
    <property name="suffix" value="*.jsp"></property>
</bean>

源码:

java 复制代码
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
    ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
    resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
    resolver.setOrder(Integer.MIN_VALUE);
    return resolver;
}

靠它来形成的视图解析器,视图解析器的前缀后缀来源于thymeleaf的模板引擎:

这里配置的前缀后缀

java 复制代码
@ConfigurationProperties(
    prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {
    private static final Charset DEFAULT_ENCODING;
    public static final String DEFAULT_PREFIX = "classpath:/templates/";
    public static final String DEFAULT_SUFFIX = ".html";
    private boolean checkTemplate = true;
    private boolean checkTemplateLocation = true;
    private String prefix = "classpath:/templates/";
    private String suffix = ".html";
    private String mode = "HTML";
    private Charset encoding;
    private boolean cache;
    private Integer templateResolverOrder;
    private String[] viewNames;
    private String[] excludedViewNames;
    private boolean enableSpringElCompiler;
    private boolean renderHiddenMarkersBeforeCheckboxes;
    private boolean enabled;
    private final Servlet servlet;
    private final Reactive reactive;

做文件上传的时候也会发现multipartResolver是自动被配置好的页面:

文件上传大小可以通过配置来修改

4.静态资源访问

springboot会默认将以下路径作为静态资源的目录

复制代码
"classpath:/META‐INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
"/":当前项目的根路径

5.消息转换和格式化

(1)Springboot自动配置了消息转换器

java 复制代码
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
java 复制代码
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    this.messageConvertersProvider.ifAvailable((customConverters) -> {
        converters.addAll(customConverters.getConverters());
    });
}

打个断点:

也就是说消息转换器有10个

(2)格式化转换器的自动注册

java 复制代码
public void addFormatters(FormatterRegistry registry) {
    ApplicationConversionService.addBeans(registry, this.beanFactory);
}

可以在配置文件里修改时间类型

6.欢迎页面的自动配置

Springboot自动指定resources下的index.html

二、.springboot扩展springmvc

在实际开发中,springboot提供了很多自动配置的功能,简化了很多配置和开发工作,但它并非完全自动化,很多业务需要自己扩展,springboot提供了接口

1.通过实现WebMvcConfigurer接口来扩展

java 复制代码
public interface WebMvcConfigurer {
    default void configurePathMatch(PathMatchConfigurer configurer) {
    }
	//配置内容裁决的一些参数
    default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    }

    default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
    }
	//默认静态资源处理器
    default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    }
    //格式化
    default void addFormatters(FormatterRegistry registry) {
    }
	//拦截器
    default void addInterceptors(InterceptorRegistry registry) {
    }
	//静态资源
    default void addResourceHandlers(ResourceHandlerRegistry registry) {
    }
	//跨域
    default void addCorsMappings(CorsRegistry registry) {
    }
	//页面跳转
    default void addViewControllers(ViewControllerRegistry registry) {
    }
	//视图解析器
    default void configureViewResolvers(ViewResolverRegistry registry) {
    }

    default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
    }

    default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
    }
	//信息转换器
    default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    }

    default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    }

    default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }

    default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }

    @Nullable
    default Validator getValidator() {
        return null;
    }

    @Nullable
    default MessageCodesResolver getMessageCodesResolver() {
        return null;
    }
}

2.在容器中注册视图控制器(请求转发)

创建一个MyMVCCofnig实现WebMvcConfigurer接口,实现一下addViewControllers方法,我们完成通过/tx访问,转发到hei.html的工作

MyMVCCofnig

java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyMVCCofnig implements WebMvcConfigurer {
    //视图控制器(请求转发)
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/tx").setViewName("hei");
    }
}

hei.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
hello
</body>
</html>

运行

3.注册格式化器

用来可以对请求过来的日期格式化的字符串来做定制化,通过application.properties配置也可以办到。

java 复制代码
//注册格式化器
@Override
public void addFormatters(FormatterRegistry registry) {
    registry.addFormatter(new Formatter<Date>() {
        @Override
        public String print(Date date, Locale locale) {
            return null;
        }
        @Override
        public Date parse(String s, Locale locale) throws ParseException {
            return new SimpleDateFormat("yyyy-MM-dd").parse(s);
        }
    });
}

4.消息转换器扩展fastjson

在pom文件中导入fastjson

xml 复制代码
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>

配置消息转换器,添加fastjson

java 复制代码
//配置消息转换器,添加fastjson
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    FastJsonHttpMessageConverter fc = new FastJsonHttpMessageConverter();
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
    fc.setFastJsonConfig(fastJsonConfig);
    converters.add(fc);
}

在实体类上可以继续控制

java 复制代码
public class User {
    private  String username;

    private  String password;

    private int age;

    private int score;

    private int gender;

    @JSONField(format = "yyyy-MM-dd")
    private Date date;

5.拦截器注册

以前是要先写拦截器类,再把拦截器配置到springmvc的配置文件里,现在不用了:

(1)创建拦截器

java 复制代码
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("前置拦截");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("后置拦截");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("最终拦截");
    }
}

(2)拦截器注册

java 复制代码
//拦截器注册
@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new MyInterceptor())
            .addPathPatterns("/**")
            .excludePathPatterns("/hello2");
}
相关推荐
葫芦和十三4 小时前
图解 MongoDB 21|选举与 failover:Primary 是怎么选出来的
后端·mongodb·agent
GetcharZp5 小时前
26k Star 开源内网穿透神器 NetBird,一分钟实现全球设备互联!
后端
考虑考虑5 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯6 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式
lizhongxuan8 小时前
多Agent之间的区别
后端
青石路10 小时前
记一次多JDK版本问题的排查,一坑套一坑,差点没爬上来
java
杨充10 小时前
1.面向对象设计思想
后端
IT_陈寒11 小时前
Java的Date类又坑了我一次,改用时间戳真香
前端·人工智能·后端
systemPro11 小时前
2.6亿条设备数据,历史查询从超时到50ms,我做了什么
后端
要阿尔卑斯吗11 小时前
提示词优化启示:为什么“按顺序输出“比“关键度评分“更有效
后端