前言

主要介绍自己在学习spring mvc过程中踩到的一些坑,涉及到当时遇到这个错误是如何思考的,对思路进行总结,下次遇到类似的错误能够提供一些思路甚至快速解决。

环境准备

jdk8,spring4.3.3.RELEASE,spring mvc与spring版本一致,maven3.2.5,tomcat7

目标:

1.测试spring mvc的json参数绑定功能

2.测试spring mvc的返回json功能

项目目录(已经推送到github:https://github.com/ComingOnuguys/frankwin):

测试1相关代码:
index.jsp

 <%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
<script type="text/javascript"
src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.min.js"></script>
</head>
<body>
<div>
id:<input type="text" id="id" value="123456"><br>
menuName:<input type="text" id="menuName" value="李白"><br>
<input type="button" id="abc" value="test">
</div> <script type="text/javascript">
window.onload = function() {
$("#abc").click(function() {
var menu = {
"id" : $("#id").val(),
"menuName" : $("#menuName").val()
};
var jsonStr = JSON.stringify(menu);
$.ajax({
type : "POST",
async : false,
url : "http://localhost:8080/ssm/getList",
dataType : "json",
contentType : "application/json;charset=UTF-8",
data : jsonStr,
success : function(data) {
alert("123");
}
});
});
}
</script>
</body>
</html>

getList.jsp(为了返回的时候不报404的错)

 <%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.min.js"></script>
</head>
<body> <h2>陈公告</h2> </body>
</html>

TestSpringMvcController.java

 package com.dg.action;

 import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import com.dg.bean.Menu; @Controller
public class TestSpringMvcController { @RequestMapping("getList")
public void getList(@RequestBody Menu menu){
System.out.println("menu:" + menu);
}
}

Menu.java

 package com.dg.bean;

 import java.io.Serializable;

 public class Menu implements Serializable {

     private static final long serialVersionUID = 410202860691610816L;
private String id;
private String menuCode;
private String menuName;
private String menuUrl;
private String parentMenuId; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getMenuCode() {
return menuCode;
} public void setMenuCode(String menuCode) {
this.menuCode = menuCode;
} public String getMenuName() {
return menuName;
} public void setMenuName(String menuName) {
this.menuName = menuName;
} public String getMenuUrl() {
return menuUrl;
} public void setMenuUrl(String menuUrl) {
this.menuUrl = menuUrl;
} public String getParentMenuId() {
return parentMenuId;
} public void setParentMenuId(String parentMenuId) {
this.parentMenuId = parentMenuId;
} @Override
public String toString() {
return "Menu [id=" + id + ", menuCode=" + menuCode + ", menuName=" + menuName + ", menuUrl=" + menuUrl
+ ", parentMenuId=" + parentMenuId + "]";
}
}

spring-config.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> </beans>

spring-mvc.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:p="http://www.springframework.org/schema/p"
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-4.0.xsd
">
<!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器 -->
<context:component-scan base-package="com.dg.action" /> <!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->
<mvc:annotation-driven/> <!-- 定义跳转的文件的前后缀 ,视图模式配置 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean> </beans>

web.xml

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>ssm</display-name>
<!-- Spring和mybatis的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-config.xml</param-value>
</context-param>
<!-- 编码过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 防止Spring内存溢出监听器 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener> <!-- Spring MVC servlet -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<!-- 此处可以可以配置成*.do,对应struts的后缀习惯 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 设置静态资源映射 -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.gif</url-pattern>
</servlet-mapping> <servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping> <servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list> </web-app>

pom.xml

 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion>
<packaging>war</packaging> <name>ssm</name>
<groupId>dg</groupId>
<artifactId>ssm</artifactId>
<version>0.0.1-SNAPSHOT</version> <properties>
<!-- spring版本号 -->
<spring.version>4.3.3.RELEASE</spring.version>
<!-- log4j日志文件管理包版本 -->
<slf4j.version>1.7.7</slf4j.version>
<log4j.version>1.2.17</log4j.version>
</properties> <dependencies>
<!-- spring核心包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 日志文件管理包 -->
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency> </dependencies>
</project>

坑一:spring mvc的json包
对于测试1,采用以上代码一直返回httpcode415 (Unsupported Media Type)。如下图:

后台报错的日志为:

 [org.springframework.web.servlet.DispatcherServlet] - DispatcherServlet with name 'SpringMVC' processing POST request for [/ssm/getList]
[org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] - Looking up handler method for path /getList
[org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] - Returning handler method [public void com.dg.action.TestSpringMvcController.getList(com.dg.bean.Menu)]
[org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'testSpringMvcController'
[org.springframework.web.cors.DefaultCorsProcessor] - Skip CORS processing: request is from same origin
[org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod] - Error resolving argument [0] [type=com.dg.bean.Menu]
HandlerMethod details:
Controller [com.dg.action.TestSpringMvcController]
Method [public void com.dg.action.TestSpringMvcController.getList(com.dg.bean.Menu)] org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:235)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:149)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:127)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1074)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
[org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver] - Resolving exception from handler [public void com.dg.action.TestSpringMvcController.getList(com.dg.bean.Menu)]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
[org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver] - Resolving exception from handler [public void com.dg.action.TestSpringMvcController.getList(com.dg.bean.Menu)]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
[org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver] - Resolving exception from handler [public void com.dg.action.TestSpringMvcController.getList(com.dg.bean.Menu)]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
[org.springframework.web.servlet.DispatcherServlet] - Null ModelAndView returned to DispatcherServlet with name 'SpringMVC': assuming HandlerAdapter completed request handling
[org.springframework.web.servlet.DispatcherServlet] - Successfully completed request

