最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SSM框架流程及原理分析

 更新時(shí)間:2021年06月07日 16:33:31   作者:AAAhxz  
本文給大家分享小編一些心得體會(huì),主要是學(xué)習(xí)SSM框架之后的收獲吧,重點(diǎn)給大家介紹SSM框架流程以及原理分析,通過(guò)圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),需要的朋友參考下吧

前言:學(xué)ssm框架已經(jīng)有很長(zhǎng)時(shí)間,今天來(lái)復(fù)習(xí)一下
SSM圖示流程:

在這里插入圖片描述

Spring核心:Java反射
Mybatis:動(dòng)態(tài)代理,而動(dòng)態(tài)代理又是基于反射的,所以,ssm框架核心原理在反射。
(1)Spring(對(duì)象工廠): 平時(shí)開(kāi)發(fā)接觸最多的估計(jì)就是這個(gè)IOC容器,它可以裝載bean(也就是Java中的類,當(dāng)然也包括service、dao里面的),有了這個(gè)機(jī)制,就不用在每次使用這個(gè)類的時(shí)候?yàn)樗跏蓟?,很少看到關(guān)鍵字new。
(2)SpringMVC(視圖控制器): 核心為一個(gè)DispatcherServlet,控制所有請(qǐng)求
這里奉上手寫SpringMVC的核心DispatcherServlet源碼

package servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import annotation.HController;
import annotation.HRequestMapping;

/**
 * 手寫SpringMVC
 * 
 * @author hxz
 * @description TODO
 * @data 2020年1月2日 上午9:39:57
 */
public class MyDispatcherServlet extends HttpServlet {
   //加載屬性文件
	private Properties properties = new Properties();
    //裝載beanname
	private List<String> classNames = new ArrayList<String>();
	//ioc容器
	private Map<String, Object> ioc = new HashMap<String, Object>();
    //類似于以前自定義的cache緩存容器,這里也是起到一個(gè)容器的作用
    //用于加載各個(gè)mapping
	private Map<String, Method> handlerMapping = new HashMap<String, Method>();
    //容器加載所有的controller
	private Map<String, Object> controllerMap = new HashMap<String, Object>();

	@Override
	public void init(ServletConfig config) throws ServletException {

		// 1.加載配置文件
		doLoadConfig(config.getInitParameter("contextConfigLocation"));

		// 2.初始化所有相關(guān)聯(lián)的類,掃描用戶設(shè)定的包下面所有的類
		doScanner(properties.getProperty("scanPackage"));

		// 3.拿到掃描到的類,通過(guò)反射機(jī)制,實(shí)例化,并且放到ioc容器中beanName默認(rèn)是首字母小寫
		doInstance();

		// 4.初始化HandlerMapping(將url和method對(duì)應(yīng)上)
		initHandlerMapping();

	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		try {
			// 處理請(qǐng)求
			doDispatch(req, resp);
		} catch (Exception e) {
			resp.getWriter().write("500!! Server Exception");
		}

	}

	private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		if (handlerMapping.isEmpty()) {
			return;
		}

		String url = req.getRequestURI();
		String contextPath = req.getContextPath();

		url = url.replace(contextPath, "").replaceAll("/+", "/");

		if (!this.handlerMapping.containsKey(url)) {
			resp.getWriter().write("404 NOT FOUND!");
			return;
		}

		Method method = this.handlerMapping.get(url);

		// 獲取方法的參數(shù)列表
		Class<?>[] parameterTypes = method.getParameterTypes();

		// 獲取請(qǐng)求的參數(shù)
		Map<String, String[]> parameterMap = req.getParameterMap();

		// 保存參數(shù)值
		Object[] paramValues = new Object[parameterTypes.length];

