当前位置: 首页 > news >正文

springboot项目配置springMVC

为什么需要配置springMVC

在Spring Boot中配置Spring MVC,实际上是为了更好地集成和使用Spring框架提供的Web开发功能。
Spring Boot本身是为了简化Spring应用的配置和部署,它内置了一些默认的配置和组件,帮助开发者快速启动应用,
而Spring MVC是Spring框架中用于构建Web应用的模块,它提供了一个全面的Web应用架构(包括控制器、视图解析、请求映射等)。

题外话:springMVC的作用

没有springMVC之前,咱们获取前端请求是通过实现servlet接口中的doget dopost实现的,如果你用过springmvc和servlet你是知道servlet是相当麻烦的,而springMVC就是基于servlet简化了我们开发人员的配置,实现解耦。

Spring Boot与Spring MVC的关系

自动配置:在Spring Boot中,当你使用spring-boot-starter-web依赖时,Spring Boot会自动配置Spring MVC相关的组件,包括DispatcherServlet,HandlerMapping,ViewResolver等。你不需要手动配置这些东西,Spring Boot会为你提供合理的默认配置。

自定义配置:虽然Spring Boot会自动配置Spring MVC,但你依然可以根据项目需求进行自定义配置。例如,可以配置自定义的视图解析器、拦截器、格式化程序等,或者使用@Configuration和@EnableWebMvc来进行更精细的控制。

这里我们常常是需要手动配置mvc

实现了 WebMvcConfigurer 接口,并且使用了 @Configuration 注解标注为配置类。它主要用来定制和配置 Spring MVC 的一些行为

@EnableWebMvc
@Configuration
@Slf4j
public class WebMvcConfigurerConfig implements WebMvcConfigurer {@ResourceRouteHandler routeHandler;@Override//该方法用来配置跨域资源共享(CORS)策略。这里的配置允许所有来源的请求访问该服务器,且允许的 HTTP 方法有:GET, POST, PUT, OPTIONS, DELETE, PATCH。//通过 .allowCredentials(true) 允许发送认证信息(如 Cookies)。//.maxAge(3600) 设置了浏览器缓存 CORS 配置的最大时间(单位为秒)。public void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowCredentials(true).allowedOriginPatterns("*").allowedHeaders("*")
//                .allowedOrigins("*").allowedMethods("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH").allowCredentials(true).maxAge(3600);}//该方法配置 HTTP 消息转换器,用于 HTTP 请求和响应的序列化与反序列化。
//ObjectMapper:用来配置 Jackson 的对象映射器,能够自定义 JSON 的序列化和反序列化行为。
//通过 simpleModule.addSerializer(Long.class, ToStringSerializer.instance) 让 Long 类型数据在转换时变成字符串。
//设置时区为 Asia/Shanghai。
//FAIL_ON_UNKNOWN_PROPERTIES 设置为 false,即在 JSON 反序列化时,遇到实体类中不存在的字段不会抛出异常。
//向 converters 列表中添加了 ByteArrayHttpMessageConverter、MappingJackson2HttpMessageConverter(处理 JSON 数据)和 StringHttpMessageConverter(处理字符串数据)。@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {ObjectMapper objectMapper = new ObjectMapper();CustomizedModule simpleModule = new CustomizedModule();simpleModule.addSerializer(Long.class, ToStringSerializer.instance);simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);objectMapper.setTimeZone(TimeZone.getTimeZone(ZoneId.of("Asia/Shanghai")));objectMapper.registerModule(simpleModule);//实体中不存在的字段反序列化时不抛出异常objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);converters.add(new ByteArrayHttpMessageConverter());converters.add(new MappingJackson2HttpMessageConverter(objectMapper));converters.add(new StringHttpMessageConverter());//ByteArrayHttpMessageConverter must precede MappingJackson2HttpMessageConverter}//该方法用来配置路径匹配规则。
//AntPathMatcher 设置了路径匹配模式,setCaseSensitive(false) 表示路径匹配不区分大小写。
//setUseTrailingSlashMatch(true) 表示匹配路径时会忽略末尾的斜杠。@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {AntPathMatcher pathMatcher = new AntPathMatcher();pathMatcher.setCaseSensitive(false);configurer.setPathMatcher(pathMatcher);configurer.setUseTrailingSlashMatch(true);}//该方法用来注册拦截器(Interceptor),它会拦截 HTTP 请求并可以进行处理前后的逻辑操作。//通过 SaInterceptor 配置了一个拦截器,使用了 SaRouter 来进行路由匹配和权限验证,确保某些路径需要特定的权限或认证。//notMatch() 方法配置了不需要拦截的路径,比如登录接口等。//check(routeHandler.check(handler)) 表示在处理请求时会执行 routeHandler 中的 check 方法来验证路由。//addPathPatterns("/**") 表示所有路径都需要通过此拦截器进行处理。//excludePathPatterns() 方法列出了不需要拦截的路径。@Overridepublic void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(authenticationInterceptor()).addPathPatterns("/**");
//        registry.addInterceptor(actionPermissionInterceptor()).addPathPatterns("/**");registry.addInterceptor(new SaInterceptor(handler -> SaRouter.notMatch("/v1/auth/login","/biz.payment/v1/auth/login").check(routeHandler.check(handler)))).addPathPatterns("/**").excludePathPatterns("/error","/swagger-ui/**","/v3/api-docs/**","/v1/allinPay/callback/**" // 通联支付回调地址);WebMvcConfigurer.super.addInterceptors(registry);}
}