看到这个报错提示的第一反应是把前台请求index.jsp的contentType这一行注释掉(注:不写默认值是application/x-www-form-urlencoded;charset=UTF-8):
//contentType : "application/json;charset=UTF-8",
报错变成了:Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
都不支持,这就没法玩了。考虑controller的参数menu不加@RequestBody能不能参数绑定成功,于是去掉@RequestBody,前台请求注释contentType这一行注释掉,发送的参数由jsonStr这个变量改为menu,发现可以正常注入,根据之前学到的知识,String类型和Json的参数绑定是分别由StringHttpMessageConverter和MappingJackson2HttpMessageConverter进行处理,于是把断点分别打在两个类的构造方法上,断点情况如图:

启动tomcat,发现只进到了StringHttpMessageConverter这个类的构造函数里面。报错的原因找到了(没有加载MappingJackson2HttpMessageConverter),但是为什么没有加载,还不知道原因。重新启动tomcat,顺着StringHttpMessageConverter执行下来,发现有这么一段,

看到MappingJackson2HttpMessageConverter非常眼熟,但是很遗憾,这里的jackson2present变量值是false,

看到这里,接着就是去找该变量是false的原因了。Ctrl+Shift+K找到声明这个变量的地方,

选中com.fasterxml.jackson.databind.ObjectMapper,Ctrl+shift+T,没有找到这个类。嗯,问题就处在这了。意思到有可能有什么包没有加进来。查阅资料得知spring mvc从3.2版本开始依赖的json包由原先的jackson-mapper-asl.jar、jackson-core-asl-1.9.13.jar变更为了jackson-core.jar、jackson-dataformat-xml.jar

于是到mavenrepository找到springmvc4.3.3.RELEASE依赖的包的列表,上面的结论得到验证。

接着修改maven依赖json的包,再使用上面的那些代码,终于大功告成~

总结:


1、ajax请求如果不写contentType,则默认是application/x-www-form-urlencoded;charset=UTF-8

2、@RequestBody的作用是将请求参数的json串绑定到实体类上,要实现这个,请求的contentType要设置成contentType : "application/json;charset=UTF-8"

3、更明确spring mvc的这些默认的处理类在tomcat容器启动时就进行初始化。

4、当怀疑是包依赖产生的问题时,可以到mavenrepository找到该框架依赖的jar包。

包依赖的问题解决后,测试2也成功实现目标。

(完)

最新文章

  1. [速记]关于指针,引用和递归和解递归——C++
  2. c#操作access,update语句不执行的解决办法
  3. HDU 3518 Boring counting(后缀数组,字符处理)
  4. Codeforces 118 D. Caesar&#39;s Legions (dp)
  5. Android开发 设置开机自动启动
  6. ColorFilter类
  7. java学习之面向对象概念
  8. mahout 查看kmeans结果的命令
  9. JSP中列表展示,隔行变色以及S标签的使用
  10. XiaomiPushDemo【小米推送集成,基于V3.6.12版本】
  11. js四则运算
  12. one or more multiply defined symbols found
  13. [UE4]自动旋转组件
  14. SRM387 div1
  15. 一张图看懂Mysql的join连接
  16. Project Euler Problem2
  17. CentOS 7下宿主机使用virsh console访问KVM的设置
  18. 自定义 Maven 的 repositories
  19. 智能指针shared_ptr新特性shared_from_this及weak_ptr
  20. 物联网(IoT)的11大云平台:AWS、Azure、谷歌云、Oracle、

热门文章

  1. C++基础学习8:类的定义(class)
  2. 设置label的文字,一行多种颜色
  3. 【转】C#中HttpWebRequest的GetRequestStream执行的效率太低,甚至偶尔死掉
  4. [JavaScript]Prototype继承
  5. Liunx php函数 smtp 发送邮件
  6. iPhone10.3.X越狱后SSH连接不上的问题(已解决)
  7. WebApi Helper帮助文档 swagger
  8. python学习3(转载)
  9. json处理第一篇:利用Jackson处理json
  10. ckeditor(在线文本编辑器)使用教程