		// 方法的參數(shù)列表
		for (int i = 0; i < parameterTypes.length; i++) {
			// 根據(jù)參數(shù)名稱,做某些處理
			String requestParam = parameterTypes[i].getSimpleName();

			if (requestParam.equals("HttpServletRequest")) {
				// 參數(shù)類型已明確,這邊強(qiáng)轉(zhuǎn)類型
				paramValues[i] = req;
				continue;
			}
			if (requestParam.equals("HttpServletResponse")) {
				paramValues[i] = resp;
				continue;
			}
			if (requestParam.equals("String")) {
				for (Entry<String, String[]> param : parameterMap.entrySet()) {
					String value = Arrays.toString(param.getValue()).replaceAll("\\[|\\]", "").replaceAll(",\\s", ",");
					paramValues[i] = value;
				}
			}
		}
		// 利用反射機(jī)制來(lái)調(diào)用
		try {
			method.invoke(this.controllerMap.get(url), paramValues);// 第一個(gè)參數(shù)是method所對(duì)應(yīng)的實(shí)例
																	// 在ioc容器中
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void doLoadConfig(String location) {
		// 把web.xml中的contextConfigLocation對(duì)應(yīng)value值的文件加載到流里面
		InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(location);
		try {
			// 用Properties文件加載文件里的內(nèi)容
			properties.load(resourceAsStream);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 關(guān)流
			if (null != resourceAsStream) {
				try {
					resourceAsStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	private void doScanner(String packageName) {
		// 把所有的.替換成/
		URL url = this.getClass().getClassLoader().getResource("/" + packageName.replaceAll("\\.", "/"));
		File dir = new File(url.getFile());
		for (File file : dir.listFiles()) {
			if (file.isDirectory()) {
				// 遞歸讀取包
				doScanner(packageName + "." + file.getName());
			} else {
				String className = packageName + "." + file.getName().replace(".class", "");
				classNames.add(className);
			}
		}
	}
	//利用java的反射機(jī)制
	private void doInstance() {
		if (classNames.isEmpty()) {
			return;
		}
		for (String className : classNames) {
			try {
				// 把類搞出來(lái),反射來(lái)實(shí)例化
				Class<?> clazz = Class.forName(className);
				if (clazz.isAnnotationPresent(HController.class)) {
					ioc.put(toLowerFirstWord(clazz.getSimpleName()), clazz.newInstance());
				} else {
					continue;
				}

			} catch (Exception e) {
				e.printStackTrace();
				continue;
			}
		}
	}

	private void initHandlerMapping() {
		if (ioc.isEmpty()) {
			return;
		}
		try {
		    
			for (Entry<String, Object> entry : ioc.entrySet()) {
				Class<? extends Object> clazz = entry.getValue().getClass();
				if (!clazz.isAnnotationPresent(HController.class)) {
					continue;
				}

				// 拼url時(shí),是controller頭的url拼上方法上的url
				String baseUrl = "";
				if (clazz.isAnnotationPresent(HRequestMapping.class)) {
					HRequestMapping annotation = clazz.getAnnotation(HRequestMapping.class);
					baseUrl = annotation.value();
				}
				Method[] methods = clazz.getMethods();
				for (Method method : methods) {
					if (!method.isAnnotationPresent(HRequestMapping.class)) {
						continue;
					}
					HRequestMapping annotation = method.getAnnotation(HRequestMapping.class);
					String url = annotation.value();

					url = (baseUrl + "/" + url).replaceAll("/+", "/");
					handlerMapping.put(url, method);
					controllerMap.put(url, clazz.newInstance());
					System.out.println(url + "," + method);
				}

			}

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * 把字符串的首字母小寫
	 * 
	 * @param name
	 * @return
	 */
	private String toLowerFirstWord(String name) {
		char[] charArray = name.toCharArray();
		charArray[0] += 32;
		return String.valueOf(charArray);
	}

}

從源碼及可看出流程:
1)客戶端發(fā)送請(qǐng)求到DispacherServlet(由web.xml攔截所有請(qǐng)求到改servlet);

2)由DispacherServlet(核心servlet)控制器查詢HanderMapping,找到處理請(qǐng)求的Controller;(這里我用了一個(gè)map類似于緩存容器,裝載所有的mapping即映射)

3)Controller層調(diào)用業(yè)務(wù)邏輯處理后,返回ModelAndView,即下一層(往往是service、serviceimpl,mapper層)返回的的數(shù)據(jù);

4)DispacherSerclet查詢視圖解析器,找到ModelAndView指定的視圖;

5)視圖負(fù)責(zé)將結(jié)果顯示到客戶端。
(3)Mybatis(持久層框架):mybatis是對(duì)jdbc的封裝,它讓數(shù)據(jù)庫(kù)底層操作變的透明。mybatis的操作都是圍繞一個(gè)sqlSessionFactory實(shí)例展開(kāi)的。mybatis通過(guò)配置文件關(guān)聯(lián)到各實(shí)體類的Mapper文件,Mapper文件中配置了每個(gè)類對(duì)數(shù)據(jù)庫(kù)所需進(jìn)行的sql語(yǔ)句映射。在每次與數(shù)據(jù)庫(kù)交互時(shí),通過(guò)sqlSessionFactory拿到一個(gè)sqlSession,再通過(guò)得到Mapper文件sqlSession.getMapper()最后調(diào)用的是JDK的動(dòng)態(tài)代理(exlipse一直Ctrl+鼠標(biāo)左鍵點(diǎn)擊到最后發(fā)現(xiàn)如此,源碼附上)。

 protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);

發(fā)人員只需要?jiǎng)?chuàng)建Mapper接口,并使用Mapper接口即可。Mybatis會(huì)對(duì)Mapper接口產(chǎn)生動(dòng)態(tài)代理對(duì)象,這個(gè)動(dòng)態(tài)代理對(duì)象實(shí)現(xiàn)了Mapper接口,擁有Mapper中定義的所有方法,并對(duì)這些方法進(jìn)行了增強(qiáng)。增強(qiáng)的邏輯是獲得sql語(yǔ)句和執(zhí)行sql語(yǔ)句。
動(dòng)態(tài)代理:

  • 通過(guò)實(shí)現(xiàn) InvocationHandler 接口創(chuàng)建自己的調(diào)用處理器;
  • 通過(guò)為 Proxy 類指定 ClassLoader 對(duì)象和一組 interface 來(lái)創(chuàng)建動(dòng)態(tài)代理類;
  • 通過(guò)反射機(jī)制獲得動(dòng)態(tài)代理類的構(gòu)造函數(shù),其唯一參數(shù)類型是調(diào)用處理器接口類型;
  • 通過(guò)構(gòu)造函數(shù)創(chuàng)建動(dòng)態(tài)代理類實(shí)例,構(gòu)造時(shí)調(diào)用處理器對(duì)象作為參數(shù)被傳入。

