021-spring-springmvc-组件

发布于:2025-02-11 ⋅ 阅读:(9) ⋅ 点赞:(0)

SpringMVC的handMapping

比较重要的部分

比较重要的部分

比较重要的部分

关于组件的部分

这里以 RequestMappingHandlerMapping 为例子

默认的3个组件是:

org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
org.springframework.web.servlet.function.support.RouterFunctionMapping

如果在spring-mvc.xml中配置了自定义的 HandlerMapping 组件,则不会加载默认的3个组件(你自定义了组件就不用springmvc默认的组件了)

下面的代码的加载过程

SpringMVC的请求处理

SpringMVC的请求处理-Bean

SpringMVC的请求处理-转为对象

文件上传

获取head

静态资源

1、tomcat是defaultServlet 默认接受请求  /    

2、dispatherServlet 的 默认路径 /   ,覆盖了原先的 defaultServlet 。找不到原来的资源

3、解决方法:

方法1

方法2

<mvc:default-servlet-handler />的作用原理

总结:

向容器中注入了SimpleUrlHandlerMapping  (SimpleUrlHandlerMapping   是一个Mapping) 

是 Spring MVC 中的一项配置,用于处理静态资源请求。它的主要作用是在 Spring MVC 的 DispatcherServlet 无法处理的请求时,将这些请求传递给 servlet 容器的默认 servlet,例如 Tomcat 的 DefaultServlet

<mvc:annotation-driven>干了点啥

配置上注解就等于把大的红色框里的东西替代了

总结:

  1. 启用注解支持:

    • 当你添加 <mvc:annotation-driven /> 时,Spring 会自动配置相关的组件,以支持使用注解定义的控制器。这样,你可以使用如 @Controller 和 @RequestMapping 等注解而无需额外的配置。
  2. HTTP 消息转换:

    • 此配置会自动注册 HttpMessageConverter,用于将 HTTP 请求和响应中的数据类型(如 JSON 和 XML)进行转换。通过这个功能,Spring 可以根据请求的 Content-Type 和 Accept 头部自动选择合适的转换器。
    • 例如,使用 @ResponseBody 和 @RequestBody 注解时,Spring 会使用 JSON 或 XML 转换器将 Java 对象与 HTTP 消息体内容相互转换。
  3. 视图解析器:

    • 启用后,Spring 会自动配置默认的 ViewResolver,处理不同的视图解决方案,使得返回的视图能够被正确解析。

作用原理:

`<mvc:annotation-driven />` 在 Spring MVC 中的作用是启用基于注解的 MVC 配置。这个功能的底层实现机制和原理相对复杂,以下是它的主要原理和功能组件:

### 1. **HttpMessageConverters**

使用 `<mvc:annotation-driven />` 时,Spring 会自动注册一组 `HttpMessageConverter`,这些转换器负责将请求体转换为 Java 对象,同时也将 Java 对象转换为响应体。常见的 `HttpMessageConverter` 包括:

- `MappingJackson2HttpMessageConverter`:用于 JSON 转换,使用 Jackson 库。
- `Jaxb2RootElementHttpMessageConverter`:用于 XML 转换。
- 其他用于处理文本、字节流等的转换器。

### 2. **RequestMappingHandlerMapping**

添加 `<mvc:annotation-driven />` 后,Spring 会注册一个 `RequestMappingHandlerMapping` 实例,这是用来管理请求映射的。它的工作原理如下:

- **URL 路由**:根据请求的 URL、HTTP 方法等信息,将请求映射到一个具体的处理方法(使用了 `@RequestMapping` 或类似注解的方法)。
- 此外,它会解析控制器半径(可以通过 `@Controller` 注解标识)。

### 3. **RequestMappingHandlerAdapter**

`RequestMappingHandlerAdapter` 是用来调用处理器方法的适配器。其作用包括:

- **参数解析**:将 HTTP 请求中的参数、请求体、路径变量等映射到处理器方法的参数上。
- **返回值处理**:处理方法返回结果的转换,确保将 Java 对象转换成适当的 HTTP 响应格式(比如 JSON 或 HTML)。
  
### 4. **@Controller 和 @RequestMapping**

- 当你使用 `@Controller` 注解标记的类时,该类会被 Spring 识别为控制器,并由 Spring 的 IOC 容器管理。
- 在类中的方法上使用 `@RequestMapping` 注解,Spring 会建立 URL 路由与方法之间的对应关系。

### 5. **视图解析器**

虽然 `<mvc:annotation-driven />` 本身并不直接配置视图解析器,但这项配置通常与视图解析相关联。Spring 会提供默认的视图解析器,帮助根据返回的视图名称(例如返回字符串 `"viewName"`)来解析到实际的视图资源(如 JSP)。

### 6. **总结**

总体来看,`<mvc:annotation-driven />` 的核心原理是将一系列基于注解的配置和组件集成在一起,以便简化使用 Spring MVC 开发时的配置工作。它自动加入了很多关键的支持,确保请求可以被适当地映射、处理和响应,同时也提供了一种更清晰和声明式的编程风格。

如果你对这个主题还有更深入的疑问或需要具体的代码示例,请告诉我!
 

SpringMVC的转发重定向

Springmvc拦截器

Springmvc配置路径

