ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

150行实现SpringMVC核心代码

2021-02-25 09:33:14  阅读:204  来源: 互联网

标签:150 String SpringMVC 代码 Object mh Handler 处理器 public


SpringMVC的核心实现

实现效果:实现在浏chrom输入地址localhost:8080/toLogin.do进入servlet最终转发到html页面

项目包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g1g0MJK6-1614215863424)(smartMVC_files/1.png)]

实现步骤

# # 一:创建@RequestMapping注解->用于实现SpringMVC中的@RequestMapping注解

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

解释:
1)@Retention(RUNTIME)表示注解在运行期间有效
2)public String value () default中的value()为SpringMVC中的\hello
例:@RequestMapping("/toLogin.do")

# # 二:创建Handler类->方便利用java反射机制去调用一个对象的方法而设计的一个辅助类

Handler封装了:处理器实例已经对应的Method对象

	public class Handler {
		// obj:处理器实例
		private Object obj;
		// mh:方法
		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;
		}
		

	}

解释:
1)Object:存放处理器实例
2)Method:存放处理其实例中的方法

# # 三:创建HandlerMapping类->映射处理器->负责建立请求路径与处理器的对应关系

例:"/hello.do"应该由HelloControllerhello方法来处理
类设计:
成员变量:private Map<String,Handler>maps=new HashMap();
方法一·:public void process(List beans)
方法二· public Handler getHandler(String path)
1)maps用于存放请求路径和Handler的对应关系 key为请求路径 value为Handler对象

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