框架核心原理

  • AOP 面向切面編程(AOP)提供另外一種角度來(lái)思考程序結(jié)構(gòu),通過(guò)這種方式彌補(bǔ)了面向?qū)ο缶幊蹋∣OP)的不足。除了類(classes)以外,AOP提供了切面。切面對(duì)關(guān)注點(diǎn)進(jìn)行模塊化,例如橫切多個(gè)類型和對(duì)象的事務(wù)管理。Spring的一個(gè)關(guān)鍵的組件就是AOP框架,可以自由選擇是否使用AOP。提供聲明式企業(yè)服務(wù),特別是為了替代EJB聲明式服務(wù)。最重要的服務(wù)是聲明性事務(wù)管理,這個(gè)服務(wù)建立在Spring的抽象事物管理之上。允許用戶實(shí)現(xiàn)自定義切面,用AOP來(lái)完善OOP的使用可以把Spring AOP看作是對(duì)Spring的一種增強(qiáng)。AOP的實(shí)現(xiàn)乃至spring框架基本上核心代碼都是基于Java語(yǔ)言的反射機(jī)制(所謂的反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意方法和屬性;這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象方法的功能稱為java語(yǔ)言的反射機(jī)制。)。
  • AOP主要作用就是不通過(guò)修改源代碼的方式、將非核心功能代碼織入來(lái)實(shí)現(xiàn)對(duì)方法的增強(qiáng)。那么Spring AOP的底層如何實(shí)現(xiàn)對(duì)方法的增強(qiáng)?實(shí)現(xiàn)的關(guān)鍵在于使用了代理模式。代理模式的作用就是為其它對(duì)象提供一種代理,以控制對(duì)這個(gè)對(duì)象的訪問(wèn),用于解決在直接訪問(wèn)對(duì)象時(shí)帶來(lái)的各種問(wèn)題,比如要訪問(wèn)的對(duì)象在遠(yuǎn)程的機(jī)器上。在面向?qū)ο笙到y(tǒng)中,由于其他某些原因(對(duì)象創(chuàng)建開(kāi)銷很大,或者某些操作需要安全控制,或者需要進(jìn)程外的訪問(wèn))等
  • 代理主要分為兩種方式:靜態(tài)代理和動(dòng)態(tài)代理
  • IOC IoC不是一種技術(shù),只是一種思想,一個(gè)重要的面向?qū)ο缶幊痰姆▌t,它能指導(dǎo)我們?nèi)绾卧O(shè)計(jì)出松耦合、更優(yōu)良的程序。有了IoC容器后,把創(chuàng)建和查找依賴對(duì)象的控制權(quán)交給了容器,由容器進(jìn)行注入組合對(duì)象,所以相較于傳統(tǒng)的java servlet需要自己request.getParamiter等需要一系列取值,轉(zhuǎn)換中文,轉(zhuǎn)換值類型的繁瑣,更重要的是使得程序的整個(gè)體系結(jié)構(gòu)變得非常靈活。
  • 自定義一個(gè)IOC容器的思路:
  • Map做一個(gè)容器,然后用解析xml文件的工具解析出需要掃描的包。利用Java反射機(jī)制拿到鎖具有的方法,屬性,注入到Map容器中
  • DI 依賴注入,是組件之間依賴關(guān)系由容器在運(yùn)行期決定,形象的說(shuō),即由容器動(dòng)態(tài)地將某個(gè)依賴關(guān)系注入到組件之中。依賴注入的目的并非為軟件系統(tǒng)帶來(lái)更多功能,而是為了提升組件重用的頻率,并為系統(tǒng)搭建一個(gè)靈活、可擴(kuò)展的平臺(tái)。通過(guò)依賴注入機(jī)制,我們只需要通過(guò)簡(jiǎn)單的配置,而無(wú)需任何代碼就可指定目標(biāo)需要的資源,完成自身的業(yè)務(wù)邏輯,而不需要關(guān)心具體的資源來(lái)自何處,由誰(shuí)實(shí)現(xiàn)。

