中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot與SpringMVC中參數傳遞的示例分析

發布時間:2021-07-28 15:09:27 來源:億速云 閱讀:146 作者:小新 欄目:開發技術

小編給大家分享一下SpringBoot與SpringMVC中參數傳遞的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

一:普通參數與基本注解

HandlerMapping中找到能處理請求的Handler(Controller,method())
為當前Handler找一個適配器HandlerAdapter:RequestMappingHandlerAdapter

SpringBoot與SpringMVC中參數傳遞的示例分析

1.HandlerAdapter

SpringBoot與SpringMVC中參數傳遞的示例分析

0-支持方法上標注@RequestMapping
1-支持函數式編程的
xxxx

2.執行目標方法

SpringBoot與SpringMVC中參數傳遞的示例分析
SpringBoot與SpringMVC中參數傳遞的示例分析

3.參數解析器:確定要執行的目標方法每一個參數的值是什么

SpringBoot與SpringMVC中參數傳遞的示例分析

SpringBoot與SpringMVC中參數傳遞的示例分析

boolean supportsParameter(MethodParameter parameter);
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
先判斷是否支持該參數類型, 如果支持, 就調用resolveArgument解析方法

4.返回值處理器

SpringBoot與SpringMVC中參數傳遞的示例分析

5.挨個判斷所有參數解析器哪個支持這個參數:HandlerMethodArgumentResolver: 把控著支持的方法參數類型

SpringBoot與SpringMVC中參數傳遞的示例分析

請求進來后, 首先從handlerMapping中查找是否有對應的映射處理, 得到映射適配器Adapter,再通過適配器,查找有哪些方法匹配請求,首先判斷方法名,以及參數類型是否匹配,首先獲得方法中聲明的參數名字, 放到數組里,循環遍歷27種解析器判斷是否有支持處理對應參數名字類型的解析器,如果有的話,根據名字進行解析參數,根據名字獲得域數據中的參數, 循環每個參數名字進行判斷, 從而為每個參數進行賦值.

對于自定義的POJO類參數:
ServletRequestMethodArgumentResolver 這個解析器用來解析: 是通過主要是通過判斷是否是簡單類型得到的

@Override
	public boolean supportsParameter(MethodParameter parameter) {
		return (parameter.hasParameterAnnotation(ModelAttribute.class) ||
				(this.annotationNotRequired && !BeanUtils.isSimpleProperty(parameter.getParameterType())));
	}
	
public static boolean isSimpleValueType(Class<?> type) {
		return (Void.class != type && void.class != type &&
				(ClassUtils.isPrimitiveOrWrapper(type) ||
				Enum.class.isAssignableFrom(type) ||
				CharSequence.class.isAssignableFrom(type) ||
				Number.class.isAssignableFrom(type) ||
				Date.class.isAssignableFrom(type) ||
				Temporal.class.isAssignableFrom(type) ||
				URI.class == type ||
				URL.class == type ||
				Locale.class == type ||
				Class.class == type));
	}


public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {

		Assert.state(mavContainer != null, "ModelAttributeMethodProcessor requires ModelAndViewContainer");
		Assert.state(binderFactory != null, "ModelAttributeMethodProcessor requires WebDataBinderFactory");

		String name = ModelFactory.getNameForParameter(parameter);
		ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class);
		if (ann != null) {
			mavContainer.setBinding(name, ann.binding());
		}

		Object attribute = null;
		BindingResult bindingResult = null;

		if (mavContainer.containsAttribute(name)) {
			attribute = mavContainer.getModel().get(name);
		}
		else {
			// Create attribute instance
			try {
				attribute = createAttribute(name, parameter, binderFactory, webRequest);
			}
			catch (BindException ex) {
				if (isBindExceptionRequired(parameter)) {
					// No BindingResult parameter -> fail with BindException
					throw ex;
				}
				// Otherwise, expose null/empty value and associated BindingResult
				if (parameter.getParameterType() == Optional.class) {
					attribute = Optional.empty();
				}
				else {
					attribute = ex.getTarget();
				}
				bindingResult = ex.getBindingResult();
			}
		}

		if (bindingResult == null) {
			// Bean property binding and validation;
			// skipped in case of binding failure on construction.
			WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
			if (binder.getTarget() != null) {
				if (!mavContainer.isBindingDisabled(name)) {
					bindRequestParameters(binder, webRequest);
				}
				validateIfApplicable(binder, parameter);
				if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
					throw new BindException(binder.getBindingResult());
				}
			}
			// Value type adaptation, also covering java.util.Optional
			if (!parameter.getParameterType().isInstance(attribute)) {
				attribute = binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter);
			}
			bindingResult = binder.getBindingResult();
		}

		// Add resolved attribute and BindingResult at the end of the model
		Map<String, Object> bindingResultModel = bindingResult.getModel();
		mavContainer.removeAttributes(bindingResultModel);
		mavContainer.addAllAttributes(bindingResultModel);

		return attribute;
	}