--- ? :匹配文件名中得一个字符
--- * :匹配文件名得任意字符
---** : ** 匹配多层路径

 /*  -->  /a /success  /text
/**  -->  所有的路径


// 例子如下:
/user/*/createrUser   ====>匹配:/user/aaa/createrUser
/user/**/createrUser  ====>匹配:/user/createrUser    /user/aaa/bbb/createrUser
/user/createrUser??   ====>匹配:/user/createrUseraa   /user/createrUserbb

乱码

  1. get乱码:修改tomcat 的server.xml 中的 connector port =’8080’  URIEncoding=’UTF-8’ 
  2. post乱码:设置web.xml中的过滤器

springmvc异常

域对象共享数据

  1. 使用request  ---->   request.setAttribute(“key”,”value”);
  2. 使用modelAndView  ----> 推荐使用
  3. 使用model
  4. 使用map
  5. 使用session ----> 推荐使用
  6. 使用application ----> 推荐使用
  7. model、 modelMap、Map的关系

springmvc使用注解替换XML- 组件扫描

以上配置替换为

springmvc使用注解替换XML- 文件上传

<!--    处理文件上传与下载-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 必须和用户JSP 的pageEncoding属性一致,以便正确解析表单的内容 -->
        <property name="defaultEncoding" value="UTF-8"></property>
        <!-- 文件最大大小(字节) 1024*1024*50=50M-->
        <property name="maxUploadSize" value="52428800"></property>
        <!--resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常-->
        <property name="resolveLazily" value="true"/>
    </bean>

以上配置替换为

import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.web.multipart.commons.CommonsMultipartResolver;  

@Configuration  
public class WebConfig {  

    @Bean  
    public CommonsMultipartResolver multipartResolver() {  
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();  
        // 设置编码  
        resolver.setDefaultEncoding("UTF-8");  
        // 设置最大上传文件大小  
        resolver.setMaxUploadSize(52428800); // 50 MB  
        // 启用延迟解析  
        resolver.setResolveLazily(true);  
        return resolver;  
    }  
}

springmvc使用注解替换XML- 其他配置替换

以上配置替换为  @EnableWebMvc

这个地方就需要了解WebMvcConfigure 。

实现这个接口,放到容器中,会被springmvc发现。

springmvc使用注解替换XML- 消除web.xml

在启动的时候,会加载这个,会走onStartup方法来加载配置

上面这段话的意思是:tomcat启动需要一个  servlertContainerInitializer接口的类
可以自己定义一个类来创建代替web.xml

配置视图映射:
1、自定义的类WebInit 需要 springmc、spirng、filter、请求路径映射
2、创建了springmc配置类
3、创建了spirng配置类
4、重写了 filter 方法
5、重写了请求路径映射方法
6、在springmvc的配置类SpringMvcConfig 配置了thymeleaf的视图解析器、包扫描、注解驱动
7、综上在tomcat启动的时候会加载自定义类WebInit 
8、WebInit 类会加载springmc、spirng、filter、请求路径映射

web.xml 中指定了springmc、spirng、filter、请求路径映射
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {

    //1指定spirng的配置类
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    //2指定springmvc的配置类
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    //3指定dispathcServlet的路径映射
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    // 4过滤器
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("utf-8");
        characterEncodingFilter.setForceResponseEncoding(true);
        HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
        return new Filter[]{characterEncodingFilter,hiddenHttpMethodFilter};
    }

}

/**
   代替springmvc的配置文件
    1、扫描组件
    2、视图解析
    3、view-controller
    4、<mvc:default-servlet-handler/>
    5、mvc注解驱动
    6、文件上传解析器
    7、异常处理
    8、拦截器
 */

@Configuration
@ComponentScan("com.nuc")  // 1、组件扫描
@EnableWebMvc   //5、mvc注解驱动
public class SpringMvcConfig implements WebMvcConfigurer {
    //2、视图解析  配置 thyleaf 的视图解析器  就可以访问

    //3、view-controller
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // hello 是请求地址
        // success 是跳转页面
       registry.addViewController("/hello").setViewName("success");
    }

    //4、<mvc:default-servlet-handler/>
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
       configurer.enable();//默认servler可用
    }

     //  6、文件上传解析器
    @Bean
    public MultipartResolver multipartResolver(){
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
        return  commonsMultipartResolver;
    }

    //7、异常处理
    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();
        Properties properties = new Properties();
        properties.put("java.lang.Arithmeticexception","error");  //这个错误 跳error页面
        properties.put("java.lang.NullpointerException","errorNull"); //这个错误 跳 errorNull 页面

        simpleMappingExceptionResolver.setExceptionMappings(properties);
        simpleMappingExceptionResolver.setExceptionAttribute("exception");  //将错误信息放在域对象中

        resolvers.add(simpleMappingExceptionResolver);
    }

    //8、拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //实现自定义拦截器
       registry.addInterceptor(new TestInterceptors()).addPathPatterns("/**");
    }
}

//实现自定义拦截器
class  TestInterceptors implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

springmvc的组件原理-获取applicationContext容器

GenericServlet 的init方法 在 HttpServletBean 实现了 。

在HttpServletBean 的init方法  中  this.initServletBean();  方法由子类来实现

FrameworkServlet 中实现了 initServletBean 方法

总结:会有2个容器。一个是spring的,一个是springmvc容器的

先从springmvc容器中获取bean

在尝试从spring容器中获取bean

这个地方时从小到大容器的获取.。。。springmvc是子容器,spring是父容器。

springmvc的组件原理-注册9大容器

容器创建完毕,会发一个监听的事件。

监听事件,会调用一个方法

方法里会调用   initStrategies