如果您对清单使用Spring3MVC作为表单支持对象,正确的语法?和springmvcform表单感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解清单使用Spring3MVC作为表单支持对象,正
如果您对清单 使用Spring 3 MVC作为表单支持对象,正确的语法?和spring mvc form表单感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解清单 使用Spring 3 MVC作为表单支持对象,正确的语法?的各种细节,并对spring mvc form表单进行深入的分析,此外还有关于java – 不可变对象和Spring / Sring MVC:正确的选择?、JavaEE——SpringMVC(13)--SpringMVC运行流程 在 Spring 的环境下使用 SpringMVC、spring mvc-使用Servlet原生API作为参数、Spring MVC内置支持的4种内容协商方式【享学Spring MVC】的实用技巧。
本文目录一览:- 清单 使用Spring 3 MVC作为表单支持对象,正确的语法?(spring mvc form表单)
- java – 不可变对象和Spring / Sring MVC:正确的选择?
- JavaEE——SpringMVC(13)--SpringMVC运行流程 在 Spring 的环境下使用 SpringMVC
- spring mvc-使用Servlet原生API作为参数
- Spring MVC内置支持的4种内容协商方式【享学Spring MVC】
清单 使用Spring 3 MVC作为表单支持对象,正确的语法?(spring mvc form表单)
我想做这样的事情,哪里Foo
是一个具有一个String字段名称和getter / setter的类:
<form:form id="frmFoo" modelAttribute="foos"> <c:forEach items="${foos}" var="foo"> <form:input path="${foo.name}" type="text"/>
然后提交名称完整的Foos完整列表?
我的控制器如下所示:
@RequestMapping(value = "/FOO", method = RequestMethod.POST)public String getSendEmail(List<Foo> foos, Model model) { // ...}
答案1
小编典典也许这回答了您的问题:
控制器:
@Controller("/")public class FooController{ //returns the ModelAttribute fooListWrapper with the view fooForm @RequestMapping(value = "/FOO", method = RequestMethod.GET) public String getFooForm(Model model) { FooListWrapper fooListWrapper = new FooListWrapper(); fooListWrapper.add(new Foo()); fooListWrapper.add(new Foo()); //add as many FOO you need model.addAttribute("fooListWrapper", fooListWrapper); return "fooForm"; } @RequestMapping(value = "/FOO", method = RequestMethod.POST) public String postFooList(@ModelAttribute("fooListWrapper")FooListWrapper fooListWrapper, Model model) { //........... }}
FOO LIST WRAPPER:
public class FooListWrapper { private List<Foo> fooList; public FooListWrapper() { this.fooList = new ArrayList<Foo>(); } public List<Foo> getFooList() { return fooList; } public void setFooList(List<Foo> fooList) { this.fooList = fooList; } public void add(Foo foo) { this.fooList.add(foo); }}
FOO类:
public class Foo { private String name; public Foo() { } public String getName() { return name; } public void setName(String name) { this.name = name; }}
JSP VIEW(名称= fooForm):
<c:url var="fooUrl" value="/FOO"/><form:form id="frmFoo" action="${fooUrl}" method="POST" modelAttribute="fooListWrapper"> <c:forEach items="${fooListWrapper.fooList}" varStatus="i"> <form:input path="fooList[${i.index}].name" type="text"/> </c:forEach> <button>submit</button></form:form>
java – 不可变对象和Spring / Sring MVC:正确的选择?
但是与Spring一起工作时,我有时会注意到,在大多数情况下,框架不鼓励这种设计,赞成经典的JavaBeans设计:默认的构造函数getter / setter.
我真的不喜欢JavaBean设计的对象,因为他们的疯狂的可变性.
所以我想知道我是否缺少一些东西
我尽量让我的课堂设计尽可能优雅和可重复使用,但框架需要改变这个设计或允许它,但是在一个困难的方式…
这是怎么回事?
解决方法
@ConstructorProperties
(iirc我自己调查补丁,但是这很复杂,会打破很多事情).有人应该可以提交功能请求.
BTW我在谈论web数据绑定(而不是依赖注入),因为Spring已经很长时间支持基于构造函数的DI(不可变对象需要基于构造函数的注入).实际上,我会说基于构造函数的注入或(静态方法工厂)正在成为传统的getter / setter组件的首选方法(您可以看到这在许多Spring类中多年来一直转向final和constructor的变化).
无论如何,我能够使用Jackson https://gist.github.com/agentgt/4458079对不可变对象进行Web数据绑定
(尽管它使用Jackson来数据绑定请求不一定是JSON)
你可能还想看到Spring Webflow DataBinding to immutable objects via a constructor?我原来想到的想法,并有更多的信息.
JavaEE——SpringMVC(13)--SpringMVC运行流程 在 Spring 的环境下使用 SpringMVC
需要进行 Spring 整合 SpringMVC 吗 ?
还是否需要再加入 Spring 的 IOC 容器 ?
是否需要再 web.xml 文件中配置启动 Spring IOC 容器的 ContextLoaderListener ?
spring的IOC
package com.atguigu.springmvc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private HelloWorld helloWorld;
public UserService() {
System.out.println("UserService Constructor...");
}
}
SpringMVC的IOC
package com.atguigu.springmvc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloWorld {
@Autowired
private UserService userService;
public HelloWorld() {
System.out.println("HelloWorld Constructor...");
}
@RequestMapping("/helloworld")
public String hello(){
System.out.println("success");
System.out.println(userService);
return "success";
}
}
1. 需要: 通常情况下, 类似于数据源, 事务, 整合其他框架都是放在 Spring 的配置文件中(而不是放在 SpringMVC 的配置文件中).
实际上放入 Spring 配置文件对应的 IOC 容器中的还有 Service 和 Dao.
2. 不需要: 都放在 SpringMVC 的配置文件中. 也可以分多个 Spring 的配置文件, 然后使用 import 节点导入其他的配置文件
问题: 若 Spring 的 IOC 容器和 SpringMVC 的 IOC 容器扫描的包有重合的部分, 就会导致有的 bean 会被创建 2 次.
解决:
1. 使 Spring 的 IOC 容器扫描的包和 SpringMVC 的 IOC 容器扫描的包没有重合的部分.
*2. 使用 exclude-filter 和 include-filter 子节点来规定只能扫描的注解
springmvc.xml
<context:component-scan base-package="com.atguigu.springmvc" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation"
expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
bean.xml
<context:component-scan base-package="com.atguigu.springmvc">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="annotation"
expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
SpringMVC 的 IOC 容器中的 bean 可以来引用 Spring IOC 容器中的 bean.
返回来呢 ? 反之则不行. Spring IOC 容器中的 bean 却不能来引用 SpringMVC IOC 容器中的 bean!
spring mvc-使用Servlet原生API作为参数
https://www.cnblogs.com/caoyc/p/5635701.html
具体看代码:
@RequestMapping("/testServletAPI")
public void testServletAPI(HttpServletRequest request,
HttpServletResponse response,HttpSession session,
Write r out) throws IOException{
System.out.println(request);
System.out.println(response);
System.out.println(session);
out.write("hello");
}
代码解析:
很明显,要使用Servlet的一些API,只要直接将其作为参数传入即可。你需要request,就传入request,需要session,就传入session。spring mvc支持传入的Servlet原生API一共有以下这些:
1、HTTPServletRequest
2、HTTPServletResponse
3、HttpSession
4、java.security.Principal
5、Locale
6、InputStream
7、OutputStream
8、Reader
9、Writer
Spring MVC内置支持的4种内容协商方式【享学Spring MVC】
每篇一句
十个光头九个富,最后一个会砍树
前言
不知你在使用Spring Boot
时是否对这样一个现象"诧异"过:同一个
接口(同一个URL)在接口报错情况下,若你用rest访问,它返回给你的是一个json
串;但若你用浏览器访问,它返回给你的是一段html
。恰如下面例子(Spring Boot
环境~):
@RestController
@RequestMapping
public class HelloController {
@GetMapping("/test/error")
public Object testError() {
System.out.println(1 / 0); // 强制抛出异常
return "hello world";
}
}
使用浏览器访问:http://localhost:8080/test/error
使用Postman访问:
同根不同命有木有。RESTful
服务中很重要的一个特性是:同一资源可以有多种表述,这就是我们今天文章的主题:内容协商(ContentNegotiation
)。
HTTP内容协商
虽然本文主要是想说Spring MVC
中的内容协商机制,但是在此之前是很有必要先了解HTTP
的内容协商是怎么回事(Spring MVC
实现了它并且扩展了它更为强大~)。
定义
一个URL资源
服务端可以以多种形式进行响应:即MIME(MediaType
)媒体类型。但对于某一个客户端(浏览器、APP、Excel导出...)来说它只需要一种。so这样客户端和服务端就得有一种机制来保证这个事情,这种机制就是内容协商机制。
方式
http
的内容协商方式大致有两种:
- 服务端将可用列表(自己能提供的MIME类型们)发给客户端,客户端选择后再告诉服务端。这样服务端再按照客户端告诉的MIME返给它。(缺点:多一次网络交互,而且使用对使用者要求高,所以此方式一般不用)
-
(常用)客户端发请求时就指明需要的
MIME
们(比如Http
头部的:Accept
),服务端根据客户端指定的要求返回合适的形式,并且在响应头中做出说明(如:Content-Type
)1. 若客户端要求的MIME类型服务端提供不了,那就406错误吧~
常用请求头、响应头
==请求头==Accept
:告诉服务端需要的MIME(一般是多个,比如text/plain
,application/json
等。/表示可以是任何MIME资源)Accept-Language
:告诉服务端需要的语言(在中国默认是中文嘛,但浏览器一般都可以选择N多种语言,但是是否支持要看服务器是否可以协商)Accept-Charset
:告诉服务端需要的字符集Accept-Encoding
:告诉服务端需要的压缩方式(gzip,deflate,br)
==响应头==Content-Type
:告诉客户端响应的媒体类型(如application/json
、text/html
等)Content-Language
:告诉客户端响应的语言Content-Charset
:告诉客户端响应的字符集Content-Encoding
:告诉客户端响应的压缩方式(gzip)
报头Accept
与Content-Type
的区别
有很多文章粗暴的解释:Accept
属于请求头,Content-Type
属于响应头,其实这是不准确的。
在前后端分离开发成为主流的今天,你应该不乏见到前端的request请求上大都有Content-Type:application/json;charset=utf-8
这个请求头,因此可见Content-Type
并不仅仅是响应头。
HTTP协议规范的格式如下四部分:
- <request-line>(请求消息行)
- <headers>(请求消息头)
- <blank line>(请求空白行)
- <request-body>(请求消息体)
Content-Type
指请求消息体的数据格式,因为请求和响应中都可以有消息体,所以它即可用在请求头,亦可用在响应头。
关于更多Http中的Content-Type
的内容,我推荐参见此文章:Http请求中的Content-Type
Spring MVC内容协商
Spring MVC
实现了HTTP
内容协商的同时,又进行了扩展。它支持4种协商方式:
-
HTTP
头Accept
- 扩展名
- 请求参数
- 固定类型(producers)
说明:以下示例基于Spring进行演示,而非Spring Boot
方式一:HTTP头Accept
@RestController
@RequestMapping
public class HelloController {
@ResponseBody
@GetMapping("/test/{id}")
public Person test(@PathVariable(required = false) String id) {
System.out.println("id的值为:" + id);
Person person = new Person();
person.setName("fsx");
person.setAge(18);
return person;
}
}
如果默认就这样,不管浏览器访问还是Postman访问,得到的都是json串。
但若你仅仅只需在pom
加入如下两个包:
<!-- 此处需要导入databind包即可, jackson-annotations、jackson-core都不需要显示自己的导入了-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<!-- jackson默认只会支持的json。若要xml的支持,需要额外导入如下包 -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.9.8</version>
</dependency>
再用浏览器/Postman访问,得到结果就是xml了,形如这样:
有的文章说:浏览器是xml,postman是json。本人亲试:都是xml。
但若我们postman
手动指定这个头:Accept:application/json
,返回就和浏览器有差异了(若不手动指定,Accept
默认值是*/*
):
并且我们可以看到response
的头信息对比如下:
手动指定了Accept:application/json
:
木有指定Accept(默认*/*
):
原因简析
Chrome
浏览器请求默认发出的Accept
是:Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
。
由于我例子使用的是@ResponseBody
,因此它不会返回一个view:交给消息转换器处理,因此这就和MediaType
以及权重有关了。
消息最终都会交给AbstractMessageConverterMethodProcessor.writeWithMessageConverters()
方法:
// @since 3.1
AbstractMessageConverterMethodProcessor:
protected <T> void writeWithMessageConverters( ... ) {
Object body;
Class<?> valueType;
Type targetType;
...
HttpServletRequest request = inputMessage.getServletRequest();
// 这里交给contentNegotiationManager.resolveMediaTypes() 找出客户端可以接受的MediaType们~~~
// 此处是已经排序好的(根据Q值等等)
List<MediaType> acceptableTypes = getAcceptableMediaTypes(request);
// 这是服务端它所能提供出的MediaType们
List<MediaType> producibleTypes = getProducibleMediaTypes(request, valueType, targetType);
// 协商。 经过一定的排序、匹配 最终匹配出一个合适的MediaType
...
// 把待使用的们再次排序,
MediaType.sortBySpecificityAndQuality(mediaTypesToUse);
// 最终找出一个最合适的、最终使用的:selectedMediaType
for (MediaType mediaType : mediaTypesToUse) {
if (mediaType.isConcrete()) {
selectedMediaType = mediaType;
break;
} else if (mediaType.isPresentIn(ALL_APPLICATION_MEDIA_TYPES)) {
selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;
break;
}
}
}
acceptableTypes
是客户端通过Accept
告知的。producibleTypes
代表着服务端所能提供的类型们。参考这个getProducibleMediaTypes()
方法:
AbstractMessageConverterMethodProcessor:
protected List<MediaType> getProducibleMediaTypes( ... ) {
// 它设值的地方唯一在于:@RequestMapping.producers属性
// 大多数情况下:我们一般都不会给此属性赋值吧~~~
Set<MediaType> mediaTypes = (Set<MediaType>) request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
if (!CollectionUtils.isEmpty(mediaTypes)) {
return new ArrayList<>(mediaTypes);
}
// 大多数情况下:都会走进这个逻辑 --> 从消息转换器中匹配一个合适的出来
else if (!this.allSupportedMediaTypes.isEmpty()) {
List<MediaType> result = new ArrayList<>();
// 从所有的消息转换器中 匹配出一个/多个List<MediaType> result出来
// 这就代表着:我服务端所能支持的所有的List<MediaType>们了
for (HttpMessageConverter<?> converter : this.messageConverters) {
if (converter instanceof GenericHttpMessageConverter && targetType != null) {
if (((GenericHttpMessageConverter<?>) converter).canWrite(targetType, valueClass, null)) {
result.addAll(converter.getSupportedMediaTypes());
}
}
else if (converter.canWrite(valueClass, null)) {
result.addAll(converter.getSupportedMediaTypes());
}
}
return result;
} else {
return Collections.singletonList(MediaType.ALL);
}
}
可以看到服务端最终能够提供哪些MediaType
,来源于消息转换器HttpMessageConverter
对类型的支持。
本例的现象:起初返回的是json串,仅仅只需要导入jackson-dataformat-xml
后就返回xml
了。原因是因为加入MappingJackson2XmlHttpMessageConverter
都有这个判断:
private static final boolean jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
if (jackson2XmlPresent) {
addPartConverter(new MappingJackson2XmlHttpMessageConverter());
}
所以默认情况下Spring MVC
并不支持application/xml
这种媒体格式,所以若不导包协商出来的结果是:application/json
。
默认情况下优先级是xml高于json。当然一般都木有xml包,所以才轮到json的。
另外还需要注意一点:有的小伙伴说通过在请求头里指定Content-Type:application/json
来达到效果。现在你应该知道,这样做显然是没用的(至于为何没用,希望读者做到了心知肚明),只能使用Accept
这个头来指定~~~
第一种协商方式是Spring MVC
完全基于HTTP Accept
首部的方式了。该种方式Spring MVC
默认支持且默认已开启。
优缺点:
- 优点:理想的标准方式
- 缺点:由于浏览器的差异,导致发送的Accept Header头可能会不一样,从而得到的结果不具备浏览器兼容性
方式二:(变量)扩展名
基于上面例子:若我访问/test/1.xml
返回的是xml,若访问/test/1.json
返回的是json;完美~
这种方式使用起来非常的便捷,并且还不依赖于浏览器。但我总结了如下几点使时的注意事项:
- 扩展名必须是变量的扩展名。比如上例若访问
test.json / test.xml
就404~ -
@PathVariable
的参数类型只能使用通用类型(String/Object
),因为接收过来的value值就是1.json/1.xml
,所以若用Integer
接收将报错类型转换错误~1. 小技巧:我个人建议是这部分不接收(这部分不使用`@PathVariable`接收),拿出来**只为内容协商使用**
- 扩展名优先级比Accept要高(并且和使用神马浏览器无关)
优缺点:
- 优点:灵活,不受浏览器约束
- 缺点:丧失了同一URL的多种展现方式。在实际环境中使用还是较多的,因为这种方式更符合程序员的习惯
方式三:请求参数
这种协商方式Spring MVC
支持,但默认是关闭的,需要显示的打开:
@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
// 支持请求参数协商
configurer.favorParameter(true);
}
}
请求URL:/test/1?format=xml
返回xml;/test/1?format=json
返回json。同样的我总结如下几点注意事项:
- 前两种方式默认是开启的,但此种方式需要手动显示开启
- 此方式优先级
低于
扩展名(因此你测试时若想它生效,请去掉url的后缀)
优缺点:
- 优点:不受浏览器约束
- 缺点:需要额外的传递format参数,URL变得冗余繁琐,缺少了REST的简洁风范。还有个缺点便是:还需手动显示开启。
方式四:固定类型(produces)
它就是利用@RequestMapping
注解属性produces
(可能你平时也在用,但并不知道原因):
@ResponseBody
@GetMapping(value = {"/test/{id}", "/test"}, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Person test() { ... }
访问:/test/1
返回的就是json;即使你已经导入了jackson的xml包,返回的依旧还是json。
它也有它很很很重要的一个注意事项:produces
指定的MediaType
类型不能和后缀、请求参数、Accept冲突。例如本利这里指定了json
格式,如果你这么访问/test/1.xml
,或者format=xml
,或者Accept
不是application/json或者*/*
将无法完成内容协商:http状态码为406,报错如下:produces
使用固然也比较简单,针对上面报错406的原因,我简单解释如下。
原因:
1、先解析请求的媒体类型:1.xml
解析出来的MediaType
是application/xml
2、拿着这个MediaType
(当然还有URL、请求Method等所有)去匹配HandlerMethod
的时候会发现producers
匹配不上
3、匹配不上就交给RequestMappingInfoHandlerMapping.handleNoMatch()
处理:
RequestMappingInfoHandlerMapping:
@Override
protected HandlerMethod handleNoMatch(...) {
if (helper.hasConsumesMismatch()) {
...
throw new HttpMediaTypeNotSupportedException(contentType, new ArrayList<>(mediaTypes));
}
// 抛出异常:HttpMediaTypeNotAcceptableException
if (helper.hasProducesMismatch()) {
Set<MediaType> mediaTypes = helper.getProducibleMediaTypes();
throw new HttpMediaTypeNotAcceptableException(new ArrayList<>(mediaTypes));
}
}
4、抛出异常后最终交给DispatcherServlet.processHandlerException()
去处理这个异常,转换到Http
状态码
会调用所有的handlerExceptionResolvers
来处理这个异常,本处会被DefaultHandlerExceptionResolver
最终处理。最终处理代码如下(406状态码):
protected ModelAndView handleHttpMediaTypeNotAcceptable(HttpMediaTypeNotAcceptableException ex,
HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE);
return new ModelAndView();
}
Spring MVC
默认注册的异常处理器是如下3个:![]()
原理
有了关于Accept
的原理描述,理解它就非常简单了。因为指定了produces
属性,所以getProducibleMediaTypes()
方法在拿服务端支持的媒体类型时:
protected List<MediaType> getProducibleMediaTypes( ... ){
Set<MediaType> mediaTypes = (Set<MediaType>) request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
if (!CollectionUtils.isEmpty(mediaTypes)) {
return new ArrayList<>(mediaTypes);
}
...
}
因为设置了producers
,所以代码第一句就能拿到值了(后面的协商机制完全同上)。
备注:若produces属性你要指定的非常多,建议可以使用!xxx
语法,它是支持这种语法(排除语法)的~
优缺点:
- 优点:使用简单,天然支持
- 缺点:让
HandlerMethod
处理器缺失灵活性
Spring Boot默认异常消息处理
再回到开头的Spring Boot
为何对异常消息,浏览器和postman的展示不一样。这就是Spring Boot
默认的对异常处理方式:它使用的就是基于 固定类型(produces)实现的内容协商。
Spirng Boot
出现异常信息时候,会默认访问/error
,它的处理类是:BasicErrorController
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {
...
// 处理类浏览器
@RequestMapping(produces = "text/html")
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
...
return (modelAndView != null ? modelAndView : new ModelAndView("error", model));
}
// 处理restful/json方式
@RequestMapping
@ResponseBody
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = getStatus(request);
return new ResponseEntity<Map<String, Object>>(body, status);
}
...
}
有了上面的解释,对这块代码的理解应该就没有盲点了~
总结
内容协商在RESTful
流行的今天还是非常重要的一块内容,它对于提升用户体验,提升效率和降低维护成本都有不可忽视的作用,注意它三的优先级为:后缀 > 请求参数 > HTTP首部Accept
一般情况下,我们为了通用都会使用基于Http的内容协商(Accept),但在实际应用中其实很少用它,因为不同的浏览器可能导致不同的行为(比如Chrome
和Firefox
就很不一样),所以为了保证“稳定性”一般都选择使用方案二或方案三(比如Spring的官方doc)。
相关阅读
【小家Spring】Spring MVC容器的web九大组件之---HandlerMapping源码详解(二)---RequestMappingHandlerMapping系列
ContentNegotiation内容协商机制(一)---Spring MVC内置支持的4种内容协商方式【享学Spring MVC】
ContentNegotiation内容协商机制(二)---Spring MVC内容协商实现原理及自定义配置【享学Spring MVC】
ContentNegotiation内容协商机制(三)---在视图View上的应用:ContentNegotiatingViewResolver深度解析【享学Spring MVC】
知识交流
==The last:如果觉得本文对你有帮助,不妨点个赞呗。当然分享到你的朋友圈让更多小伙伴看到也是被作者本人许可的~
==
**若对技术内容感兴趣可以加入wx群交流:Java高工、架构师3群
。
若群二维码失效,请加wx号:fsx641385712
(或者扫描下方wx二维码)。并且备注:"java入群"
字样,会手动邀请入群**
==若对Spring、SpringBoot、MyBatis等源码分析感兴趣,可加我wx:fsx641385712,手动邀请你入群一起飞==
关于清单 使用Spring 3 MVC作为表单支持对象,正确的语法?和spring mvc form表单的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于java – 不可变对象和Spring / Sring MVC:正确的选择?、JavaEE——SpringMVC(13)--SpringMVC运行流程 在 Spring 的环境下使用 SpringMVC、spring mvc-使用Servlet原生API作为参数、Spring MVC内置支持的4种内容协商方式【享学Spring MVC】等相关内容,可以在本站寻找。
本文标签: