Spring Architecture Series-3.Understanding Spring MVC Implementation

Introduction

Spring MVC is a powerful web framework that implements the Model-View-Controller pattern.In this article,I’ll explore the implementation of a simplified Spring MVC framework through my miniSpring project,which captures the essential features of Spring MVC while maintaining clarity and simplicity.

src/com/yaruyng/web/
├── servlet/
│ ├── DispatcherServlet.java
│ ├── HandlerMapping.java
│ ├── HandlerAdapter.java
│ ├── ModelAndView.java
│ ├── ViewResolver.java
│ └── View.java
├── method/
├── context/
└── RequestMapping.java
src/com/yaruyng/web/
├── servlet/
│   ├── DispatcherServlet.java
│   ├── HandlerMapping.java
│   ├── HandlerAdapter.java
│   ├── ModelAndView.java
│   ├── ViewResolver.java
│   └── View.java
├── method/
├── context/
└── RequestMapping.java
src/com/yaruyng/web/ ├── servlet/ │ ├── DispatcherServlet.java │ ├── HandlerMapping.java │ ├── HandlerAdapter.java │ ├── ModelAndView.java │ ├── ViewResolver.java │ └── View.java ├── method/ ├── context/ └── RequestMapping.java

Enter fullscreen mode Exit fullscreen mode

The Front Controller:DispatcherServlet

The DispatcherServlet acts as the front controller in our MVC implements:

