Spring-SpringMvc

Introduction

Spring's Model-View-Controller (MVC) framework is designed around a DispatcherServlet, which distributes requests to various processors and supports configurable processor mapping, view rendering, localization, time zone and theme rendering etc., and even supports file upload. Processors are classes and methods annotated with @Controller and @RequestMapping in your application. Spring provides extremely diverse and flexible configurations for processor methods. Spring 3.0 and later provides the @Controller annotation mechanism, @PathVariable annotation and some other features. You can use them to develop RESTful web sites and applications.

"Open to extensions" is an important design principle of the Spring Web MVC framework, and for the entire complete
framework , the design principle is "open to extensions and closed to modifications."
Some methods in the Spring Web MVC core class library are defined as final methods. As a developer, you cannot
override these methods to customize their behavior. Of course, that's not to say it's absolutely impossible, but please remember this principle. It's not a good practice in most cases. For a detailed explanation of this principle, you can refer to the book
"In-depth Analysis of Spring Web MVC and Web Flow" written by Seth Ladd et al .
Relevant information is on page 117, section “A Look At Design.” Or, you can refer to:
"The Open-Closed Principle" (PDF) written by Bob Martin.
You cannot enhance the final methods in SpringMVC, such as the AbstractController.setSynchronizeOnSession() method, etc. Please refer to the section 10.6.1 Understanding AOP Proxies, which explains the knowledge about AOP proxies and discusses why you cannot enhance final methods.

In Spring Web MVC, you can use any object as a command object or form return object without implementing a framework-related interface or base class. Spring's data binding is very flexible: for example, it treats data type mismatches as runtime validation errors that can be handled by the application, rather than as system errors. You may use strings to store data in form objects to avoid illegal type conversion, but untyped strings cannot describe the true meaning of business data, and you also need to convert them into corresponding business object types. Spring's validation mechanism means you no longer have to do this, and binding business objects directly to form objects is often a better choice.
Spring's view parsing is also designed to be extremely flexible. The controller is generally responsible for preparing a Map model, filling in data, returning an appropriate view name, etc. At the same time, it can also directly write data to the response stream. The resolution of view names is highly flexible and supports multiple configurations, including configuration through file extensions, Accept content headers, beans, configuration files, etc. You can even implement a ViewResolver yourself. The model (M, model in MVC) is actually a Map type interface, which completely abstracts the data from the view technology. You can integrate directly with template-based rendering technologies such as JSP, Velocity, and Freemarker, or you can directly generate XML, JSON, Atom, and many other types of content. The Map model is simply converted into the appropriate format, such as a JSP request attribute, a Velocity template model, etc.

Using springmvc

Web.xml loads Spring's listener

Web.xml loads Spring's listener. According to the source code, we know that the ContextLoaderListener class inherits the parent class.
The initWebApplicationContext method of the parent class is called. The initWebApplicationContext method is to obtain/create a spring web container.

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
public void contextInitialized(ServletContextEvent event) {
        initWebApplicationContext(event.getServletContext());
}
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
        if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
            throw new IllegalStateException(
                    "Cannot initialize context because there is already a root application context present - " +
                    "check whether you have multiple ContextLoader* definitions in your web.xml!");
        }

        Log logger = LogFactory.getLog(ContextLoader.class);
        servletContext.log("Initializing Spring root WebApplicationContext");
        if (logger.isInfoEnabled()) {
            logger.info("Root WebApplicationContext: initialization started");
        }
        long startTime = System.currentTimeMillis();

        try {
            // Store context in local instance variable, to guarantee that
            // it is available on ServletContext shutdown.
            if (this.context == null) {
                this.context = createWebApplicationContext(servletContext);
            }
            if (this.context instanceof ConfigurableWebApplicationContext) {
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
                if (!cwac.isActive()) {
                    // The context has not yet been refreshed -> provide services such as
                    // setting the parent context, setting the application context id, etc
                    if (cwac.getParent() == null) {
                        // The context instance was injected without an explicit parent ->
                        // determine parent for root web application context, if any.
                        ApplicationContext parent = loadParentContext(servletContext);
                        cwac.setParent(parent);
                    }
                    configureAndRefreshWebApplicationContext(cwac, servletContext);
                }
            }
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

            ClassLoader ccl = Thread.currentThread().getContextClassLoader();
            if (ccl == ContextLoader.class.getClassLoader()) {
                currentContext = this.context;
            }
            else if (ccl != null) {
                currentContextPerThread.put(ccl, this.context);
            }

            if (logger.isDebugEnabled()) {
                logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
                        WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
            }
            if (logger.isInfoEnabled()) {
                long elapsedTime = System.currentTimeMillis() - startTime;
                logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
            }

            return this.context;
        }
        catch (RuntimeException ex) {
            logger.error("Context initialization failed", ex);
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
            throw ex;
        }
        catch (Error err) {
            logger.error("Context initialization failed", err);
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
            throw err;
        }
    }

Web.xml loads ServletContextListener to prevent memory leaks

