【小家Spring】Spring MVC好用工具介绍:UrlPathHelper、WebUtils、RequestContextUtils、WebApplicationContextUtils...(下)

简介: 【小家Spring】Spring MVC好用工具介绍:UrlPathHelper、WebUtils、RequestContextUtils、WebApplicationContextUtils...(下)

WebApplicationContextUtils


当 Web 应用集成 Spring 容器后,这个工具类就可以很方便的访问出一些web组件。比如`.


  @Nullable
  public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
    return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
  }
  //Required这个方法和上面唯一的区别是:它如果返回null 就直接抛出异常了,上面是返回null
  public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc) throws IllegalStateException {
    WebApplicationContext wac = getWebApplicationContext(sc);
    if (wac == null) {
      throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
    }
    return wac;
  }
  // 我在讲解源码的时候:创建容器失败的时候,也会吧异常放进来(我们调用者一般较少使用)
  public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) { ... }
  // 这个可以说是上面的加强版。当getWebApplicationContext(sc)没找到时,还会试从ServletContext的属性中查找唯一的一个WebApplicationContext
  // 如果找到的WebApplicationContext不唯一,则抛出异常声明该情况
  public static WebApplicationContext findWebApplicationContext(ServletContext sc) { ... }
  //向WebApplicationContext使用的BeanFactory注册web有关作用域对象 :
  public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,
      @Nullable ServletContext sc) {
    beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
    beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());
    if (sc != null) {
      ServletContextScope appScope = new ServletContextScope(sc);
      beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
      // Register as ServletContext attribute, for ContextCleanupListener to detect it.
      // 此处,还吧ServletContext上下文的Scope,注册到上下文里,方便ContextCleanupListener 进行获取
      sc.setAttribute(ServletContextScope.class.getName(), appScope);
    }
    // 定义注入规则。当开发人员依赖注入ServletRequest对象时,注入的bean其实是这里的RequestObjectFactory工厂bean
    beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
    beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory());
    beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
    // ServletWebRequest 里面既有request,也有response
    beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
    if (jsfPresent) {
      FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
    }
  }


接下来看看这个方法registerEnvironmentBeans:


  public static void registerEnvironmentBeans(ConfigurableListableBeanFactory bf,
      @Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
    // 把servletContext和servletConfig以Bean的形式,注册到容器里面,这样我们就可以@Autowired了  如下面例子
    if (servletContext != null && !bf.containsBean(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME)) {
      bf.registerSingleton(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME, servletContext);
    }
        if (servletConfig != null && !bf.containsBean(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME)) {
      bf.registerSingleton(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME, servletConfig);
    }
    //这个特别特别重要:我们可以看到Spring在启动的时候,把ServletContext里面所有所有的InitParameter都拿出来了,存到一个Map里面
    // 最后把这个Bean注册到容器里面了,Bean名称为:contextParameters
    // 这就是为什么,后面我们可以非常非常方便拿到initParam的原因~~~
    if (!bf.containsBean(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME)) {
      Map<String, String> parameterMap = new HashMap<>();
      if (servletContext != null) {
        Enumeration<?> paramNameEnum = servletContext.getInitParameterNames();
        while (paramNameEnum.hasMoreElements()) {
          String paramName = (String) paramNameEnum.nextElement();
          parameterMap.put(paramName, servletContext.getInitParameter(paramName));
        }
      }
      if (servletConfig != null) {
        Enumeration<?> paramNameEnum = servletConfig.getInitParameterNames();
        while (paramNameEnum.hasMoreElements()) {
          String paramName = (String) paramNameEnum.nextElement();
          parameterMap.put(paramName, servletConfig.getInitParameter(paramName));
        }
      }
      bf.registerSingleton(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME,
          Collections.unmodifiableMap(parameterMap));
    }
    // 原理同上,这里吧ServletContext里面的contextAttributes,都以Bean的形式放进Bean容器里了
    if (!bf.containsBean(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME)) {
      Map<String, Object> attributeMap = new HashMap<>();
      if (servletContext != null) {
        Enumeration<?> attrNameEnum = servletContext.getAttributeNames();
        while (attrNameEnum.hasMoreElements()) {
          String attrName = (String) attrNameEnum.nextElement();
          attributeMap.put(attrName, servletContext.getAttribute(attrName));
        }
      }
      bf.registerSingleton(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME,
          Collections.unmodifiableMap(attributeMap));
    }
  }


因为可以看到上面已经注册了Bean,因此我们可以这么来使用,直接注入即可:


    @Autowired
    private ServletContext servletContext;
    @Autowired
    private ServletConfig servletConfig;
    @ResponseBody
    @GetMapping("/hello")
    public String helloGet() {
        System.out.println(servletContext); //org.apache.catalina.core.StandardWrapperFacade@1f3768f6
        System.out.println(servletConfig); //org.apache.catalina.core.StandardContext$NoPluggabilityServletContext@73ced3c2
        return "hello...Get";
    }
  //将 servletContext、servletConfig 添加到 propertySources
  public static void initServletPropertySources(MutablePropertySources sources,
      @Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) { ... }



UrlPathHelper


这个帮助类非常的重要了,位于包org.springframework.web.util内。它帮助Spring MVC处理URL相关的各种难题,先介绍它的几个属性~~~

public class UrlPathHelper {
  // 是否总是按照全路径 默认是false(一般不改~) 
  private boolean alwaysUseFullPath = false;
  // 是否对url进行解码(默认都是需要解码的)  解码可以是request.getCharacterEncoding()。若没指定就是下面的defaultEncoding 
  private boolean urlDecode = true;
  // 设置是否应从请求URI中删除“;”(分号)
  private boolean removeSemicolonContent = true;
  // 默认编码是它:ISO-8859-1
  private String defaultEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING;
  ...
}


它的API具体如图:


image.png


简单使用Demo如下:(我的请求地址为:http://localhost:8080/demo_war_war/api/v1/hello


    @ResponseBody
    @GetMapping("/hello")
    public String helloGet(HttpServletRequest request) throws Exception {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        System.out.println(urlPathHelper.getLookupPathForRequest(request)); // /api/v1/hello
        System.out.println(urlPathHelper.getOriginatingContextPath(request)); // /demo_war_war
        System.out.println(urlPathHelper.getContextPath(request)); // /demo_war_war
        System.out.println(urlPathHelper.getServletPath(request)); // /api/v1/hello
        System.out.println(urlPathHelper.getRequestUri(request)); // /demo_war_war/api/v1/hello
        return "hello...Get";
    }



总之它就是Spring用来处理URL的工具类,若你在你的项目中有类似的需要,也可以参考使用的。同时还有:UriUtils、UriComponents、UriComponentsBuilder等等

总结


Spring-web这个jar包内提供给我们还是有几个比较好用的类的,大家知悉即可。

特别是request的包装类,还是非常好用的~

相关文章
|
6月前
|
前端开发 Java 测试技术
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
本文介绍了 `@RequestParam` 注解的使用方法及其与 `@PathVariable` 的区别。`@RequestParam` 用于从请求中获取参数值(如 GET 请求的 URL 参数或 POST 请求的表单数据),而 `@PathVariable` 用于从 URL 模板中提取参数。文章通过示例代码详细说明了 `@RequestParam` 的常用属性,如 `required` 和 `defaultValue`,并展示了如何用实体类封装大量表单参数以简化处理流程。最后,结合 Postman 测试工具验证了接口的功能。
315 0
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
|
6月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestBody
`@RequestBody` 是 Spring 框架中的注解,用于将 HTTP 请求体中的 JSON 数据自动映射为 Java 对象。例如,前端通过 POST 请求发送包含 `username` 和 `password` 的 JSON 数据,后端可通过带有 `@RequestBody` 注解的方法参数接收并处理。此注解适用于传递复杂对象的场景,简化了数据解析过程。与表单提交不同,它主要用于接收 JSON 格式的实体数据。
477 0
|
6月前
|
前端开发 Java 微服务
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@PathVariable
`@PathVariable` 是 Spring Boot 中用于从 URL 中提取参数的注解,支持 RESTful 风格接口开发。例如,通过 `@GetMapping(&quot;/user/{id}&quot;)` 可以将 URL 中的 `{id}` 参数自动映射到方法参数中。若参数名不一致,可通过 `@PathVariable(&quot;自定义名&quot;)` 指定绑定关系。此外,还支持多参数占位符,如 `/user/{id}/{name}`,分别映射到方法中的多个参数。运行项目后,访问指定 URL 即可验证参数是否正确接收。
290 0
|
6月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestMapping
@RequestMapping 是 Spring MVC 中用于请求地址映射的注解,可作用于类或方法上。类级别定义控制器父路径,方法级别进一步指定处理逻辑。常用属性包括 value(请求地址)、method(请求类型,如 GET/POST 等,默认 GET)和 produces(返回内容类型)。例如:`@RequestMapping(value = &quot;/test&quot;, produces = &quot;application/json; charset=UTF-8&quot;)`。此外,针对不同请求方式还有简化注解,如 @GetMapping、@PostMapping 等。
257 0
|
6月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RestController
本文主要介绍 Spring Boot 中 MVC 开发常用的几个注解及其使用方式,包括 `@RestController`、`@RequestMapping`、`@PathVariable`、`@RequestParam` 和 `@RequestBody`。其中重点讲解了 `@RestController` 注解的构成与特点:它是 `@Controller` 和 `@ResponseBody` 的结合体,适用于返回 JSON 数据的场景。文章还指出,在需要模板渲染(如 Thymeleaf)而非前后端分离的情况下,应使用 `@Controller` 而非 `@RestController`
201 0
|
2月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
177 0
|
2月前
|
SQL Java 数据库连接
Spring、SpringMVC 与 MyBatis 核心知识点解析
我梳理的这些内容,涵盖了 Spring、SpringMVC 和 MyBatis 的核心知识点。 在 Spring 中,我了解到 IOC 是控制反转,把对象控制权交容器;DI 是依赖注入,有三种实现方式。Bean 有五种作用域,单例 bean 的线程安全问题及自动装配方式也清晰了。事务基于数据库和 AOP,有失效场景和七种传播行为。AOP 是面向切面编程,动态代理有 JDK 和 CGLIB 两种。 SpringMVC 的 11 步执行流程我烂熟于心,还有那些常用注解的用法。 MyBatis 里,#{} 和 ${} 的区别很关键,获取主键、处理字段与属性名不匹配的方法也掌握了。多表查询、动态
110 0
|
2月前
|
JSON 前端开发 Java
第05课:Spring Boot中的MVC支持
第05课:Spring Boot中的MVC支持
148 0
|
8月前
|
SQL Java 数据库连接
对Spring、SpringMVC、MyBatis框架的介绍与解释
Spring 框架提供了全面的基础设施支持,Spring MVC 专注于 Web 层的开发,而 MyBatis 则是一个高效的持久层框架。这三个框架结合使用,可以显著提升 Java 企业级应用的开发效率和质量。通过理解它们的核心特性和使用方法,开发者可以更好地构建和维护复杂的应用程序。
359 29

热门文章

最新文章