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)