对于addInterceptors的补充

HTTP 请求


是否匹配 excludePathPatterns? ➔ 是 ➔ 不触发拦截器(直接放行)
│ 否

进入 SaInterceptor 逻辑


是否匹配 SaRouter.notMatch()? ➔ 是 ➔ 跳过 check() 逻辑
│ 否

执行 check() 鉴权逻辑

下面是自己定义的check鉴权逻辑

    public SaFunction check(Object handler) {return () -> {//检测是否是通过运营平台调用的if (!checkPlatformAuthentication(handler)) {checkAuthentication(handler);}};}/*** 检测是否通过运营平台调用* 并校验是否登录* @param handler MethodHandler*/public boolean checkPlatformAuthentication(Object handler) {HttpServletRequest request = ServletUtils.getRequest();String authorization = request.getHeader(HttpHeaderConstant.AUTHORIZATION);if (StringUtils.isNotBlank(authorization)) {String[] split = authorization.split("-");if (split.length < 3) {throw ExFactory.bizException(PaymentError.INVALID_LOGIN);}String token = split[0];String identityType = split[1];String tenantId = split[2];if (StringUtils.isBlank(token) || StringUtils.isBlank(identityType) || StringUtils.isBlank(tenantId)) {throw ExFactory.bizException(PaymentError.INVALID_LOGIN);}//根据传入的token找出用户账号idString loginXAuthTokenKey = TokenRedisKeyPrefixConstant.AUTHORIZATION + token;String accountId = redisUtil.get(loginXAuthTokenKey);if(StringUtils.isBlank(accountId)){throw ExFactory.bizException(PaymentError.UN_LOGIN);}//验证通过了,则对token做延时操作Calendar calendar = new GregorianCalendar();calendar.setTime(Date.from(Instant.now()));calendar.add(Calendar.MINUTE, expireMinutes);Date dateAdd = calendar.getTime();redisUtil.expireAt(loginXAuthTokenKey, dateAdd);redisUtil.expireAt(TokenRedisKeyPrefixConstant.AUTHORIZATION_CURRENT_LOGIN_USER + accountId, dateAdd);return true;}return false;}private void checkAuthentication(Object handler) {//检测是否登录StpUtil.checkLogin();//权限校验String path = SaHolder.getRequest().getRequestPath();permissionService.checkPermission(path);//续期timeoutStpUtil.renewTimeout(timeout);}

这里的check是我们自己定义的校验逻辑

相关文章:

  • MATLAB Coder 应用:转换 MATLAB 代码至 C/C++ | 实践步骤与问题解决
  • mockMvc构建web单元测试学习笔记
  • C++学习:六个月从基础到就业——C++学习之旅:STL容器详解
  • [特殊字符]【Qt自定义控件】创意开关按钮 - 丝滑动画+自定义样式+信号交互 | 附完整源码
  • OpenLDAP 管理 ELK 用户
  • PHP通讯录网站源码无需sql数据库
  • 【中级软件设计师】程序设计语言基础成分
  • 从零开始创建MCP Server实战指南
  • STM32外部中断与外设中断区别
  • Element Plus表格组件深度解析:构建高性能企业级数据视图
  • Vue2-指令语法
  • C++静态与动态联编区别解析
  • Windows安装Hadoop(图文解说版)
  • 【华为HCIP | 华为数通工程师】821—多选解析—第十二页
  • Spring中配置 Bean 的两种方式:XML 配置 和 Java 配置类
  • NDSS 2025|侧信道与可信计算攻击技术导读(二)系统化评估新旧缓存侧信道攻击技术
  • Mininet--node.py源码解析
  • ViViT: 一种视频视觉Transformer
  • Cline 之Plan和Act模式
  • [大模型]AI Agent入门01——AI Agent概念梳理
  • 美国那点事|特朗普的“刀”砍向国务院,美国霸权迎来历史拐点?
  • “电化长江”的宜昌成果:船舶航运停靠都能用电,助力一江清水向东流
  • 马上评|治理“龟速车”,也是一次驾驶文明的升级
  • 北京:义务教育阶段入学将积极为多孩家庭长幼随学创造条件
  • 男子拍摄女性视频后在网上配发诱导他人违法犯罪文字,已被警方行拘
  • 江西一季度GDP为7927.1亿元,同比增长5.7%