Web.xml loads another listener. Implemented the ServletContextListener interface. This causes Tomcat to load objects repeatedly, resulting in memory leaks that may occur when the framework is used concurrently.
Memory leak means that useless objects (objects that are no longer used) continue to occupy memory or the memory of useless objects cannot be released in time, resulting in a waste of memory space, which is called a memory leak. Sometimes memory leaks are not serious and not easy to detect, so developers do not know that there is a memory leak, but sometimes they are serious and you will be prompted for Out of memory.
So, what is the root cause of Java memory leaks? If a long-lived object holds a reference to a short-lived object, a memory leak is likely to occur. Although the short-lived object is no longer needed, it cannot be recycled because the long-lived object holds a reference to it. This is Java. Scenarios where memory leaks occur.

I only know that the servlet standard does not allow thread management within the web container, and the quartz problem does exist.
For web containers, it is most taboo for applications to start threads privately and schedule threads by themselves. A framework like Quartz, which starts 10 threads by default inside the web container for asynchronous job scheduling, is very dangerous in itself and can easily cause problems. Servlet thread resources cannot be recycled, so I have always resisted using quartz.
Another problem with quartz is that it does not support clusters. As a result, applications using quartz cannot be clustered.

<listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
public void contextInitialized(ServletContextEvent event) {
        CachedIntrospectionResults.acceptClassLoader(Thread.currentThread().getContextClassLoader());
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        CachedIntrospectionResults.clearClassLoader(Thread.currentThread().getContextClassLoader());
        Introspector.flushCaches();
    }

Web.xml loads the core configuration file of springmvc

Web.xml loads the configuration file of springmvc. The core class DispatcherServlet of springmvc is loaded here. When starting to listen, the xml file will be configured into the DispatcherServlet. The DispatcherServlet class interprets the xml file and obtains the corresponding configuration information.
When you do not specify it, an xml file starting with any character and ending with servlet will be loaded by default. If not, a not find file Exception will be thrown. "/*" means intercept all requests

<servlet>
        <description>spring mvc servlet</description>
        <servlet-name>springMvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <description>spring mvc 配置文件</description>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMvc</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

DispatcherServlet is responsible for distributing all requests to the controller; it also provides other functions required for web application development. But Spring's central processor, DispatcherServlet, can do more than this. It is seamlessly integrated with the Spring IoC container, which means that any features provided by Spring can be used in SpringMVC.
The following figure shows the workflow of Spring Web MVC's DispatcherServlet processing requests. Friends who are familiar with design patterns will find that DispatcherServlet actually applies a "front-end controller" design pattern (many other excellent web frameworks also use this design pattern).
The core method is to load beans (including view parsers/json converters/files/etc.) into the ioc container.
Write picture description here
Write picture description here

protected void initStrategies(ApplicationContext context) {
        initMultipartResolver(context);
        initLocaleResolver(context);
        initThemeResolver(context);
        initHandlerMappings(context);
        initHandlerAdapters(context);
        initHandlerExceptionResolvers(context);
        initRequestToViewNameTranslator(context);
        initViewResolvers(context);
        initFlashMapManager(context);
    }

Springmvc loading view resolver

Springmvc loads the view resolver: There are two interfaces that are crucial when Spring handles view-related matters, namely the view resolver interface ViewResolver and the view interface itself View. The view resolver ViewResolver is responsible for processing the mapping relationship between the view name and the actual view. The view interface View is responsible for preparing requests and handing over the rendering of requests to a specific view technology implementation.

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>  
        <property name="prefix" value="/WEB-INF/"/>  
        <property name="suffix" value=".jsp"/> 
        <property name="order" value="1"/>  
</bean>

Write picture description here
Load ViewResolver. ViewResolver is the top-level interface of InternalResourceViewResolver. So it is interface-oriented programming and setting the subclass in the xml file. The viewClass class is injected in the constructor method. The viewClass is also configured in the xml file. Attributes such as prefix (prefix and suffix) are set in UrlBasedViewResolver, the parent class of InternalResourceViewResolver. This completes operations such as suffix addition and prefix insertion.

private void initViewResolvers(ApplicationContext context) {
        this.viewResolvers = null;

        if (this.detectAllViewResolvers) {
            // Find all ViewResolvers in the ApplicationContext, including ancestor contexts.
            Map<String, ViewResolver> matchingBeans =
                    BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.viewResolvers = new ArrayList<ViewResolver>(matchingBeans.values());
                // We keep ViewResolvers in sorted order.
                AnnotationAwareOrderComparator.sort(this.viewResolvers);
            }
        }
        else {
            try {
                ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
                this.viewResolvers = Collections.singletonList(vr);
            }
            catch (NoSuchBeanDefinitionException ex) {
                // Ignore, we'll add a default ViewResolver later.
            }
        }
        // Ensure we have at least one ViewResolver, by registering
        // a default ViewResolver if no other resolvers are found.
        if (this.viewResolvers == null) {
            this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
            if (logger.isDebugEnabled()) {
                logger.debug("No ViewResolvers found in servlet '" + getServletName() + "': using default");
            }
        }
    }
public InternalResourceViewResolver() {
        Class<?> viewClass = requiredViewClass();
        if (InternalResourceView.class == viewClass && jstlPresent) {
            viewClass = JstlView.class;
        }
        setViewClass(viewClass);
    }

  1. Complete mavne package structure – portal
  2. spring configuration file (not available yet) – Portal

Guess you like

Origin blog.csdn.net/my_God_sky/article/details/72547922