2)``HadlerMapping中核心方法process(List beans)`:负责变量存放对应关系

   // 传入DispatcherServlet中获得的List集合:List集合为处理器实例
   public void process(List beans) {
   		// for循环获取每一个处理器实例
   		for(Object bean:beans) {
   			// 反射拿到所有方法
   			Method[]methods=bean.getClass().getDeclaredMethods();
   			// 遍历获得的方法
   			for(Method mh:methods) {
   				// 获取加在方法前的@RequestMapping注解
   				RequestMapping rm=mh.getDeclaredAnnotation(RequestMapping.class);
   				// 如果注解为空就说明没有找到合适的处理器,为空
   				if(rm!=null) {
   					// 获取注解中的value 请求路径 /*.do
   					String path=rm.value();
   					// 将method对象以及处理器实例封装到Handler对象
   					Handler handler=new Handler();
   					handler.setMh(mh);
   					handler.setObj(bean);
   					// 以请求路径作为key,以Handler对象作为value
   					// 将对应关系添加到map里
   					maps.put(path,handler);
   					
   				}
   			}
   		}
   		System.out.println("maps:"+maps);
   	}

3)HadlerMappingget方法getHandler(String path)根据请求路径获取对应的处理器Handler

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

# # 四:DispatcherServlet方法也是SpringMVC中的核心方法,负责处理分发请求(前端控制器)DispatcherServlet为一个Servlet

成员变量:private HandlerMapping handlerMapping;
方法一:public void init() throws ServletException {}初始化方法
方法二:protected void service(HttpServletRequest request, HttpServletResponse response) {}用于分发请求
1)handlerMapping为存储请求路径value和处理的关系handler

	private HandlerMapping handlerMapping;

2)DispatcherServlet中核心方法也是初始化方法:用dom4j解析smartmvc.xml文件获取类全路径名,之后反射,存储Handler已经HandlerMapping也是一个初始化方法

	public void init() throws ServletException {
			try {
				SAXReader saxReader=new SAXReader();
				InputStream in=getClass()
						.getClassLoader()
						.getResourceAsStream("smartmvc.xml");
				Document doc=saxReader.read(in);
				// 获得根元素 <beans></beans>
				Element root=doc.getRootElement();
				// 获得根元素下面的所有子元素
				List beans=new ArrayList();
				List<Element>elements=root.elements();
				for(Element ele:elements) {
					// 获取处理器类名
					String className=ele.attributeValue("class");
					System.out.println("className:"+className);
					// 将处理器实例化
					Object bean=Class.forName(className);
					System.out.println(bean);
					beans.add(bean);
				}
				// 将处理器实例交给HandlerMapping来处理
				handlerMapping=new HandlerMapping();
				handlerMapping.process(beans);
				
			} catch (Exception e) {
				System.out.println("初始化失败:"+e);
				e.printStackTrace();
			}
		}

2.5)smartmvc.xml代码如下

	<?xml version="1.0" encoding="UTF-8"?>
	<beans>
		<!--
			配置处理器,其中,class属性用于指定处理器类名
		-->
		<bean class="controller.HelloController"/>
		<bean class="controller.LoginController"/>
	</beans>

xml文件通常存储反射对象的全路径名
3)DispatcherServlet中处理请求方法也是servlet中的处理业务的方法

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			// 现获得请求资源路径
			String uri=request.getRequestURI();
			System.out.println("uri:"+uri);
			// 获得应用名
			String contextPath=request.getContextPath();
			System.out.println("contextPath:"+contextPath);
			// 将请求路径中到应用名截取掉,生成请求路径
			String path=uri.substring(contextPath.length());
			System.out.println("path:"+path);
			
			// 依据请求路径获取对应掉Handler对象
			Handler handler=handlerMapping.getHandler(path);
			if(handler==null) {
				response.sendError(404);
				System.out.println("没有对应到处理器");
				return;
			}
			Object bean=handler.getObj();
			Method mh=handler.getMh();
			/**
			 * 获取处理器的方法
			 * 先获得处理器方法的参数类型信息
			 */
			Class[]types=mh.getParameterTypes();
			// 获得返回值
			Object rv=null;
			if(types.length>0) {
				// params用于存放实际参数
				Object[]params=new Object[types.length];
				// 依据参数类型进行相应的赋值
				for(int i=0;i<types.length;i++) {
					if(types[i]==HttpServletRequest.class) {
						params[i]=request;
					}
					if(types[i]==HttpServletResponse.class) {
						params[i]=response;
					}
				}
				// 处理器方法带参数
				rv=mh.invoke(bean, params);
			}else {
				// 处理器方法不带参数
				rv=mh.invoke(bean);
			}		
			// 获得视图名
			String viewName=rv.toString();
			System.out.println("viewName:"+viewName);
			/*
			 * 处理视图名
			 * 如果视图名是以"redirect:"开头,则重定向,否则
			 * 默认转发到 "/WEB-INF/"+视图名+".jsp"
			 */
			if(viewName.startsWith("redirect:")) {
				// 生成重定向地址
				String redirectPath=contextPath+"/"+viewName.substring("redirect:".length());
				// 重定向
				response.sendRedirect(redirectPath);
			}else {
				// 生成转发地址
				String forwardPath="/WEB-INF/"+viewName+".jsp";
				// 转发
				request.getRequestDispatcher(forwardPath).forward(request, response);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new ServletException(e);
		}
		
	}

# # 五:编写Controller类进行测试HelloController

	public class HelloController {
		
		@RequestMapping(value = "/hello.do")
		public String hello() {
			System.out.println("HelloController hello()");
			// 返回视图名
			return "hello";
		}	
	}

hello.jsp代码

	<%@ 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>

测试:在Chrom地址栏中敲入localhost:8080/hello.do就可以直接转发到hello.jsp了完成了SpringMVC的核心实现

实现思路:根据反射的api m.invoke(obj) m为方法 obj为类实例->通过Handler存储m和obj->HandlerMapping存储url和Handler的对应关系
最终实现(凑齐)m.invoke(obj)的参数实现代码

标签:150,String,SpringMVC,代码,Object,mh,Handler,处理器,public
来源: https://blog.csdn.net/weixin_48621005/article/details/114059622

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有