<span>public</span> <span>class</span> <span>DispatcherServlet</span> <span>extends</span> <span>HttpServlet</span> <span>{</span>
<span>private</span> <span>WebApplicationContext</span> <span>webApplicationContext</span><span>;</span>
<span>private</span> <span>HandlerMapping</span> <span>handlerMapping</span><span>;</span>
<span>private</span> <span>HandlerAdapter</span> <span>handlerAdapter</span><span>;</span>
<span>private</span> <span>ViewResolver</span> <span>viewResolver</span><span>;</span>
<span>@Override</span>
<span>public</span> <span>void</span> <span>init</span><span>(</span><span>ServletConfig</span> <span>config</span><span>)</span> <span>throws</span> <span>ServletException</span> <span>{</span>
<span>super</span><span>.</span><span>init</span><span>(</span><span>config</span><span>);</span>
<span>this</span><span>.</span><span>parentApplicationContext</span> <span>=</span> <span>(</span><span>WebApplicationContext</span><span>)</span> <span>this</span><span>.</span><span>getServletContext</span><span>()</span>
<span>.</span><span>getAttribute</span><span>(</span><span>WebApplicationContext</span><span>.</span><span>ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE</span><span>);</span>
<span>this</span><span>.</span><span>sContextConfigLocation</span> <span>=</span> <span>config</span><span>.</span><span>getInitParameter</span><span>(</span><span>"contextConfigLocation"</span><span>);</span>
<span>this</span><span>.</span><span>webApplicationContext</span> <span>=</span> <span>new</span> <span>AnnotationConfigWebApplicationContext</span><span>(</span>
<span>sContextConfigLocation</span><span>,</span>
<span>this</span><span>.</span><span>parentApplicationContext</span>
<span>);</span>
<span>Refresh</span><span>();</span>
<span>}</span>
<span>protected</span> <span>void</span> <span>doDispatch</span><span>(</span><span>HttpServletRequest</span> <span>request</span><span>,</span> <span>HttpServletResponse</span> <span>response</span><span>)</span>
<span>throws</span> <span>Exception</span> <span>{</span>
<span>HttpServletRequest</span> <span>processedRequest</span> <span>=</span> <span>request</span><span>;</span>
<span>HandlerMethod</span> <span>handlerMethod</span> <span>=</span> <span>null</span><span>;</span>
<span>ModelAndView</span> <span>mv</span> <span>=</span> <span>null</span><span>;</span>
<span>// 1. Get handler for request</span>
<span>handlerMethod</span> <span>=</span> <span>this</span><span>.</span><span>handlerMapping</span><span>.</span><span>getHandler</span><span>(</span><span>processedRequest</span><span>);</span>
<span>if</span><span>(</span><span>handlerMethod</span> <span>==</span> <span>null</span><span>)</span> <span>{</span>
<span>return</span><span>;</span>
<span>}</span>
<span>// 2. Execute handler with adapter</span>
<span>HandlerAdapter</span> <span>ha</span> <span>=</span> <span>this</span><span>.</span><span>handlerAdapter</span><span>;</span>
<span>mv</span> <span>=</span> <span>ha</span><span>.</span><span>handle</span><span>(</span><span>processedRequest</span><span>,</span> <span>response</span><span>,</span> <span>handlerMethod</span><span>);</span>
<span>// 3. Render view</span>
<span>render</span><span>(</span><span>request</span><span>,</span> <span>response</span><span>,</span> <span>mv</span><span>);</span>
<span>}</span>
<span>}</span>
<span>public</span> <span>class</span> <span>DispatcherServlet</span> <span>extends</span> <span>HttpServlet</span> <span>{</span>
    <span>private</span> <span>WebApplicationContext</span> <span>webApplicationContext</span><span>;</span>
    <span>private</span> <span>HandlerMapping</span> <span>handlerMapping</span><span>;</span>
    <span>private</span> <span>HandlerAdapter</span> <span>handlerAdapter</span><span>;</span>
    <span>private</span> <span>ViewResolver</span> <span>viewResolver</span><span>;</span>

    <span>@Override</span>
    <span>public</span> <span>void</span> <span>init</span><span>(</span><span>ServletConfig</span> <span>config</span><span>)</span> <span>throws</span> <span>ServletException</span> <span>{</span>
        <span>super</span><span>.</span><span>init</span><span>(</span><span>config</span><span>);</span>
        <span>this</span><span>.</span><span>parentApplicationContext</span> <span>=</span> <span>(</span><span>WebApplicationContext</span><span>)</span> <span>this</span><span>.</span><span>getServletContext</span><span>()</span>
                <span>.</span><span>getAttribute</span><span>(</span><span>WebApplicationContext</span><span>.</span><span>ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE</span><span>);</span>
        <span>this</span><span>.</span><span>sContextConfigLocation</span> <span>=</span> <span>config</span><span>.</span><span>getInitParameter</span><span>(</span><span>"contextConfigLocation"</span><span>);</span>

        <span>this</span><span>.</span><span>webApplicationContext</span> <span>=</span> <span>new</span> <span>AnnotationConfigWebApplicationContext</span><span>(</span>
            <span>sContextConfigLocation</span><span>,</span> 
            <span>this</span><span>.</span><span>parentApplicationContext</span>
        <span>);</span>
        <span>Refresh</span><span>();</span>
    <span>}</span>

    <span>protected</span> <span>void</span> <span>doDispatch</span><span>(</span><span>HttpServletRequest</span> <span>request</span><span>,</span> <span>HttpServletResponse</span> <span>response</span><span>)</span> 
            <span>throws</span> <span>Exception</span> <span>{</span>
        <span>HttpServletRequest</span> <span>processedRequest</span> <span>=</span> <span>request</span><span>;</span>
        <span>HandlerMethod</span> <span>handlerMethod</span> <span>=</span> <span>null</span><span>;</span>
        <span>ModelAndView</span> <span>mv</span> <span>=</span> <span>null</span><span>;</span>

        <span>// 1. Get handler for request</span>
        <span>handlerMethod</span> <span>=</span> <span>this</span><span>.</span><span>handlerMapping</span><span>.</span><span>getHandler</span><span>(</span><span>processedRequest</span><span>);</span>
        <span>if</span><span>(</span><span>handlerMethod</span> <span>==</span> <span>null</span><span>)</span> <span>{</span>
            <span>return</span><span>;</span>
        <span>}</span>

        <span>// 2. Execute handler with adapter</span>
        <span>HandlerAdapter</span> <span>ha</span> <span>=</span> <span>this</span><span>.</span><span>handlerAdapter</span><span>;</span>
        <span>mv</span> <span>=</span> <span>ha</span><span>.</span><span>handle</span><span>(</span><span>processedRequest</span><span>,</span> <span>response</span><span>,</span> <span>handlerMethod</span><span>);</span>

        <span>// 3. Render view</span>
        <span>render</span><span>(</span><span>request</span><span>,</span> <span>response</span><span>,</span> <span>mv</span><span>);</span>
    <span>}</span>
<span>}</span>
public class DispatcherServlet extends HttpServlet { private WebApplicationContext webApplicationContext; private HandlerMapping handlerMapping; private HandlerAdapter handlerAdapter; private ViewResolver viewResolver; @Override public void init(ServletConfig config) throws ServletException { super.init(config); this.parentApplicationContext = (WebApplicationContext) this.getServletContext() .getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); this.sContextConfigLocation = config.getInitParameter("contextConfigLocation"); this.webApplicationContext = new AnnotationConfigWebApplicationContext( sContextConfigLocation, this.parentApplicationContext ); Refresh(); } protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerMethod handlerMethod = null; ModelAndView mv = null; // 1. Get handler for request handlerMethod = this.handlerMapping.getHandler(processedRequest); if(handlerMethod == null) { return; } // 2. Execute handler with adapter HandlerAdapter ha = this.handlerAdapter; mv = ha.handle(processedRequest, response, handlerMethod); // 3. Render view render(request, response, mv); } }

