The core implementation of spring MVC

The core implementation of spring MVC

Implementation effect: enter the address localhost: 8080 / tologin in chrom e Do enters the servlet and finally forwards it to the html page

Project package
[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-g1g0MJK6-1614215863424)(smartMVC_files/1.png)]
Implementation steps

## 1: create @ RequestMapping annotation - > used to implement @ RequestMapping annotation in spring MVC

	@Retention(RUNTIME)
	public @interface RequestMapping {
	
		public String value () default "";
	
	
	}

Explanation:
1)@Retention(RUNTIME) indicates that the annotation is valid during runtime
2) Public string value() value() in default is the \ hello value in spring MVC
Example: @ RequestMapping("/toLogin.do")

## 2: create Handler class - > an auxiliary class designed to facilitate the use of java reflection mechanism to call the method of an object

Handler encapsulates the Method object corresponding to the processor instance

	public class Handler {
		// obj: processor instance
		private Object obj;
		// mh: method
		private Method mh;
		public Object getObj() {
			return obj;
		}
		public void setObj(Object obj) {
			this.obj = obj;
		}
		public Method getMh() {
			return mh;
		}
		public void setMh(Method mh) {
			this.mh = mh;
		}
		

	}

Explanation:
1)Object: store processor instances
2)Method: store and process the methods in its instance

## 3: create HandlerMapping class - > mapping processor - > responsible for establishing the corresponding relationship between the request path and the processor

Example: "/ hello.do" should be handled by HelloController's hello method
Class design:
Member variable: private map < string, handler > maps = new hashmap();
Method 1: public void process(List beans)
Method 2. public Handler getHandler(String path)
1)maps is used to store the correspondence between the request path and the Handler. key is the request path and value is the Handler object

   private Map<String,Handler>maps=new HashMap();

2)``HadlerMapping's core method process(List beans) `: it is responsible for storing the corresponding relationship of variables

   // Pass in the List set obtained in the dispatcher servlet: the List set is the processor instance
   public void process(List beans) {
   		// The for loop gets each processor instance
   		for(Object bean:beans) {
   			// Reflect all methods
   			Method[]methods=bean.getClass().getDeclaredMethods();
   			// Traversal method
   			for(Method mh:methods) {
   				// Get the @ RequestMapping annotation before the method
   				RequestMapping rm=mh.getDeclaredAnnotation(RequestMapping.class);
   				// If the comment is empty, it means that no suitable processor has been found
   				if(rm!=null) {
   					// Get the value request path in the annotation / * do
   					String path=rm.value();
   					// Encapsulate the method object and the processor instance into the Handler object
   					Handler handler=new Handler();
   					handler.setMh(mh);
   					handler.setObj(bean);
   					// Take the request path as the key and the Handler object as the value
   					// Add correspondence to map
   					maps.put(path,handler);
   					
   				}
   			}
   		}
   		System.out.println("maps:"+maps);
   	}

3) The get method getHandler(String path) in hadlermapping obtains the corresponding processor Handler according to the request path

    public Handler getHandler(String path) {
   		return maps.get(path);
   }

## 4: the DispatcherServlet method is also the core method in spring MVC, which is responsible for processing distribution requests (front-end controller). The DispatcherServlet is a Servlet

Member variable: private HandlerMapping handlerMapping;
Method 1: public void init() throws ServletException {} initialization method
Method 2: protected void service (HttpServletRequest, httpservletresponse) {} is used to distribute requests
1)handlerMapping is the handler that stores the relationship between the request path value and processing

	private HandlerMapping handlerMapping;

2) The core method in dispatcher servlet is also the initialization method: parsing smartmvc with dom4j Get the full path name of the class from the XML file, and then reflect that the Handler has been stored. HandlerMapping is also an initialization method

	public void init() throws ServletException {
			try {
				SAXReader saxReader=new SAXReader();
				InputStream in=getClass()
						.getClassLoader()
						.getResourceAsStream("smartmvc.xml");
				Document doc=saxReader.read(in);
				// Get root element < beans > < / beans >
				Element root=doc.getRootElement();
				// Get all child elements below the root element
				List beans=new ArrayList();
				List<Element>elements=root.elements();
				for(Element ele:elements) {
					// Get processor class name
					String className=ele.attributeValue("class");
					System.out.println("className:"+className);
					// Instantiate processor
					Object bean=Class.forName(className);
					System.out.println(bean);
					beans.add(bean);
				}
				// Hand over the processor instance to HandlerMapping for processing
				handlerMapping=new HandlerMapping();
				handlerMapping.process(beans);
				
			} catch (Exception e) {
				System.out.println("initialization failed:"+e);
				e.printStackTrace();
			}
		}

