CFSDN nhấn mạnh vào giá trị tạo ra nguồn mở và chúng tôi cam kết xây dựng nền tảng chia sẻ tài nguyên để mọi nhân viên CNTT có thể tìm thấy thế giới tuyệt vời của bạn tại đây.
Bài blog CFSDN này tổng hợp các kiến thức liên quan đến ràng buộc tham số SpringMVC được tác giả sưu tầm và biên soạn. Nếu các bạn quan tâm tới bài viết này thì nhớ like nhé.
Sau khi yêu cầu nhập doDispatch của DispatcherServlet, hãy lấy HandlerMethod. Sau đó xác nhận HandlerApapter theo HandlerMethod và thực thi phương thức xử lý của HandlerAdapter sau khi xác nhận. Ở đây xác nhận rằng HandlerApater làRequestMappingHandlerAdapter. Trước khi thực thi handlerMethod, việc ràng buộc các tham số cần phải được xử lý.
1. Ràng buộc tham số đơn giản
Sau khi thực thi phương thức xử lý của HandlerAdapter, hãy nhập phương thứcgọiHandleMethod của AskMappingHandlerAdapter.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
riêng tư
ModelAndView invokeHandleMethod(HttpServletRequest yêu cầu,
Phản hồi HttpServletResponse, HandlerMethod handlerMethod)
ném
Ngoại lệ {
ServletWebRequest webYêu cầu =
mới
ServletWebRequest(yêu cầu, phản hồi);
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
Phương thức ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);
ModelAndViewContainer mavContainer =
mới
ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(yêu cầu));
modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(
cái này
.ignoreDefaultModelOnRedirect);
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(yêu cầu, phản hồi);
asyncWebRequest. đặt thời gian chờ(
cái này
.asyncRequestTimeout);
cuối cùng
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(yêu cầu);
asyncManager.setTaskExecutor(
cái này
.taskExecutor);
asyncManager. setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(
cái này
.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(
cái này
.deferredResultInterceptors);
nếu như
(asyncManager.hasConcurrentResult()) {
Đối tượng result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[
0
];
asyncManager.clearConcurrentResult();
nếu như
(logger.isDebugEnabled()) {
logger.debug(
"Đã tìm thấy giá trị kết quả đồng thời ["
+ kết quả +
"]"
);
}
requestMappingMethod = requestMappingMethod.wrapConcurrentResult(kết quả);
}
requestMappingMethod.invokeAndHandle(webRequest, mavContainer);
nếu như
(asyncManager.isConcurrentHandlingStarted()) {
trở lại
vô giá trị
;
}
trở lại
getModelAndView(mavContainer, modelFactory, webRequest);
}
|
Sau đó, nhập phương thứcgọiAndHanldle, rồi nhập phương thứcgọiForRequest. Trách nhiệm của phương thức này là phân tích các tham số mà phương thức HandlerMethod yêu cầu từ yêu cầu, sau đó gọi phương thức trong HandlerMethod thông qua sự phản chiếu.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
|
công cộng
cuối cùng
Đối tượng invokeForRequest(NativeWebRequest yêu cầu,
ModelAndViewContainer mavContainer, Object... providedArgs)
ném
Ngoại lệ {
Đối tượng[] args = getMethodArgumentValues(yêu cầu, mavContainer, providedArgs);
nếu như
(logger.isTraceEnabled()) {
Trình xây dựng StringBuilder =
mới
Trình tạo chuỗi(
"Đang triệu hồi ["
);
builder.append(
cái này
.getMethod().getName()).thêm(
"] phương pháp với các đối số "
);
builder.append(Mảng.asList(đối số));
logger.trace(builder.toString());
}
Đối tượng returnValue = invoke(args);
nếu như
(logger.isTraceEnabled()) {
logger.trace(
"Phương pháp ["
+
cái này
.getMethod().getName() +
"] đã trả lại ["
+ trả vềGiá trị +
"]"
);
}
trở lại
giá trị trả về;
}
|
Nhập phương thức getMethodArgumentValues.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
riêng tư
Đối tượng[] getMethodArgumentValues(
Yêu cầu NativeWebRequest, ModelAndViewContainer mavContainer, Object... providedArgs)
ném
Ngoại lệ {
MethodParameter[] tham số = getMethodParameters();
Đối tượng[] args =
mới
Đối tượng[tham số.chiều dài];
vì
(
số nguyên
tôi =
0
; i < tham số.chiều dài; i++) {
MethodParameter tham số = tham số[i];
tham số.initParameterNameDiscovery(parameterNameDiscoverer);
GenericTypeResolver.resolveParameterType(tham số, getBean().getClass());
args[i] = resolveProvidedArgument(tham số, providedArgs);
nếu như
(đối số[i] !=
vô giá trị
) {
Tiếp tục
;
}
nếu như
(argumentResolvers.supportsParameter(tham số)) {
thử
{
args[i] = argumentResolvers.resolveArgument(tham số, mavContainer, yêu cầu, dataBinderFactory);
Tiếp tục
;
}
nắm lấy
(Ngoại lệ cũ) {
nếu như
(logger.isTraceEnabled()) {
logger.trace(getArgumentResolutionErrorMessage(
"Lỗi khi giải quyết đối số"
, i), ví dụ);
}
ném
bán tại;
}
}
nếu như
(đối số[i] ==
vô giá trị
) { Chuỗi msg = getArgumentResolutionErrorMessage(
"Không có giải pháp phù hợp cho lập luận"
, Tôi);
ném
mới
Ngoại lệ bất hợp pháp (tin nhắn);
}
}
trở lại
các đối số;
}
|
Nhập phương thức ResolveArgument của HandlerMethodArgumentResolverComposite.
?
1
2
3
4
5
6
7
8
9
10
|
công cộng
Đối tượng resolveArgument(
Tham số MethodParameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
ném
Ngoại lệ {
Trình giải quyết HandlerMethodArgumentResolver = getArgumentResolver(tham số);
Assert.notNull(trình giải quyết,
"Loại tham số không xác định ["
+ tham số.getParameterType().getName() +
"]"
);
trở lại
resolver.resolveArgument(tham số, mavContainer, webRequest, binderFactory);
}
|
Sau đó nhập phương thức ResolverArgument của HandlerMethodArgumentResolver.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
công cộng
cuối cùng
Đối tượng resolveArgument(
Tham số MethodParameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
ném
Ngoại lệ {
Lớp > paramType = tham số.getParameterType();
NamedValueInfo namedValueInfo = getNamedValueInfo(tham số);
Đối tượng arg = resolveName(namedValueInfo.name, tham số, webRequest);
nếu như
(đối số ==
vô giá trị
) {
nếu như
(namedValueInfo.defaultValue !=
vô giá trị
) {
đối số = giải quyếtDefaultValue(namedValueInfo.defaultValue);
}
khác
nếu như
(namedValueInfo.required) {
handleMissingValue(namedValueInfo.name, tham số);
}
arg = handleNullValue(namedValueInfo.name, arg, paramType);
}
khác
nếu như
(
""
.equals(arg) && (namedValueInfo.defaultValue !=
vô giá trị
)) {
đối số = giải quyếtDefaultValue(namedValueInfo.defaultValue);
}
nếu như
(Nhà máy binder !=
vô giá trị
) {
Trình liên kết WebDataBinder = binderFactory.createBinder(webRequest,
vô giá trị
, namedValueInfo.name);
arg = binder.convertIfNecessary(arg, paramType, tham số);
}
handleResolvedValue(arg, namedValueInfo.name, tham số, mavContainer, webRequest);
trở lại
tranh luận;
}
|
Trách nhiệm của phương pháp này là tạo một đối tượng NamedValueInfo dựa trên đối tượng tham số. Đối tượng này lưu trữ ba biến thành viên: tên tham số, có bắt buộc hay không và giá trị mặc định của tham số. Sau đó nhập phương thức ResolverName để phân tích các tham số và cuối cùng trả về.
2. Ràng buộc tham số đối tượng
Việc phân tích và liên kết tham số đối tượng sẽ được chuyển giao cho lớp ServletModelAttributionMethodProcessor để phân tích cú pháp và nhập phương thức supportParameter.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/**
*Với chú thích @ModelAttribution trả về true
* Tham số trả về true ngay cả khi nó không phải là kiểu đơn giản.
*/
công cộng
Boolean
supportsParameter(Tham số MethodParameter) {
nếu như
(parameter.hasParameterAnnotation(ModelAttribution.
lớp học
)) {
trở lại
ĐÚNG VẬY
;
}
khác
nếu như
(
cái này
.annotationNotRequired) {
trở lại
!BeanUtils.isSimpleProperty(parameter.getParameterType());
}
khác
{
trở lại
SAI
;
}
}
|
Nhập phương thức ResolveArgument của ServletModelAttributionMethodProcessor. ResolveArgument của nó được triển khai cụ thể bởi lớp cha ModelAttributionMethodProcessor.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
/**
* Phân tích các tham số trong mô hình Nếu không tìm thấy từ ModelAndViewContainer, hãy khởi tạo một đối tượng trực tiếp thông qua sự phản chiếu. Việc khởi tạo cụ thể được khởi tạo thông qua phương thức createAttribution của lớp cha và bằng cách gọi phương thức BeanUtils.instantiateClass. Đối tượng này là đối tượng sau đó được chuyển đến phương thức test2 (Người dùng u), nhưng các giá trị trong đối tượng được tạo tại thời điểm này vẫn trống. Giá trị được chèn đạt được thông qua phương thức bindRequestParameters.
*/
công cộng
cuối cùng
Đối tượng resolveArgument(
Tham số MethodParameter, ModelAndViewContainer mavContainer,
Yêu cầu NativeWebRequest, WebDataBinderFactory binderFactory)
ném
Ngoại lệ {
Tên chuỗi = ModelFactory.getNameForParameter(tham số); Thuộc tính đối tượng = (mavContainer.containsAttribute(tên)) ?
mavContainer.getModel().get(name) : createAttribute(tên, tham số, binderFactory, yêu cầu);
WebDataBinder binder = binderFactory.createBinder(yêu cầu, thuộc tính, tên);
nếu như
(binder.getTarget() !=
vô giá trị
) {
bindRequestParameters(binder, yêu cầu);
validateIfApplicable(binder, tham số);
nếu như
(binder.getBindingResult().hasErrors()) {
nếu như
(isBindExceptionRequired(binder, tham số)) {
ném
mới
BindException(binder.getBindingResult());
}
}
}
Bản đồ bindingResultModel = binder.getBindingResult().getModel();
mavContainer.removeAttributes(bindingResultModel);
mavContainer.addAllAttributes(bindingResultModel);
trở lại
binder.getTarget();
}
|
- Phương thức này tạo một đối tượng WebDataBinder dựa trên yêu cầu, thuộc tính và tên, ở đâu. Sau đó nhập liên kết phương thức bindRequestParameters và tạo đối tượng MutablePropertyValues dựa trên các tham số trong reqeust. MutablePropertyValues lưu trữ một hoặc nhiều PropertyValues, trong đó PropertyValue được sử dụng để lưu thông tin liên quan đến một thuộc tính Bean đơn lẻ, chẳng hạn như tên tham số và giá trị tham số. Điều cần lưu ý ở đây là PropertyValue không lưu lại toàn bộ thông tin thuộc tính tham số của đối tượng yêu cầu. Thay vào đó, thuộc tính tham số tương ứng với PropertyValue. Ví dụ: đối tượng reqeust ở đây mang hai tham số là tên và tuổi và hai đối tượng PropertyValue sẽ được tạo tương ứng.
- Sau khi tạo đối tượng MutablePropertyValues, hãy nhập DataBinder.applyPropertyValues(DataBinder.java line737). Nó sẽ dựa trên đối tượng User vừa tạo. Tạo một đối tượng BeanWrapperImpl. BeanWrapperImpl triển khai giao diện PropertyAccessor (trình truy cập thuộc tính). Đây là một lớp thuộc spring-bean. Trong Sping, việc truy cập vào các thuộc tính Bean được triển khai thông qua lớp BeanWrapperImpl. Vai trò của BeanWarapperImpl ở đây là đưa các thuộc tính của đối tượng java tương ứng vào BeanWarapperImpl thông qua mô tả liên quan đến thuộc tính trong PropertyValue. Phương pháp chèn cụ thể là setPropertyValues, hơi phức tạp. Trách nhiệm của nó có thể được tóm tắt đơn giản là gọi phương thức set... tương ứng dựa trên tên thuộc tính. Ví dụ: khi tiêm thuộc tính tên của đối tượng Người dùng, phương thức setName thu được thông qua sự phản chiếu. Nếu phương thức này tồn tại, hãy gọi nó. Đây là lý do tại sao phương thức set... được yêu cầu khi xác định đối tượng mô hình SpringMVC.
3. Tóm tắt phân tích ràng buộc tham số
- Khi SpringMVC được khởi tạo, lớpRequestMappingHandlerAdapter sẽ thêm một số trình phân giải tham số mặc định vào đối sốResolvers. Khi SpringMVC nhận được yêu cầu, đầu tiên nó sẽ tìm kiếm HandlerMethod tương ứng dựa trên url.
- Duyệt qua mảng MethodParameter của HandlerMethod
- Tìm và xác nhận HandlerMethodArgumentResolver nào sẽ sử dụng dựa trên loại MethodParameter và duyệt qua phương thức supportParameter (tham số MethodParameter) của tất cả các đối số. . Nếu trả về true, điều đó có nghĩa là tìm kiếm thành công. Đối với MethodParameter hiện tại, hãy sử dụng HandlerMethodArgumentResolver. Hầu hết xác nhận ở đây đều dựa trên chú thích của tham số và Loại của tham số.
- Phân tích các tham số và phân tích các tham số tương ứng với MethodParameter từ yêu cầu. Kết quả được phân tích ở đây đều là các kiểu String.
- Chuyển đổi các tham số và chuyển đổi Chuỗi tương ứng thành loại theo yêu cầu của phương thức cụ thể, bao gồm các loại cơ bản, đối tượng, Danh sách, Tập hợp và Bản đồ.
Trên đây là tổng hợp chi tiết các kiến thức liên quan đến ràng buộc tham số SpringMVC. Để biết thêm thông tin về ràng buộc tham số SpringMVC các bạn hãy theo dõi các bài viết liên quan khác của mình nhé! .
Liên kết gốc: https://segmentfault.com/a/1190000039411057.
Cuối cùng, bài viết tổng hợp kiến thức liên quan đến ràng buộc tham số SpringMVC kết thúc tại đây. Nếu bạn muốn biết thêm về tổng hợp kiến thức liên quan đến ràng buộc tham số SpringMVC, vui lòng tìm kiếm bài viết CFSDN hoặc tiếp tục duyệt qua các bài viết liên quan. hỗ trợ nó trong tương lai blog của tôi! .
Tôi là một lập trình viên xuất sắc, rất giỏi!