以上就是深入淺出SSM框架流程以及原理的詳細(xì)內(nèi)容,更多關(guān)于SSM框架原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java 日志的數(shù)據(jù)脫敏的實(shí)現(xiàn)方法

    java 日志的數(shù)據(jù)脫敏的實(shí)現(xiàn)方法

    今日給大家介紹一下java 日志的數(shù)據(jù)脫敏的實(shí)現(xiàn)方法,可以更好的保護(hù)數(shù)據(jù)的安全,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • HashMap和Hashtable的詳細(xì)比較

    HashMap和Hashtable的詳細(xì)比較

    這篇文章主要介紹了HashMap和Hashtable的詳細(xì)比較的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • MyBatis結(jié)果映射(ResultMap)的使用

    MyBatis結(jié)果映射(ResultMap)的使用

    在MyBatis中,結(jié)果映射是實(shí)現(xiàn)數(shù)據(jù)庫(kù)結(jié)果集到Java對(duì)象映射的核心,它不僅支持簡(jiǎn)單的字段映射,還能處理字段名不一致、嵌套對(duì)象和集合映射等復(fù)雜場(chǎng)景,通過(guò)ResultMap,開(kāi)發(fā)者可以靈活定義映射關(guān)系,以適應(yīng)各種需求,感興趣的可以了解一下
    2024-09-09
  • 使用jpa之動(dòng)態(tài)插入與修改(重寫save)

    使用jpa之動(dòng)態(tài)插入與修改(重寫save)

    這篇文章主要介紹了使用jpa之動(dòng)態(tài)插入與修改(重寫save),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java判斷對(duì)象是否為空的四種方法小結(jié)

    Java判斷對(duì)象是否為空的四種方法小結(jié)

    這篇文章主要介紹了Java判斷對(duì)象是否為空的四種方法,判斷對(duì)象是否為空有多種方法,包括使用==或!=運(yùn)算符直接比較對(duì)象與null,使用Objects.isNull()方法,以及用instanceof運(yùn)算符或Optional類進(jìn)行更安全的空值處理,需要的朋友可以參考下
    2024-10-10
  • Java8中stream和functional interface的配合使用詳解

    Java8中stream和functional interface的配合使用詳解

    這篇文章主要給大家介紹了關(guān)于Java8中stream和functional interface配合使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java8具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-11-11
  • JAVA讀取PDF、WORD文檔實(shí)例代碼

    JAVA讀取PDF、WORD文檔實(shí)例代碼

    本篇文章主要通過(guò)實(shí)例代碼介紹了JAVA讀取PDF、WORD文檔,需要的朋友可以參考下
    2017-04-04
  • SpringBoot項(xiàng)目部署在weblogic中間件的注意事項(xiàng)說(shuō)明

    SpringBoot項(xiàng)目部署在weblogic中間件的注意事項(xiàng)說(shuō)明

    這篇文章主要介紹了SpringBoot項(xiàng)目部署在weblogic中間件的注意事項(xiàng)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Idea導(dǎo)入eureka源碼實(shí)現(xiàn)過(guò)程解析

    Idea導(dǎo)入eureka源碼實(shí)現(xiàn)過(guò)程解析

    這篇文章主要介紹了Idea導(dǎo)入eureka源碼實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • JDK源碼分析之String、StringBuilder和StringBuffer

    JDK源碼分析之String、StringBuilder和StringBuffer

    這篇文章主要給大家介紹了關(guān)于JDK源碼分析之String、StringBuilder和StringBuffer的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用jdk具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05

最新評(píng)論

芒康县| 韶山市| 凌源市| 珲春市| 神农架林区| 新丰县| 钟祥市| 博客| 六盘水市| 读书| 南康市| 论坛| 临泉县| 乐山市| 怀仁县| 廉江市| 福鼎市| 天水市| 金山区| 禹州市| 麻栗坡县| 普陀区| 西平县| 荆门市| 长岭县| 吴川市| 喀喇| 长治县| 周至县| 区。| 碌曲县| 江孜县| 望城县| 且末县| 资兴市| 六安市| 乐山市| 会理县| 垣曲县| 固始县| 兴山县|