WebDataBinder binder =binderFactory.createBinder(webRequest,attribute,name)
WebDataBinder:web數據綁定器,將請求參數的值綁定到指定的javaBean里面
WebDataBinder 利用它里面的Converters將請求數據轉成指定的數據類型,通過反射一系列操作,再次封裝到javabean中

GenericConversionService:在設置每一個值的時候,找它里面所有的converter哪個可以將這個數據類型(request帶來參數的字符串)轉換到指定的類型(javabean—某一個類型)

SpringBoot與SpringMVC中參數傳遞的示例分析
SpringBoot與SpringMVC中參數傳遞的示例分析

未來我們可以給WebDataBinder里面放自己的Converter

private static final class StringToNumber implements Converter<String, T> {

converter總接口:
@FunctionalInterface
public interface Converter<S, T> {

//自定義轉換器:實現按照自己的規則給相應對象賦值

@Override
    public void addFormatters(FormatterRegistry registry) {
            registry.addConverter(new Converter<String, Pet>() {
                @Override
                public Pet convert(String source) {
                    if (!StringUtils.isEmpty(source)){
                        Pet pet = new Pet();
                        String[] split = source.split(",");
                        pet.setName(split[0]);
                        pet.setAge(split[1]);
                        return pet;
                    }

                    return null;
                }
            });
    }

二:復雜參數

Map/Model(map/model里面的數據會被放在request的請求域 相當于request.setAttribute)/Errors/BindingResult/RedirectAttributes(重定向攜帶數據)/ServletRespons().SessionStaus.UriComponentsBuilder

6.在上面第五步目標方法執行完成后:
將所有的數據都放在ModelAdnViewContainer;包含要去的頁面地址View,還包含Model數據

SpringBoot與SpringMVC中參數傳遞的示例分析

7.處理派發結果

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

在頁面進行響應前, 進行視圖渲染的時候:
exposeModelAsRequestAttributes(model, request); 該方法將model中所有參數都放在請求域數據中

protected void renderMergedOutputModel(
			Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		// Expose the model object as request attributes.
		exposeModelAsRequestAttributes(model, request);

		// Expose helpers as request attributes, if any.
		exposeHelpers(request);

		// Determine the path for the request dispatcher.
		String dispatcherPath = prepareForRendering(request, response);

		// Obtain a RequestDispatcher for the target resource (typically a JSP).
		RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
		if (rd == null) {
			throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
					"]: Check that the corresponding file exists within your web application archive!");
		}

		// If already included or response already committed, perform include, else forward.
		if (useInclude(request, response)) {
			response.setContentType(getContentType());
			if (logger.isDebugEnabled()) {
				logger.debug("Including [" + getUrl() + "]");
			}
			rd.include(request, response);
		}

		else {
			// Note: The forwarded resource is supposed to determine the content type itself.
			if (logger.isDebugEnabled()) {
				logger.debug("Forwarding to [" + getUrl() + "]");
			}
			rd.forward(request, response);
		}
	}

通過循環遍歷model中的所有數據放在請求域中

protected void exposeModelAsRequestAttributes(Map<String, Object> model,
			HttpServletRequest request) throws Exception {
		
		model.forEach((name, value) -> {
			if (value != null) {
				request.setAttribute(name, value);
			}
			else {
				request.removeAttribute(name);
			}
		});
	}

不管我們在方法形參位置放 Map集合或者Molde 最終在底層源碼都是同一個對象在mvcContainer容器中進行保存

以上是“SpringBoot與SpringMVC中參數傳遞的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

保定市| 新野县| 兴文县| 平湖市| 北流市| 洞头县| 浠水县| 隆尧县| 乌拉特前旗| 鹤山市| 若尔盖县| 竹北市| 襄城县| 栾城县| 株洲县| 图木舒克市| 金阳县| 缙云县| 河池市| 岳阳县| 郎溪县| 靖州| 桐乡市| 海伦市| 广河县| 泉州市| 韩城市| 沛县| 阳春市| 邓州市| 龙岩市| 奉新县| 南汇区| 辽宁省| 昌黎县| 泰和县| 清苑县| 略阳县| 麻栗坡县| 巴里| 新乡市|