SpringMVC(十四):SpringMVC 与表单提交(post/put/delete的用法);form属性设置encrypt='mutilpart/form-data'时,如何正确配置web.xml才能以put方式提交表单
SpringMVC 与表单提交(post/put/delete的用法)
为了迎合Restful风格,提供的接口可能会包含:put、delete提交方式。在springmvc中实现表单以put、delete方式提交时,需要使用HiddenHttpMethodFilter过滤器。该过滤器的实现原理,默认在form表单内部定义一个hidden隐藏的标签,默认需要标签名为:_method,hidden标签的value为put或delete;过滤器会接收_method的hidden标签的value,如果发现存在_method的标签,并且value为put或delete时,会重新包装一个请求,请求类型会设置为_method标签的value值。进而实现将post方式提交表单转化为Delete或Put请求。
实现form post表当以put或delete方式提交的步骤包含以下:
idea下创建一个pom.xml工程:
创建完后,工程结构如下:
设置web.xml配置如下:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>springmvcdemo</display-name> <welcome-file-list> <welcome-file>/index</welcome-file> </welcome-file-list> <!--结束后端数据输出到前端乱码问题--> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> <!--可以通过配置覆盖默认'_method'值 --> <init-param> <param-name>methodParam</param-name> <param-value>_method</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>myAppServletName</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>myAppServletName</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
此时在WEB-INF下还需要新建一个applicationContext.xml配置文件,配置文件内容如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--扫描所有的 spring包下的文件;--> <!--当然需要在spring配置文件里面配置一下自动扫描范围 <context:component-scan base-package="*"/> *代表你想要扫描的那些包的目录所在位置。Spring 在容器初始化时将自动扫描 base-package 指定的包及其子包下的所有的.class文件, 所有标注了 @Repository 的类都将被注册为 Spring Bean。 --> <context:component-scan base-package="com.dx.test"/> <!--新增加的两个配置,这个是解决406问题的关键--> <!--mvc注解驱动(可代替注解适配器与注解映射器的配置),默认加载很多参数绑定方法(实际开发时使用)--> <context:annotation-config/> <mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> <property name="contentType" value="text/html;charset=UTF-8" /> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> </bean> <!--自己后加的,该BeanPostProcessor将自动对标注@Autowired的bean进行注入--> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"></bean> <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> <property name="messageConverters"> <list> <!--<ref bean="stringHttpMessageConverter"/>--> <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/> <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/> <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/> <bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/> <!-- <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/> --> </list> </property> </bean> </beans>
配置pom.xml引入依赖如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 7 <groupId>com.dx.test</groupId> 8 <artifactId>demo</artifactId> 9 <version>1.0-SNAPSHOT</version> 10 <packaging>war</packaging> 11 12 <name>demo Maven Webapp</name> 13 <!-- FIXME change it to the project's website --> 14 <url>http://www.example.com</url> 15 16 <properties> 17 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 18 <maven.compiler.source>1.8</maven.compiler.source> 19 <maven.compiler.target>1.8</maven.compiler.target> 20 <!--Spring版本号--> 21 <spring.version>5.2.0.RELEASE</spring.version> 22 <!--jstl标签库--> 23 <jstl.version>1.2</jstl.version> 24 <standard.version>1.1.2</standard.version> 25 </properties> 26 27 <dependencies> 28 <!-- servlet相关 29 <dependency> 30 <groupId>javax.servlet</groupId> 31 <artifactId>servlet-api</artifactId> 32 <version>2.5</version> 33 <scope>provided</scope> 34 </dependency> 35 --> 36 <dependency> 37 <groupId>javax.servlet</groupId> 38 <artifactId>javax.servlet-api</artifactId> 39 <version>3.0.1</version> 40 <scope>provided</scope> 41 </dependency> 42 43 <!--form 设置为enctype="multipart/form-data",多文件上传,在applicationContext.xml中配置了bean multipartResolver时,需要依赖该包。--> 44 <dependency> 45 <groupId>commons-fileupload</groupId> 46 <artifactId>commons-fileupload</artifactId> 47 <version>1.4</version> 48 </dependency> 49 50 <dependency> 51 <groupId>commons-io</groupId> 52 <artifactId>commons-io</artifactId> 53 <version>2.5</version> 54 </dependency> 55 56 <!--spring单元测试依赖--> 57 <dependency> 58 <groupId>org.springframework</groupId> 59 <artifactId>spring-test</artifactId> 60 <version>${spring.version}</version> 61 <scope>test</scope> 62 </dependency> 63 64 <!--springMVC核心包--> 65 <dependency> 66 <groupId>org.springframework</groupId> 67 <artifactId>spring-webmvc</artifactId> 68 <version>${spring.version}</version> 69 </dependency> 70 71 <!--spring核心包--> 72 <dependency> 73 <groupId>org.springframework</groupId> 74 <artifactId>spring-core</artifactId> 75 <version>${spring.version}</version> 76 </dependency> 77 78 <dependency> 79 <groupId>org.springframework</groupId> 80 <artifactId>spring-beans</artifactId> 81 <version>${spring.version}</version> 82 </dependency> 83 84 <dependency> 85 <groupId>org.springframework</groupId> 86 <artifactId>spring-context</artifactId> 87 <version>${spring.version}</version> 88 </dependency> 89 90 <dependency> 91 <groupId>org.springframework</groupId> 92 <artifactId>spring-context-support</artifactId> 93 <version>${spring.version}</version> 94 </dependency> 95 96 <dependency> 97 <groupId>org.springframework</groupId> 98 <artifactId>spring-aop</artifactId> 99 <version>${spring.version}</version> 100 </dependency> 101 102 <dependency> 103 <groupId>org.springframework</groupId> 104 <artifactId>spring-aspects</artifactId> 105 <version>${spring.version}</version> 106 </dependency> 107 108 <dependency> 109 <groupId>org.springframework</groupId> 110 <artifactId>spring-tx</artifactId> 111 <version>${spring.version}</version> 112 </dependency> 113 114 <dependency> 115 <groupId>org.springframework</groupId> 116 <artifactId>spring-web</artifactId> 117 <version>${spring.version}</version> 118 </dependency> 119 120 <dependency> 121 <groupId>org.springframework</groupId> 122 <artifactId>spring-jdbc</artifactId> 123 <version>${spring.version}</version> 124 </dependency> 125 126 <!--AOP begin--> 127 <dependency> 128 <groupId>org.aspectj</groupId> 129 <artifactId>aspectjrt</artifactId> 130 <version>1.8.13</version> 131 </dependency> 132 133 <dependency> 134 <groupId>org.aspectj</groupId> 135 <artifactId>aspectjrt</artifactId> 136 <version>1.8.13</version> 137 </dependency> 138 139 <dependency> 140 <groupId>cglib</groupId> 141 <artifactId>cglib</artifactId> 142 <version>3.2.5</version> 143 </dependency> 144 <!--AOP end--> 145 146 <!--json依赖--> 147 <dependency> 148 <groupId>org.codehaus.jackson</groupId> 149 <artifactId>jackson-core-asl</artifactId> 150 <version>1.5.2</version> 151 </dependency> 152 <dependency> 153 <groupId>org.codehaus.jackson</groupId> 154 <artifactId>jackson-mapper-asl</artifactId> 155 <version>1.5.2</version> 156 </dependency> 157 158 <!--jstl库--> 159 <dependency> 160 <groupId>javax.servlet</groupId> 161 <artifactId>jstl</artifactId> 162 <version>${jstl.version}</version> 163 <scope>runtime</scope> 164 </dependency> 165 <dependency> 166 <groupId>taglibs</groupId> 167 <artifactId>standard</artifactId> 168 <version>${standard.version}</version> 169 </dependency> 170 171 <dependency> 172 <groupId>junit</groupId> 173 <artifactId>junit</artifactId> 174 <version>4.11</version> 175 <scope>test</scope> 176 </dependency> 177 </dependencies> 178 179 <build> 180 <finalName>demo</finalName> 181 <plugins> 182 <!-- 配置Tomcat插件 --> 183 <plugin> 184 <groupId>org.apache.tomcat.maven</groupId> 185 <artifactId>tomcat7-maven-plugin</artifactId> 186 <version>2.2</version> 187 <configuration> 188 <port>9090</port> 189 <path>/</path> 190 <uriEncoding>UTF-8</uriEncoding> 191 <server>tomcat7</server> 192 </configuration> 193 </plugin> 194 </plugins> 195 <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> 196 <plugins> 197 <plugin> 198 <artifactId>maven-clean-plugin</artifactId> 199 <version>3.1.0</version> 200 </plugin> 201 <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> 202 <plugin> 203 <artifactId>maven-resources-plugin</artifactId> 204 <version>3.0.2</version> 205 </plugin> 206 <plugin> 207 <artifactId>maven-compiler-plugin</artifactId> 208 <version>3.8.0</version> 209 </plugin> 210 <plugin> 211 <artifactId>maven-surefire-plugin</artifactId> 212 <version>2.22.1</version> 213 </plugin> 214 <plugin> 215 <artifactId>maven-war-plugin</artifactId> 216 <version>3.2.2</version> 217 </plugin> 218 <plugin> 219 <artifactId>maven-install-plugin</artifactId> 220 <version>2.5.2</version> 221 </plugin> 222 <plugin> 223 <artifactId>maven-deploy-plugin</artifactId> 224 <version>2.8.2</version> 225 </plugin> 226 </plugins> 227 </pluginManagement> 228 </build> 229 </project>
/WEB-INF/views/index.jsp内容如下:
<html> <body> <h2>Hello World!</h2> </body> </html>
/WEB-INF/views/article/list.jsp内容如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <!-- 屏蔽tomcat 自带的 EL表达式 --> <%@ page isELIgnored="false" %> <html> <head> <meta charset="UTF-8"> <title>Spring MVC Demo</title> </head> <body> <h2>All Articles</h2> <table border="1"> <tr> <th>Article Id</th> <th>Article Name</th> </tr> <c:forEach items="${articles}" var="article"> <tr> <td>${article.id}</td> <td>${article.title}</td> </tr> </c:forEach> </table> </body> </html>
/WEB-INF/views/article/show.jsp内容如下:
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!-- 屏蔽tomcat 自带的 EL表达式 --> <%@ page isELIgnored="false" %> <html> <head> <meta charset="UTF-8"> <title>Spring MVC Demo</title> </head> <body> <h2>Post方式提交:</h2> <form:form name="article" method="POST" action="update_with_post" modelAttribute="article"> Id:<form:hidden path="id"/> Title: <form:input path="title" style="width:200px;"/><br/> Content: <form:input path="content" style="width:200px;"/><br/> <input type="submit" value="Submit" /> </form:form> <form name="article" method="POST" action="update_with_post"> Id:<input name="id" id="id" value="${article.id}"/><br/> Title:<input name="title" id="title" value="${article.title}"/><br/> Content:<input name="content" id="content" value="${article.content}"/><br/> <input type="submit" value="Submit" /> </form> <h2>Post包含上传文件提交:</h2> <form:form name="article" method="POST" action="update_with_post_file" modelAttribute="article" enctype="multipart/form-data"> Id:<form:hidden path="id"/> Title: <form:input path="title" style="width:200px;"/><br/> Content: <form:input path="content" style="width:200px;"/><br/> yourfile: <input type="file" name="file"/><br/> <input type="submit" value="Submit" /> </form:form> <form name="article" method="POST" action="update_with_post_file" enctype="multipart/form-data"> Id:<input name="id" id="id" value="${article.id}"/><br/> Title:<input name="title" id="title" value="${article.title}"/><br/> Content:<input name="content" id="content" value="${article.content}"/><br/> yourfile: <input type="file" name="file"/><br/> <input type="submit" value="Submit" /> </form> <h2>Put方式提交:</h2> <form:form name="article" method="POST" action="update_with_put" modelAttribute="article"> <input type="hidden" name="_method" value="PUT"/> Id:<form:hidden path="id"/> Title: <form:input path="title" style="width:200px;"/><br/> Content: <form:input path="content" style="width:200px;"/><br/> <input type="submit" value="Submit" /> </form:form> <form name="article" method="POST" action="update_with_put"> <input type="hidden" name="_method" value="PUT"/> Id:<input name="id" id="id" value="${article.id}"/><br/> Title:<input name="title" id="title" value="${article.title}"/><br/> Content:<input name="content" id="content" value="${article.content}"/><br/> <input type="submit" value="Submit" /> </form> <h2>Put包含上传文件提交:</h2> <form:form name="article" method="POST" action="update_with_put_file" modelAttribute="article" enctype="multipart/form-data"> <input type="hidden" name="_method" value="PUT"/> Id:<form:hidden path="id"/> Title: <form:input path="title" style="width:200px;"/><br/> Content: <form:input path="content" style="width:200px;"/><br/> yourfile: <input type="file" name="file"/><br/> <input type="submit" value="Submit" /> </form:form> <form method="POST" name="article" action="update_with_put_file" enctype="multipart/form-data"> <input type="hidden" name="_method" value="PUT"/> Id:<input name="id" id="id" value="${article.id}"/><br/> Title:<input name="title" id="title" value="${article.title}"/><br/> Content:<input name="content" id="content" value="${article.content}"/><br/> yourfile: <input type="file" name="file"/><br/> <input type="submit" value="Submit" /> </form> </body> </html>
com.dx.test.model.ArticleModel.java
package com.dx.test.model; import java.io.Serializable; import java.util.Date; /** * 文章内容 */ public class ArticleModel implements Serializable { private Long id; private Long categoryId; private String title; private String content; private Date createTime; private String createUser; private String createUserId; private Date modifyTime; private String modifyUser; private String modifyUserId; public ArticleModel() { } public ArticleModel(Long id, Long categoryId, String title, String content) { this.id = id; this.categoryId = categoryId; this.title = title; this.content = content; } /** * @return the id */ public Long getId() { return id; } /** * @param id the id to set */ public void setId(Long id) { this.id = id; } /** * @return the categoryId */ public Long getCategoryId() { return categoryId; } /** * @param categoryId the categoryId to set */ public void setCategoryId(Long categoryId) { this.categoryId = categoryId; } /** * @return the title */ public String getTitle() { return title; } /** * @param title the title to set */ public void setTitle(String title) { this.title = title; } /** * @return the content */ public String getContent() { return content; } /** * @param content the content to set */ public void setContent(String content) { this.content = content; } /** * @return the createTime */ public Date getCreateTime() { return createTime; } /** * @param createTime the createTime to set */ public void setCreateTime(Date createTime) { this.createTime = createTime; } /** * @return the createUser */ public String getCreateUser() { return createUser; } /** * @param createUser the createUser to set */ public void setCreateUser(String createUser) { this.createUser = createUser; } /** * @return the createUserId */ public String getCreateUserId() { return createUserId; } /** * @param createUserId the createUserId to set */ public void setCreateUserId(String createUserId) { this.createUserId = createUserId; } /** * @return the modifyTime */ public Date getModifyTime() { return modifyTime; } /** * @param modifyTime the modifyTime to set */ public void setModifyTime(Date modifyTime) { this.modifyTime = modifyTime; } /** * @return the modifyUser */ public String getModifyUser() { return modifyUser; } /** * @param modifyUser the modifyUser to set */ public void setModifyUser(String modifyUser) { this.modifyUser = modifyUser; } /** * @return the modifyUserId */ public String getModifyUserId() { return modifyUserId; } /** * @param modifyUserId the modifyUserId to set */ public void setModifyUserId(String modifyUserId) { this.modifyUserId = modifyUserId; } @Override public String toString() { return "ArticleModel{" + "id=" + id + ", categoryId=" + categoryId + ", title='" + title + '\'' + ", content='" + content + '\'' + '}'; } }
com.dx.test.controller.HomeController.java
package com.dx.test.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class HomeController { @RequestMapping(value = "/", method = RequestMethod.GET) public String index() { return "index"; } }
com.dx.test.controller.ArticleController.java
1 package com.dx.test.controller; 2 3 import com.dx.test.model.ArticleModel; 4 import com.dx.test.service.IArticleService; 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.http.MediaType; 7 import org.springframework.stereotype.Controller; 8 import org.springframework.ui.Model; 9 import org.springframework.ui.ModelMap; 10 import org.springframework.web.bind.annotation.*; 11 import org.springframework.web.multipart.MultipartFile; 12 import org.springframework.web.multipart.MultipartHttpServletRequest; 13 import org.springframework.web.servlet.ModelAndView; 14 15 import javax.servlet.http.HttpServletRequest; 16 import javax.xml.ws.http.HTTPBinding; 17 import java.io.IOException; 18 import java.util.List; 19 import java.util.Map; 20 import java.util.Optional; 21 22 @Controller 23 @RequestMapping("/article") 24 public class ArticleController { 25 @Autowired 26 private IArticleService articleService; 27 28 @GetMapping("/list") 29 public String queryList(Model model, @RequestHeader(value = "userId", required = false) String userId) { 30 List<ArticleModel> articleModelList = articleService.queryList(); 31 model.addAttribute("articles", articleModelList); 32 return "article/list"; 33 } 34 35 @RequestMapping(value = "/{id}", method = RequestMethod.GET) 36 public ModelAndView queryById(@PathVariable(value = "id", required = true) Long id) { 37 ArticleModel articleModel = articleService.getById(id); 38 ModelAndView mv = new ModelAndView(); 39 mv.setViewName("article/show"); 40 mv.addObject("article", articleModel); 41 return mv; 42 } 43 44 @RequestMapping(value = "/update_with_post", method = RequestMethod.POST) 45 public String update_with_post(@ModelAttribute(value = "article") ArticleModel article) { 46 System.out.println(article); 47 return "index"; 48 } 49 50 @RequestMapping(value = "/update_with_post_file", method = RequestMethod.POST, consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) 51 public String update_with_post_file(@ModelAttribute(value = "article") ArticleModel article, @RequestBody MultipartFile file, HttpServletRequest request) { 52 System.out.println(article); 53 System.out.println(file); 54 String id = request.getParameter("id"); 55 String title = request.getParameter("title"); 56 String content = request.getParameter("content"); 57 System.out.println(String.format("%s,%s,%s", id, title, content)); 58 59 return "index"; 60 } 61 62 @RequestMapping(value = "/update_with_put", method = RequestMethod.PUT) 63 public String update_with_put(@ModelAttribute(value = "article") ArticleModel article) { 64 System.out.println(article); 65 return "index"; 66 } 67 68 @RequestMapping(value = "/update_with_put_file", method = RequestMethod.PUT, consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) 69 public String update_with_put_file(@ModelAttribute(value = "article") ArticleModel article, @RequestBody MultipartFile file, HttpServletRequest request) { 70 System.out.println(article); 71 System.out.println(file); 72 String id = request.getParameter("id"); 73 String title = request.getParameter("title"); 74 String content = request.getParameter("content"); 75 System.out.println(String.format("%s,%s,%s", id, title, content)); 76 77 return "index"; 78 } 79 }
给demo工程配置tomcat:
之后启动后可以从Console上打印信息,查看到端口,我这里端口是9090
1)Post(不含上传文件)方式提交
在http://localhost:9090/article/1页面中:
对应show.jsp上的内容:
按照上边新建项目的web.xml、applicationContext.xml、ArticleController.java,提交'Post方式提交:,后台就能正常接收到参数,此时后台打印信息如下:
[DEBUG] POST "/article/update_with_post", parameters={masked} [DEBUG] Mapped to com.dx.test.controller.ArticleController#update_with_post(ArticleModel) ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容', createTime=null, createUser='null', createUserId='null', modifyTime=null, modifyUser='null', modifyUserId='null'} [DEBUG] View name 'index', model {article=ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容', createTime=null, createUser='null', createUserId='null', modifyTime=null, modifyUser='null', modifyUserId='null'}, org.springframework.validation.BindingResult.article=org.springframework.validation.BeanPropertyBindingResult: 0 errors} [DEBUG] Forwarding to [/WEB-INF/views/index.jsp] [DEBUG] Completed 200 OK
[DEBUG] POST "/article/update_with_post", parameters={masked} [DEBUG] Mapped to com.dx.test.controller.ArticleController#update_with_post(ArticleModel) ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容', createTime=null, createUser='null', createUserId='null', modifyTime=null, modifyUser='null', modifyUserId='null'} [DEBUG] View name 'index', model {article=ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容', createTime=null, createUser='null', createUserId='null', modifyTime=null, modifyUser='null', modifyUserId='null'}, org.springframework.validation.BindingResult.article=org.springframework.validation.BeanPropertyBindingResult: 0 errors} [DEBUG] Forwarding to [/WEB-INF/views/index.jsp] [DEBUG] Completed 200 OK
备注:
1)post不含上传文件的意思是:form表单中不包含属性enctype="multipart/form-data"设置。
2)上边日志包含两次提交分别代表/WEB-INF/views/article/show.jsp页面中“Post方式提交:”下边的两个表单提交:第一个表单是jst方式的表单,第二个表单是纯html的表单。
2)Post(包含上传文件)方式提交
在http://localhost:9090/article/1页面中:
对应show.jsp中内容:
因为是上传文件,而且handler方法使用HttpServletRequest参数,因此需要在pom.xml中引入上传文件依赖包,和servlet包:
<!-- servlet相关,在handler参数中中包含:HttpServletRequest request参数时,需要引入javax.servlet依赖 <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <!--form 设置为enctype="multipart/form-data",多文件上传,在applicationContext.xml中配置了bean multipartResolver时,需要依赖该包。--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency>
按照上边新建项目的web.xml、applicationContext.xml、ArticleController.java,提交'Post包含上传文件提交:',后台不能正常接收到参数,此时后台打印信息如下:
[DEBUG] POST "/article/update_with_post_file", parameters={} [DEBUG] Mapped to com.dx.test.controller.ArticleController#update_with_post_file(ArticleModel, MultipartFile, HttpServletRequest) ArticleModel{id=null, categoryId=null, title='null', content='null', createTime=null, createUser='null', createUserId='null', modifyTime=null, modifyUser='null', modifyUserId='null'} null null,null,null [DEBUG] View name 'index', model {article=ArticleModel{id=null, categoryId=null, title='null', content='null', createTime=null, createUser='null', createUserId='null', modifyTime=null, modifyUser='null', modifyUserId='null'}, org.springframework.validation.BindingResult.article=org.springframework.validation.BeanPropertyBindingResult: 0 errors} [DEBUG] Forwarding to [/WEB-INF/views/index.jsp] [DEBUG] Completed 200 OK
[DEBUG] POST "/article/update_with_post_file", parameters={} [DEBUG] Mapped to com.dx.test.controller.ArticleController#update_with_post_file(ArticleModel, MultipartFile, HttpServletRequest) ArticleModel{id=null, categoryId=null, title='null', content='null', createTime=null, createUser='null', createUserId='null', modifyTime=null, modifyUser='null', modifyUserId='null'} null null,null,null [DEBUG] View name 'index', model {article=ArticleModel{id=null, categoryId=null, title='null', content='null', createTime=null, createUser='null', createUserId='null', modifyTime=null, modifyUser='null', modifyUserId='null'}, org.springframework.validation.BindingResult.article=org.springframework.validation.BeanPropertyBindingResult: 0 errors} [DEBUG] Forwarding to [/WEB-INF/views/index.jsp] [DEBUG] Completed 200 OK
备注:
1)post包含上传文件的意思是:form表单中包含属性enctype="multipart/form-data"设置。
2)上边日志包含两次提交分别代表/WEB-INF/views/article/show.jsp页面中“Post包含上传文件提交:”下边的两个表单提交:第一个表单是jst方式的表单,第二个表单是纯html的表单。
从上边日志可以看到,按照新建项目的方式提交“Post包含上传文件”的表单,后台是接收不到文件和article参数,而且request中也接收不到id,title,content参数。
此时,需要修改applicationContext.xml和web.xml才能实现后端接收到file和参数信息:
applicationContext.xml中需要注册bean“multipartResolver”:
<!-- 配置文件上传解析器 enctype="multipart/form-data" --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 指定所上传文件的总大小不能超过20M。注意maxUploadSize属性的限制不是针对单个文件,而是所有文件的容量之和 --> <property name="maxUploadSize" value="209715200"/> <property name="defaultEncoding" value="UTF-8"/> <property name="resolveLazily" value="true"/> </bean>
web.xml需要加入以下filter“MultipartFilter”和引入listener“ContextLoaderListener”:
<!-- 全局初始化数据,spring的监听器读取此配置文件,多个配置文件用分号分隔 如果在web.xml中不写任何参数配置信息,默认的路径是/WEB-INF/applicationContext.xml,在WEB-INF目录下创建的xml文件的名称必须是applicationContext.xml; 如果是要自定义文件名可以在web.xml里加入contextConfigLocation这个context参数: --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 文件上传与下载过滤器:form表单中存在文件时,该过滤器可以处理http请求中的文件,被该过滤器过滤后会用post方法提交,form表单需设为enctype="multipart/form-data"--> <!-- 注意:必须放在HiddenHttpMethodFilter过滤器之前 --> <filter> <filter-name>MultipartFilter</filter-name> <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class> <init-param> <param-name>multipartResolverBeanName</param-name> <!--spring中配置的id为multipartResolver的解析器--> <param-value>multipartResolver</param-value> </init-param> </filter> <filter-mapping> <filter-name>MultipartFilter</filter-name> <!--<servlet-name>myAppServletName</servlet-name>--> <url-pattern>/*</url-pattern> </filter-mapping>
此时重新提交两个表单,后台打印日志如下:
[DEBUG] Using MultipartResolver 'multipartResolver' for MultipartFilter [DEBUG] Part 'file', size 9 bytes, filename='test.svg' [DEBUG] POST "/article/update_with_post_file", parameters={masked} [DEBUG] Mapped to com.dx.test.controller.ArticleController#update_with_post_file(ArticleModel, MultipartFile, HttpServletRequest) ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容'} org.springframework.web.multipart.commons.CommonsMultipartFile@7df79c2d 1,算法与数据结构--综合提升篇(c++版),文章内容 [DEBUG] View name 'index', model {article=ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容'}, org.springframework.validation.BindingResult.article=org.springframework.validation.BeanPropertyBindingResult: 0 errors} [DEBUG] Forwarding to [/WEB-INF/views/index.jsp] [DEBUG] Completed 200 OK [DEBUG] Cleaning up part 'file', filename 'test.svg'
[DEBUG] Using MultipartResolver 'multipartResolver' for MultipartFilter [DEBUG] Part 'file', size 20098 bytes, filename='试用期考核报告-员工版.xlsx' [DEBUG] POST "/article/update_with_post_file", parameters={masked} [DEBUG] Mapped to com.dx.test.controller.ArticleController#update_with_post_file(ArticleModel, MultipartFile, HttpServletRequest) ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容'} org.springframework.web.multipart.commons.CommonsMultipartFile@448bda6e 1,算法与数据结构--综合提升篇(c++版),文章内容 [DEBUG] View name 'index', model {article=ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容'}, org.springframework.validation.BindingResult.article=org.springframework.validation.BeanPropertyBindingResult: 0 errors} [DEBUG] Forwarding to [/WEB-INF/views/index.jsp] [DEBUG] Completed 200 OK [DEBUG] Cleaning up part 'file', filename '试用期考核报告-员工版.xlsx'
3)Put(不含上传文件)方式提交
在http://localhost:9090/article/1页面中:
对应show.jsp中内容:
按照上边新建项目的web.xml、applicationContext.xml、ArticleController.java,提交'Put方式提交:',后台不能正常接收到参数,此时提交后页面会跳转到405错误页面:
服务器打印日志信息如下:
DEBUG] POST "/article/update_with_put", parameters={masked}
[WARNING] Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
[DEBUG] Completed 405 METHOD_NOT_ALLOWED
[DEBUG] POST "/article/update_with_put", parameters={masked}
[WARNING] Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
[DEBUG] Completed 405 METHOD_NOT_ALLOWED
备注:
1)post不含上传文件的意思是:form表单中不包含属性enctype="multipart/form-data"设置。
2)上边日志包含两次提交分别代表/WEB-INF/views/article/show.jsp页面中“Put方式提交:”下边的两个表单提交:第一个表单是jst方式的表单,第二个表单是纯html的表单。
从错误页面和日志来查看,该错误原因是,springmvc默认不能以form post+<input type="hidden" name="_method" value="put"/>方式实现put提交方式。
解决该错误的方案:
修改web.xml添加HiddenHtmlMethodFilter filter。
<!-- 注意:HiddenHttpMethodFilter必须作用于dispatcher前 请求method支持 put 和 delete 必须添加该过滤器 作用:可以过滤所有请求,并可以分为四种 使用该过滤器需要在前端页面加隐藏表单域 <input type="hidden" name="_method" value="请求方式(put/delete)"> post会寻找_method中的请求式是不是put 或者 delete,如果不是 则默认post请求 --> <filter> <filter-name>hiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenHttpMethodFilter</filter-name> <!--servlet为springMvc的servlet名 --> <servlet-name>myAppServletName</servlet-name> <!--<url-pattern>/*</url-pattern>--> </filter-mapping>
修改web.xml配置之后,重新提交两个表单,后台打印结果如下:
[DEBUG] PUT "/article/update_with_put", parameters={masked}
[DEBUG] Mapped to com.dx.test.controller.ArticleController#update_with_put(ArticleModel)
ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容'}
[DEBUG] View name 'index', model {article=ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容'}, org.springframework.validation.BindingResult.article=org.springframework.validation.BeanPropertyBindingResult: 0 errors}
[DEBUG] Forwarding to [/WEB-INF/views/index.jsp]
[DEBUG] Completed 200 OK
[DEBUG] PUT "/article/update_with_put", parameters={masked}
[DEBUG] Mapped to com.dx.test.controller.ArticleController#update_with_put(ArticleModel)
ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容'}
[DEBUG] View name 'index', model {article=ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容'}, org.springframework.validation.BindingResult.article=org.springframework.validation.BeanPropertyBindingResult: 0 errors}
[DEBUG] Forwarding to [/WEB-INF/views/index.jsp]
[DEBUG] Completed 200 OK
4)Put(包含上传文件)方式提交
在http://localhost:9090/article/1页面中:
对应show.jsp中内容:
因为是上传文件,而且handler方法使用HttpServletRequest参数,因此需要在pom.xml中引入上传文件依赖包,和servlet包:
<!-- servlet相关,在handler参数中中包含:HttpServletRequest request参数时,需要引入javax.servlet依赖 <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <!--form 设置为enctype="multipart/form-data",多文件上传,在applicationContext.xml中配置了bean multipartResolver时,需要依赖该包。--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency>
按照上边新建项目的web.xml、applicationContext.xml、ArticleController.java,提交'Put方式提交:',后台不能正常接收到参数,此时提交后页面会跳转到405错误页面:
服务器打印日志信息如下:
DEBUG] POST "/article/update_with_put_file", parameters={masked}
[WARNING] Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
[DEBUG] Completed 405 METHOD_NOT_ALLOWED
[DEBUG] POST "/article/update_with_put_file", parameters={masked}
[WARNING] Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
[DEBUG] Completed 405 METHOD_NOT_ALLOWED
备注:
1)post不含上传文件的意思是:form表单中不包含属性enctype="multipart/form-data"设置。
2)上边日志包含两次提交分别代表/WEB-INF/views/article/show.jsp页面中“Put方式提交:”下边的两个表单提交:第一个表单是jst方式的表单,第二个表单是纯html的表单。
从错误页面和日志来查看,该错误原因是,springmvc默认不能以form post+<input type="hidden" name="_method" value="put"/>方式实现put提交方式。
解决该错误的方案:
1)为了实现put方式提交修改web.xml,添加HiddenHtmlMethodFilter filter;
2)为了实现上传文件需要修改web.xml,添加filter“MultipartFilter”和引入listener“ContextLoaderListener”;
3)为了实现上传文件需要修改applicaitonContext.xml,注册bean“multipartResolver”。
web.xml修改后内容为:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>springmvcdemo</display-name> <welcome-file-list> <welcome-file>/index</welcome-file> </welcome-file-list> <!-- 全局初始化数据,spring的监听器读取此配置文件,多个配置文件用分号分隔 如果在web.xml中不写任何参数配置信息,默认的路径是/WEB-INF/applicationContext.xml,在WEB-INF目录下创建的xml文件的名称必须是applicationContext.xml; 如果是要自定义文件名可以在web.xml里加入contextConfigLocation这个context参数: --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 文件上传与下载过滤器:form表单中存在文件时,该过滤器可以处理http请求中的文件,被该过滤器过滤后会用post方法提交,form表单需设为enctype="multipart/form-data"--> <!-- 注意:必须放在HiddenHttpMethodFilter过滤器之前 --> <filter> <filter-name>MultipartFilter</filter-name> <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class> <init-param> <param-name>multipartResolverBeanName</param-name> <!--spring中配置的id为multipartResolver的解析器--> <param-value>multipartResolver</param-value> </init-param> </filter> <filter-mapping> <filter-name>MultipartFilter</filter-name> <!--<servlet-name>myAppServletName</servlet-name>--> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 注意:HiddenHttpMethodFilter必须作用于dispatcher前 请求method支持 put 和 delete 必须添加该过滤器 作用:可以过滤所有请求,并可以分为四种 使用该过滤器需要在前端页面加隐藏表单域 <input type="hidden" name="_method" value="请求方式(put/delete)"> post会寻找_method中的请求式是不是put 或者 delete,如果不是 则默认post请求 --> <filter> <filter-name>hiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenHttpMethodFilter</filter-name> <!--servlet为springMvc的servlet名 --> <servlet-name>myAppServletName</servlet-name> <!--<url-pattern>/*</url-pattern>--> </filter-mapping> <!--结束后端数据输出到前端乱码问题--> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> <!--可以通过配置覆盖默认'_method'值 --> <init-param> <param-name>methodParam</param-name> <param-value>_method</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>myAppServletName</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>myAppServletName</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
applicationContext.xml修改后内容为:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--扫描所有的 spring包下的文件;--> <!--当然需要在spring配置文件里面配置一下自动扫描范围 <context:component-scan base-package="*"/> *代表你想要扫描的那些包的目录所在位置。Spring 在容器初始化时将自动扫描 base-package 指定的包及其子包下的所有的.class文件, 所有标注了 @Repository 的类都将被注册为 Spring Bean。 --> <context:component-scan base-package="com.dx.test"/> <!--新增加的两个配置,这个是解决406问题的关键--> <!--mvc注解驱动(可代替注解适配器与注解映射器的配置),默认加载很多参数绑定方法(实际开发时使用)--> <context:annotation-config/> <mvc:annotation-driven/> <!-- <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.dx.test.interceptors.LogInterceptor"/> </mvc:interceptor> </mvc:interceptors> --> <!--end--> <!-- <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/> --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> <property name="contentType" value="text/html;charset=UTF-8" /> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> </bean> <!-- 配置文件上传解析器 enctype="multipart/form-data" --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 指定所上传文件的总大小不能超过20M。注意maxUploadSize属性的限制不是针对单个文件,而是所有文件的容量之和 --> <property name="maxUploadSize" value="209715200"/> <property name="defaultEncoding" value="UTF-8"/> <property name="resolveLazily" value="true"/> </bean> <!--自己后加的,该BeanPostProcessor将自动对标注@Autowired的bean进行注入--> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"></bean> <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> <property name="messageConverters"> <list> <!--<ref bean="stringHttpMessageConverter"/>--> <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/> <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/> <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/> <bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/> <!-- <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/> --> </list> </property> </bean> </beans>
修改后,重新提交两个表单,此时服务端打印日志如下:
[DEBUG] Using MultipartResolver 'multipartResolver' for MultipartFilter
[DEBUG] Part 'file', size 1181 bytes, filename='ImageVO.java'
[DEBUG] PUT "/article/update_with_put_file", parameters={masked}
[DEBUG] Mapped to com.dx.test.controller.ArticleController#update_with_put_file(ArticleModel, MultipartFile, HttpServletRequest)
ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容'}
org.springframework.web.multipart.commons.CommonsMultipartFile@62032272
1,算法与数据结构--综合提升篇(c++版),文章内容
[DEBUG] View name 'index', model {article=ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容'}, org.springframework.validation.BindingResult.article=org.springframework.validation.BeanPropertyBindingResult: 0 errors}
[DEBUG] Forwarding to [/WEB-INF/views/index.jsp]
[DEBUG] Completed 200 OK
[DEBUG] Cleaning up part 'file', filename 'ImageVO.java'
[DEBUG] Using MultipartResolver 'multipartResolver' for MultipartFilter
[DEBUG] Part 'file', size 1732 bytes, filename='UploadImgParam.java'
[DEBUG] PUT "/article/update_with_put_file", parameters={masked}
[DEBUG] Mapped to com.dx.test.controller.ArticleController#update_with_put_file(ArticleModel, MultipartFile, HttpServletRequest)
ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容'}
org.springframework.web.multipart.commons.CommonsMultipartFile@32d8a82d
1,算法与数据结构--综合提升篇(c++版),文章内容
[DEBUG] View name 'index', model {article=ArticleModel{id=1, categoryId=null, title='算法与数据结构--综合提升篇(c++版)', content='文章内容'}, org.springframework.validation.BindingResult.article=org.springframework.validation.BeanPropertyBindingResult: 0 errors}
[DEBUG] Forwarding to [/WEB-INF/views/index.jsp]
[DEBUG] Completed 200 OK
[DEBUG] Cleaning up part 'file', filename 'UploadImgParam.java'
备注:该web.xml和applicationContext.xml的配置方式,可以支持post方式提交、post+上传文件提交、put提交、put+上传文件提交。因此,推荐使用该配置。
总结:
1)form属性设置encrypt='mutilpart/form-data'时,如何正确配置web.xml才能以put方式提交表单?
1)为了实现put方式提交修改web.xml,添加HiddenHtmlMethodFilter filter;
2)为了实现上传文件需要修改web.xml,添加filter“MultipartFilter”和引入listener“ContextLoaderListener”;
3)为了实现上传文件需要修改applicaitonContext.xml,注册bean“multipartResolver”。
备注:
1)如果multipartResolver bean配置的是org.springframework.web.multipart.commons.CommonsMultipartResolver,因为CommonsMultipartResolver依赖commons-fileupload.jar和commons-io.jar,所以需要pom.xml引入这两个包。
2)handler方法使用HttpServletRequest request作为参数,则需要在pom.xml中引入servlet包。
2)留3个问题:
1)ContextLoaderListener在Web.xml中配置与不配置的区别:
为什么上边上传文件方式需要配置它,不配置会导致上传文件后端接收不到;
它在上传文件中是不是必须配置的吗?
2)web.xml 中的 ContextLoaderListener 是干什么用的?
3)web.xml 中的 DispatcherServlet 是如何加载的,它其什么作用?
基础才是编程人员应该深入研究的问题,比如:
1)List/Set/Map内部组成原理|区别
2)mysql索引存储结构&如何调优/b-tree特点、计算复杂度及影响复杂度的因素。。。
3)JVM运行组成与原理及调优
4)Java类加载器运行原理
5)Java中GC过程原理|使用的回收算法原理
6)Redis中hash一致性实现及与hash其他区别
7)Java多线程、线程池开发、管理Lock与Synchroined区别
8)Spring IOC/AOP 原理;加载过程的。。。
【+加关注】。