Enter fullscreen mode Exit fullscreen mode

Key features of the Dispatcher:

  1. Initializes the web application context
  2. Sets up handler mapping,adapter, and view resolver
  3. Processes incoming requests through the doDispatch method
  4. Coordinates between different components of the MVC framework

Request Mapping

The @RequestMapping annotation is used to map web requests to handler methods:

<span>@Target</span><span>(</span><span>value</span> <span>=</span> <span>{</span><span>ElementType</span><span>.</span><span>METHOD</span><span>})</span>
<span>@Retention</span><span>(</span><span>RetentionPolicy</span><span>.</span><span>RUNTIME</span><span>)</span>
<span>public</span> <span>@interface</span> <span>RequestMapping</span> <span>{</span>
<span>String</span> <span>value</span><span>()</span> <span>default</span> <span>""</span><span>;</span>
<span>}</span>
<span>@Target</span><span>(</span><span>value</span> <span>=</span> <span>{</span><span>ElementType</span><span>.</span><span>METHOD</span><span>})</span>
<span>@Retention</span><span>(</span><span>RetentionPolicy</span><span>.</span><span>RUNTIME</span><span>)</span>
<span>public</span> <span>@interface</span> <span>RequestMapping</span> <span>{</span>
    <span>String</span> <span>value</span><span>()</span> <span>default</span> <span>""</span><span>;</span>
<span>}</span>
@Target(value = {ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface RequestMapping { String value() default ""; }

Enter fullscreen mode Exit fullscreen mode

This simple yet powerful annotation allows for:

  • Method-level request mapping
  • URL pattern matching
  • Runtime processing of mapping

Model and View Handling

The ModelAndView class represents both the model data and view information:

<span>public</span> <span>class</span> <span>ModelAndView</span> <span>{</span>
<span>private</span> <span>Object</span> <span>view</span><span>;</span>
<span>private</span> <span>Map</span><span><</span><span>String</span><span>,</span> <span>Object</span><span>></span> <span>model</span> <span>=</span> <span>new</span> <span>HashMap</span><span><>();</span>
<span>public</span> <span>ModelAndView</span><span>(</span><span>String</span> <span>viewName</span><span>,</span> <span>Map</span><span><</span><span>String</span><span>,</span> <span>?></span> <span>modelData</span><span>)</span> <span>{</span>
<span>this</span><span>.</span><span>view</span> <span>=</span> <span>viewName</span><span>;</span>
<span>if</span><span>(</span><span>modelData</span> <span>!=</span> <span>null</span><span>)</span> <span>{</span>
<span>addAllAttributes</span><span>(</span><span>modelData</span><span>);</span>
<span>}</span>
<span>}</span>
<span>public</span> <span>void</span> <span>addAttribute</span><span>(</span><span>String</span> <span>attributeName</span><span>,</span> <span>Object</span> <span>attributeValue</span><span>)</span> <span>{</span>
<span>model</span><span>.</span><span>put</span><span>(</span><span>attributeName</span><span>,</span> <span>attributeValue</span><span>);</span>
<span>}</span>
<span>public</span> <span>ModelAndView</span> <span>addObject</span><span>(</span><span>String</span> <span>attributeName</span><span>,</span> <span>Object</span> <span>attributeValue</span><span>)</span> <span>{</span>
<span>addAttribute</span><span>(</span><span>attributeName</span><span>,</span> <span>attributeValue</span><span>);</span>
<span>return</span> <span>this</span><span>;</span>
<span>}</span>
<span>// Other methods...</span>
<span>}</span>
<span>public</span> <span>class</span> <span>ModelAndView</span> <span>{</span>
    <span>private</span> <span>Object</span> <span>view</span><span>;</span>
    <span>private</span> <span>Map</span><span><</span><span>String</span><span>,</span> <span>Object</span><span>></span> <span>model</span> <span>=</span> <span>new</span> <span>HashMap</span><span><>();</span>

    <span>public</span> <span>ModelAndView</span><span>(</span><span>String</span> <span>viewName</span><span>,</span> <span>Map</span><span><</span><span>String</span><span>,</span> <span>?></span> <span>modelData</span><span>)</span> <span>{</span>
        <span>this</span><span>.</span><span>view</span> <span>=</span> <span>viewName</span><span>;</span>
        <span>if</span><span>(</span><span>modelData</span> <span>!=</span> <span>null</span><span>)</span> <span>{</span>
            <span>addAllAttributes</span><span>(</span><span>modelData</span><span>);</span>
        <span>}</span>
    <span>}</span>

    <span>public</span> <span>void</span> <span>addAttribute</span><span>(</span><span>String</span> <span>attributeName</span><span>,</span> <span>Object</span> <span>attributeValue</span><span>)</span> <span>{</span>
        <span>model</span><span>.</span><span>put</span><span>(</span><span>attributeName</span><span>,</span> <span>attributeValue</span><span>);</span>
    <span>}</span>

    <span>public</span> <span>ModelAndView</span> <span>addObject</span><span>(</span><span>String</span> <span>attributeName</span><span>,</span> <span>Object</span> <span>attributeValue</span><span>)</span> <span>{</span>
        <span>addAttribute</span><span>(</span><span>attributeName</span><span>,</span> <span>attributeValue</span><span>);</span>
        <span>return</span> <span>this</span><span>;</span>
    <span>}</span>

    <span>// Other methods...</span>
<span>}</span>
public class ModelAndView { private Object view; private Map<String, Object> model = new HashMap<>(); public ModelAndView(String viewName, Map<String, ?> modelData) { this.view = viewName; if(modelData != null) { addAllAttributes(modelData); } } public void addAttribute(String attributeName, Object attributeValue) { model.put(attributeName, attributeValue); } public ModelAndView addObject(String attributeName, Object attributeValue) { addAttribute(attributeName, attributeValue); return this; } // Other methods... }

Enter fullscreen mode Exit fullscreen mode

This implementation:

  1. Combines view information with model data
  2. Provides flexible constructors fro different use cases
  3. Offers convenient methods for adding attributes

View Resolution

The view resolution process is handled the ViewResolver interface and its implementation:

<span>public</span> <span>interface</span> <span>ViewResolver</span> <span>{</span>
<span>View</span> <span>resolveViewName</span><span>(</span><span>String</span> <span>viewName</span><span>)</span> <span>throws</span> <span>Exception</span><span>;</span>
<span>}</span>
<span>public</span> <span>interface</span> <span>ViewResolver</span> <span>{</span>
    <span>View</span> <span>resolveViewName</span><span>(</span><span>String</span> <span>viewName</span><span>)</span> <span>throws</span> <span>Exception</span><span>;</span>
<span>}</span>
public interface ViewResolver { View resolveViewName(String viewName) throws Exception; }

Enter fullscreen mode Exit fullscreen mode

The actual rendering is performed by the View interface:

<span>public</span> <span>interface</span> <span>View</span> <span>{</span>
<span>void</span> <span>render</span><span>(</span><span>Map</span><span><</span><span>String</span><span>,</span> <span>Object</span><span>></span> <span>model</span><span>,</span> <span>HttpServletRequest</span> <span>request</span><span>,</span>
<span>HttpServletResponse</span> <span>response</span><span>)</span> <span>throws</span> <span>Exception</span><span>;</span>
<span>}</span>
<span>public</span> <span>interface</span> <span>View</span> <span>{</span>
    <span>void</span> <span>render</span><span>(</span><span>Map</span><span><</span><span>String</span><span>,</span> <span>Object</span><span>></span> <span>model</span><span>,</span> <span>HttpServletRequest</span> <span>request</span><span>,</span>
                <span>HttpServletResponse</span> <span>response</span><span>)</span> <span>throws</span> <span>Exception</span><span>;</span>
<span>}</span>
public interface View { void render(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception; }

Enter fullscreen mode Exit fullscreen mode

Request Processing Flow

The request processing flow in miniSpring MVC follows these steps:

  1. Request Reception
<span>protected</span> <span>void</span> <span>service</span><span>(</span><span>HttpServletRequest</span> <span>request</span><span>,</span> <span>HttpServletResponse</span> <span>response</span><span>)</span> <span>{</span>
<span>request</span><span>.</span><span>setAttribute</span><span>(</span><span>WEB_APPLICATION_CONTEXT_ATTRIBUTE</span><span>,</span> <span>this</span><span>.</span><span>webApplicationContext</span><span>);</span>
<span>try</span> <span>{</span>
<span>doDispatch</span><span>(</span><span>request</span><span>,</span> <span>response</span><span>);</span>
<span>}</span> <span>catch</span> <span>(</span><span>Exception</span> <span>e</span><span>)</span> <span>{</span>
<span>throw</span> <span>new</span> <span>RuntimeException</span><span>(</span><span>e</span><span>);</span>
<span>}</span>
<span>}</span>
<span>protected</span> <span>void</span> <span>service</span><span>(</span><span>HttpServletRequest</span> <span>request</span><span>,</span> <span>HttpServletResponse</span> <span>response</span><span>)</span> <span>{</span>
    <span>request</span><span>.</span><span>setAttribute</span><span>(</span><span>WEB_APPLICATION_CONTEXT_ATTRIBUTE</span><span>,</span> <span>this</span><span>.</span><span>webApplicationContext</span><span>);</span>
    <span>try</span> <span>{</span>
        <span>doDispatch</span><span>(</span><span>request</span><span>,</span> <span>response</span><span>);</span>
    <span>}</span> <span>catch</span> <span>(</span><span>Exception</span> <span>e</span><span>)</span> <span>{</span>
        <span>throw</span> <span>new</span> <span>RuntimeException</span><span>(</span><span>e</span><span>);</span>
    <span>}</span>
<span>}</span>
protected void service(HttpServletRequest request, HttpServletResponse response) { request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.webApplicationContext); try { doDispatch(request, response); } catch (Exception e) { throw new RuntimeException(e); } }

Enter fullscreen mode Exit fullscreen mode

  1. Handler Mapping
<span>handlerMethod</span> <span>=</span> <span>this</span><span>.</span><span>handlerMapping</span><span>.</span><span>getHandler</span><span>(</span><span>processedRequest</span><span>);</span>
<span>handlerMethod</span> <span>=</span> <span>this</span><span>.</span><span>handlerMapping</span><span>.</span><span>getHandler</span><span>(</span><span>processedRequest</span><span>);</span>
handlerMethod = this.handlerMapping.getHandler(processedRequest);

Enter fullscreen mode Exit fullscreen mode

  1. Handler Execution
<span>mv</span> <span>=</span> <span>ha</span><span>.</span><span>handle</span><span>(</span><span>processedRequest</span><span>,</span> <span>response</span><span>,</span> <span>handlerMethod</span><span>);</span>
<span>mv</span> <span>=</span> <span>ha</span><span>.</span><span>handle</span><span>(</span><span>processedRequest</span><span>,</span> <span>response</span><span>,</span> <span>handlerMethod</span><span>);</span>
mv = ha.handle(processedRequest, response, handlerMethod);

Enter fullscreen mode Exit fullscreen mode

  1. View Rendering
<span>protected</span> <span>void</span> <span>render</span><span>(</span><span>HttpServletRequest</span> <span>request</span><span>,</span> <span>HttpServletResponse</span> <span>response</span><span>,</span>
<span>ModelAndView</span> <span>mv</span><span>)</span> <span>throws</span> <span>Exception</span> <span>{</span>
<span>if</span><span>(</span><span>mv</span> <span>==</span> <span>null</span><span>)</span> <span>{</span>
<span>response</span><span>.</span><span>getWriter</span><span>().</span><span>flush</span><span>();</span>
<span>response</span><span>.</span><span>getWriter</span><span>().</span><span>close</span><span>();</span>
<span>return</span><span>;</span>
<span>}</span>
<span>String</span> <span>sTarget</span> <span>=</span> <span>mv</span><span>.</span><span>getViewName</span><span>();</span>
<span>Map</span><span><</span><span>String</span><span>,</span> <span>Object</span><span>></span> <span>modelMap</span> <span>=</span> <span>mv</span><span>.</span><span>getModel</span><span>();</span>
<span>View</span> <span>view</span> <span>=</span> <span>resolveViewName</span><span>(</span><span>sTarget</span><span>,</span> <span>modelMap</span><span>,</span> <span>request</span><span>);</span>
<span>view</span><span>.</span><span>render</span><span>(</span><span>modelMap</span><span>,</span> <span>request</span><span>,</span> <span>response</span><span>);</span>
<span>}</span>
<span>protected</span> <span>void</span> <span>render</span><span>(</span><span>HttpServletRequest</span> <span>request</span><span>,</span> <span>HttpServletResponse</span> <span>response</span><span>,</span> 
        <span>ModelAndView</span> <span>mv</span><span>)</span> <span>throws</span> <span>Exception</span> <span>{</span>
    <span>if</span><span>(</span><span>mv</span> <span>==</span> <span>null</span><span>)</span> <span>{</span>
        <span>response</span><span>.</span><span>getWriter</span><span>().</span><span>flush</span><span>();</span>
        <span>response</span><span>.</span><span>getWriter</span><span>().</span><span>close</span><span>();</span>
        <span>return</span><span>;</span>
    <span>}</span>

    <span>String</span> <span>sTarget</span> <span>=</span> <span>mv</span><span>.</span><span>getViewName</span><span>();</span>
    <span>Map</span><span><</span><span>String</span><span>,</span> <span>Object</span><span>></span> <span>modelMap</span> <span>=</span> <span>mv</span><span>.</span><span>getModel</span><span>();</span>
    <span>View</span> <span>view</span> <span>=</span> <span>resolveViewName</span><span>(</span><span>sTarget</span><span>,</span> <span>modelMap</span><span>,</span> <span>request</span><span>);</span>
    <span>view</span><span>.</span><span>render</span><span>(</span><span>modelMap</span><span>,</span> <span>request</span><span>,</span> <span>response</span><span>);</span>
<span>}</span>
protected void render(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception { if(mv == null) { response.getWriter().flush(); response.getWriter().close(); return; } String sTarget = mv.getViewName(); Map<String, Object> modelMap = mv.getModel(); View view = resolveViewName(sTarget, modelMap, request); view.render(modelMap, request, response); }

Enter fullscreen mode Exit fullscreen mode

Integration with IoC Container

The MVC framework integrates with the IoC container through the WebApplicationContext:

<span>protected</span> <span>void</span> <span>initHandlerMappings</span><span>(</span><span>WebApplicationContext</span> <span>wac</span><span>)</span> <span>{</span>
<span>try</span> <span>{</span>
<span>this</span><span>.</span><span>handlerMapping</span> <span>=</span> <span>(</span><span>HandlerMapping</span><span>)</span> <span>wac</span><span>.</span><span>getBean</span><span>(</span><span>HANDLER_MAPPING_BEAN_NAME</span><span>);</span>
<span>}</span> <span>catch</span> <span>(</span><span>BeansException</span> <span>e</span><span>)</span> <span>{</span>
<span>e</span><span>.</span><span>printStackTrace</span><span>();</span>
<span>}</span>
<span>}</span>
<span>protected</span> <span>void</span> <span>initHandlerMappings</span><span>(</span><span>WebApplicationContext</span> <span>wac</span><span>)</span> <span>{</span>
    <span>try</span> <span>{</span>
        <span>this</span><span>.</span><span>handlerMapping</span> <span>=</span> <span>(</span><span>HandlerMapping</span><span>)</span> <span>wac</span><span>.</span><span>getBean</span><span>(</span><span>HANDLER_MAPPING_BEAN_NAME</span><span>);</span>
    <span>}</span> <span>catch</span> <span>(</span><span>BeansException</span> <span>e</span><span>)</span> <span>{</span>
        <span>e</span><span>.</span><span>printStackTrace</span><span>();</span>
    <span>}</span>
<span>}</span>
protected void initHandlerMappings(WebApplicationContext wac) { try { this.handlerMapping = (HandlerMapping) wac.getBean(HANDLER_MAPPING_BEAN_NAME); } catch (BeansException e) { e.printStackTrace(); } }

Enter fullscreen mode Exit fullscreen mode

This integration provides:

  • Automatic bean management
  • Dependency injection for controllers
  • Configuration management

Example Usage

Here’s how to use the miniSpring MVC framework:

<span>@RequestMapping</span><span>(</span><span>"/hello"</span><span>)</span>
<span>public</span> <span>ModelAndView</span> <span>handleRequest</span><span>(</span><span>HttpServletRequest</span> <span>request</span><span>)</span> <span>{</span>
<span>String</span> <span>message</span> <span>=</span> <span>"Hello, World!"</span><span>;</span>
<span>ModelAndView</span> <span>mv</span> <span>=</span> <span>new</span> <span>ModelAndView</span><span>(</span><span>"hello"</span><span>);</span>
<span>mv</span><span>.</span><span>addObject</span><span>(</span><span>"message"</span><span>,</span> <span>message</span><span>);</span>
<span>return</span> <span>mv</span><span>;</span>
<span>}</span>
<span>@RequestMapping</span><span>(</span><span>"/hello"</span><span>)</span>
<span>public</span> <span>ModelAndView</span> <span>handleRequest</span><span>(</span><span>HttpServletRequest</span> <span>request</span><span>)</span> <span>{</span>
    <span>String</span> <span>message</span> <span>=</span> <span>"Hello, World!"</span><span>;</span>
    <span>ModelAndView</span> <span>mv</span> <span>=</span> <span>new</span> <span>ModelAndView</span><span>(</span><span>"hello"</span><span>);</span>
    <span>mv</span><span>.</span><span>addObject</span><span>(</span><span>"message"</span><span>,</span> <span>message</span><span>);</span>
    <span>return</span> <span>mv</span><span>;</span>
<span>}</span>
@RequestMapping("/hello") public ModelAndView handleRequest(HttpServletRequest request) { String message = "Hello, World!"; ModelAndView mv = new ModelAndView("hello"); mv.addObject("message", message); return mv; }

Enter fullscreen mode Exit fullscreen mode

And the corresponding configuration:

<span><bean</span> <span>class=</span><span>"com.yaruyng.web.servlet.SimpleUrlHandlerMapping"</span><span>></span>
<span><property</span> <span>name=</span><span>"mappings"</span><span>></span>
<span><props></span>
<span><prop</span> <span>key=</span><span>"/hello"</span><span>></span>helloController<span></prop></span>
<span></props></span>
<span></property></span>
<span></bean></span>
<span><bean</span> <span>class=</span><span>"com.yaruyng.web.servlet.SimpleUrlHandlerMapping"</span><span>></span>
    <span><property</span> <span>name=</span><span>"mappings"</span><span>></span>
        <span><props></span>
            <span><prop</span> <span>key=</span><span>"/hello"</span><span>></span>helloController<span></prop></span>
        <span></props></span>
    <span></property></span>
<span></bean></span>
<bean class="com.yaruyng.web.servlet.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/hello">helloController</prop> </props> </property> </bean>

Enter fullscreen mode Exit fullscreen mode

Performance Considerations

The implementation includes several performance optimizations:

  1. Single Front Controller: All request go through a single servlet
  2. Handler Caching: Handler methods are cached after first resolution
  3. View Caching: Resolved views are cached for reuse
  4. Efficient Request Processing: Minimal object creation per request

Extension Points

The framework provides several extension points:

  1. Custom Handler Mappings: Implement HandlerMapping interface
  2. Custom View Resolvers: Implement ViewResolver interface
  3. Custom Handler Adapters: Implement HandlerAdapter interface
  4. Custom Views: Implement View interface

Conclusion

This implementation of Spring MVC demonstrates:

  1. The power of the front controller pattern
  2. Clean separation of concerns through MVC
  3. Flexible handling of requests and responses
  4. Integration with IoC container
  5. Extensible architecture Key takeaways:
  6. Understanding Spring MVC’s internal structure
  7. How different components work together
  8. The importance of clean architecture
  9. Extension points for customization

The miniSpring MVC implementation provides a solid foundation for understanding how Spring MVC works internally while maintaining simplicity and clarity.

原文链接:Spring Architecture Series-3.Understanding Spring MVC Implementation

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
Happiness is not something you postpone for the future; it is something you design for the present.
幸福不应该留到未来品尝,幸福是你专门为当下的自己所准备的
评论 抢沙发

请登录后发表评论

    暂无评论内容