2.5)smartmvc. The XML code is as follows

	<?xml version="1.0" encoding="UTF-8"?>
	<beans>
		<!--
			Configure the processor, where, class Property specifies the processor class name
		-->
		<bean class="controller.HelloController"/>
		<bean class="controller.LoginController"/>
	</beans>

The xml file usually stores the full pathname of the reflection object
3) The method of processing requests in dispatcher servlet is also the method of processing business in servlet

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			// Now get the requested resource path
			String uri=request.getRequestURI();
			System.out.println("uri:"+uri);
			// Get app name
			String contextPath=request.getContextPath();
			System.out.println("contextPath:"+contextPath);
			// Intercept the application name from the request path to generate the request path
			String path=uri.substring(contextPath.length());
			System.out.println("path:"+path);
			
			// Get the corresponding Handler object according to the request path
			Handler handler=handlerMapping.getHandler(path);
			if(handler==null) {
				response.sendError(404);
				System.out.println("No corresponding processor");
				return;
			}
			Object bean=handler.getObj();
			Method mh=handler.getMh();
			/**
			 * Method of obtaining processor
			 * First obtain the parameter type information of the processor method
			 */
			Class[]types=mh.getParameterTypes();
			// Get return value
			Object rv=null;
			if(types.length>0) {
				// params is used to store actual parameters
				Object[]params=new Object[types.length];
				// Assign values according to the parameter type
				for(int i=0;i<types.length;i++) {
					if(types[i]==HttpServletRequest.class) {
						params[i]=request;
					}
					if(types[i]==HttpServletResponse.class) {
						params[i]=response;
					}
				}
				// Processor method with parameters
				rv=mh.invoke(bean, params);
			}else {
				// Processor method without parameters
				rv=mh.invoke(bean);
			}		
			// Get view name
			String viewName=rv.toString();
			System.out.println("viewName:"+viewName);
			/*
			 * Process view name
			 * If the view name starts with "redirect:", it will be redirected; otherwise
			 * Default forward to "/ Web inf / + view name +". jsp "
			 */
			if(viewName.startsWith("redirect:")) {
				// Generate redirect address
				String redirectPath=contextPath+"/"+viewName.substring("redirect:".length());
				// redirect
				response.sendRedirect(redirectPath);
			}else {
				// Generate forwarding address
				String forwardPath="/WEB-INF/"+viewName+".jsp";
				// forward
				request.getRequestDispatcher(forwardPath).forward(request, response);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new ServletException(e);
		}
		
	}

## 5: write Controller class to test HelloController

	public class HelloController {
		
		@RequestMapping(value = "/hello.do")
		public String hello() {
			System.out.println("HelloController hello()");
			// Return view name
			return "hello";
		}	
	}

hello.jsp code

	<%@ page language="java" contentType="text/html; charset=UTF-8"
	    pageEncoding="UTF-8"%>
	<!DOCTYPE html>
	<html>
	<head>
	<meta charset="UTF-8">
	<title>Insert title here</title>
	</head>
	<body>
		Hello SmartMVC
	</body>
	</html>

Test: type localhost: 8080 / Hello. In the chrome address bar Do can be forwarded directly to hello JSP completes the core implementation of spring MVC

Implementation idea: according to the reflected API, m.invoke (obj) m is the method, obj is the class instance - > store m through Handler and obj - > handlermapping to store the corresponding relationship between url and Handler
Finally, the parameter implementation code of m.invoke(obj) is implemented (rounded up)

Tags: Java Spring

Posted by hubfub on Sat, 16 Apr 2022 05:42:06 +0930