zoukankan      html  css  js  c++  java
  • spring mvc踩坑记

    前言

    主要介绍自己在学习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

     1 <%@ page language="java" contentType="text/html; charset=utf-8"
     2     pageEncoding="utf-8"%>
     3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
     4 <html>
     5 <head>
     6 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     7 <title>Insert title here</title>
     8 <script type="text/javascript"
     9     src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.min.js"></script>
    10 </head>
    11 <body>
    12     <div>
    13         id:<input type="text" id="id" value="123456"><br>
    14         menuName:<input type="text" id="menuName" value="李白"><br>
    15         <input type="button" id="abc" value="test">
    16     </div>
    17 
    18     <script type="text/javascript">
    19         window.onload = function() {
    20             $("#abc").click(function() {
    21                 var menu = {
    22                     "id" : $("#id").val(),
    23                     "menuName" : $("#menuName").val()
    24                 };
    25                 var jsonStr = JSON.stringify(menu);
    26                 $.ajax({
    27                     type : "POST",
    28                     async : false,
    29                     url : "http://localhost:8080/ssm/getList",
    30                     dataType : "json",
    31                     contentType : "application/json;charset=UTF-8",
    32                     data : jsonStr,
    33                     success : function(data) {
    34                         alert("123");
    35                     }
    36                 });
    37             });
    38         }
    39     </script>
    40 </body>
    41 </html>


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

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


    TestSpringMvcController.java

     1 package com.dg.action;
     2 
     3 import org.springframework.stereotype.Controller;
     4 import org.springframework.web.bind.annotation.RequestBody;
     5 import org.springframework.web.bind.annotation.RequestMapping;
     6 
     7 import com.dg.bean.Menu;
     8 
     9 @Controller
    10 public class TestSpringMvcController {
    11 
    12     @RequestMapping("getList")
    13     public void getList(@RequestBody Menu menu){
    14         System.out.println("menu:" + menu);
    15     }
    16 }


    Menu.java

     1 package com.dg.bean;
     2 
     3 import java.io.Serializable;
     4 
     5 public class Menu implements Serializable {
     6 
     7     private static final long serialVersionUID = 410202860691610816L;
     8     private String id;
     9     private String menuCode;
    10     private String menuName;
    11     private String menuUrl;
    12     private String parentMenuId;
    13 
    14     public String getId() {
    15         return id;
    16     }
    17 
    18     public void setId(String id) {
    19         this.id = id;
    20     }
    21 
    22     public String getMenuCode() {
    23         return menuCode;
    24     }
    25 
    26     public void setMenuCode(String menuCode) {
    27         this.menuCode = menuCode;
    28     }
    29 
    30     public String getMenuName() {
    31         return menuName;
    32     }
    33 
    34     public void setMenuName(String menuName) {
    35         this.menuName = menuName;
    36     }
    37 
    38     public String getMenuUrl() {
    39         return menuUrl;
    40     }
    41 
    42     public void setMenuUrl(String menuUrl) {
    43         this.menuUrl = menuUrl;
    44     }
    45 
    46     public String getParentMenuId() {
    47         return parentMenuId;
    48     }
    49 
    50     public void setParentMenuId(String parentMenuId) {
    51         this.parentMenuId = parentMenuId;
    52     }
    53 
    54     @Override
    55     public String toString() {
    56         return "Menu [id=" + id + ", menuCode=" + menuCode + ", menuName=" + menuName + ", menuUrl=" + menuUrl
    57                 + ", parentMenuId=" + parentMenuId + "]";
    58     }
    59 }

    spring-config.xml(进行了最大程度精简)

    1 <?xml version="1.0" encoding="UTF-8"?>
    2 <beans xmlns="http://www.springframework.org/schema/beans"
    3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    5 
    6     
    7 </beans>

    spring-mvc.xml

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xmlns:mvc="http://www.springframework.org/schema/mvc" 
     6     xsi:schemaLocation="http://www.springframework.org/schema/beans    
     7                             http://www.springframework.org/schema/beans/spring-beans-4.0.xsd    
     8                             http://www.springframework.org/schema/context    
     9                             http://www.springframework.org/schema/context/spring-context-4.0.xsd    
    10                             http://www.springframework.org/schema/mvc
    11                             http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
    12                             ">
    13     <!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器 -->
    14     <context:component-scan base-package="com.dg.action" />
    15 
    16     <!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->
    17     <mvc:annotation-driven/>
    18     
    19     <!-- 定义跳转的文件的前后缀 ,视图模式配置 -->
    20      <bean
    21         class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    22         <property name="prefix" value="/WEB-INF/jsp/" />
    23         <property name="suffix" value=".jsp" />
    24     </bean> 
    25 
    26 
    27 </beans> 

    web.xml

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     3     xmlns="http://java.sun.com/xml/ns/javaee"
     4     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
     5     version="3.0">
     6     <display-name>ssm</display-name>
     7     <!-- Spring和mybatis的配置文件 -->
     8     <context-param>
     9         <param-name>contextConfigLocation</param-name>
    10         <param-value>classpath:spring-config.xml</param-value>
    11     </context-param>
    12     <!-- 编码过滤器 -->
    13     <filter>
    14         <filter-name>encodingFilter</filter-name>
    15         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    16         <async-supported>true</async-supported>
    17         <init-param>
    18             <param-name>encoding</param-name>
    19             <param-value>UTF-8</param-value>
    20         </init-param>
    21     </filter>
    22     <filter-mapping>
    23         <filter-name>encodingFilter</filter-name>
    24         <url-pattern>/*</url-pattern>
    25     </filter-mapping>
    26     <!-- Spring监听器 -->
    27     <listener>
    28         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    29     </listener>
    30     <!-- 防止Spring内存溢出监听器 -->
    31     <listener>
    32         <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    33     </listener>
    34 
    35     <!-- Spring MVC servlet -->
    36     <servlet>
    37         <servlet-name>SpringMVC</servlet-name>
    38         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    39         <init-param>
    40             <param-name>contextConfigLocation</param-name>
    41             <param-value>classpath:spring-mvc.xml</param-value>
    42         </init-param>
    43         <load-on-startup>1</load-on-startup>
    44         <async-supported>true</async-supported>
    45     </servlet>
    46     <servlet-mapping>
    47         <servlet-name>SpringMVC</servlet-name>
    48         <!-- 此处可以可以配置成*.do,对应struts的后缀习惯 -->
    49         <url-pattern>/</url-pattern>
    50     </servlet-mapping>
    51     <!-- 设置静态资源映射 -->
    52     <servlet-mapping>
    53         <servlet-name>default</servlet-name>
    54         <url-pattern>*.jpg</url-pattern>
    55     </servlet-mapping>
    56     <servlet-mapping>
    57         <servlet-name>default</servlet-name>
    58         <url-pattern>*.gif</url-pattern>
    59     </servlet-mapping>
    60     
    61     <servlet-mapping>
    62         <servlet-name>default</servlet-name>
    63         <url-pattern>*.png</url-pattern>
    64     </servlet-mapping>
    65     
    66     <servlet-mapping>
    67         <servlet-name>default</servlet-name>
    68         <url-pattern>*.js</url-pattern>
    69     </servlet-mapping>
    70     <servlet-mapping>
    71         <servlet-name>default</servlet-name>
    72         <url-pattern>*.css</url-pattern>
    73     </servlet-mapping>
    74     <welcome-file-list>
    75         <welcome-file>/index.jsp</welcome-file>
    76     </welcome-file-list>
    77 
    78 </web-app> 

    pom.xml

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     3     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
     4 
     5     <modelVersion>4.0.0</modelVersion>
     6     <packaging>war</packaging>
     7 
     8     <name>ssm</name>
     9     <groupId>dg</groupId>
    10     <artifactId>ssm</artifactId>
    11     <version>0.0.1-SNAPSHOT</version>
    12 
    13     <properties>
    14         <!-- spring版本号 -->
    15         <spring.version>4.3.3.RELEASE</spring.version>
    16         <!-- log4j日志文件管理包版本 -->
    17         <slf4j.version>1.7.7</slf4j.version>
    18         <log4j.version>1.2.17</log4j.version>
    19     </properties>
    20 
    21     <dependencies>
    22         <!-- spring核心包 -->
    23         <dependency>
    24             <groupId>org.springframework</groupId>
    25             <artifactId>spring-core</artifactId>
    26             <version>${spring.version}</version>
    27         </dependency>
    28         <dependency>
    29             <groupId>org.springframework</groupId>
    30             <artifactId>spring-web</artifactId>
    31             <version>${spring.version}</version>
    32         </dependency>
    33         <dependency>
    34             <groupId>org.springframework</groupId>
    35             <artifactId>spring-webmvc</artifactId>
    36             <version>${spring.version}</version>
    37         </dependency>
    38         <!-- 日志文件管理包 -->
    39         <!-- log start -->
    40         <dependency>
    41             <groupId>log4j</groupId>
    42             <artifactId>log4j</artifactId>
    43             <version>${log4j.version}</version>
    44         </dependency>
    45         <dependency>
    46             <groupId>org.codehaus.jackson</groupId>
    47             <artifactId>jackson-mapper-asl</artifactId>
    48             <version>1.9.13</version>
    49         </dependency>
    50     
    51     </dependencies>
    52 </project>

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

    后台报错的日志为:

     1 [org.springframework.web.servlet.DispatcherServlet] - DispatcherServlet with name 'SpringMVC' processing POST request for [/ssm/getList]
     2   [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] - Looking up handler method for path /getList
     3   [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] - Returning handler method [public void com.dg.action.TestSpringMvcController.getList(com.dg.bean.Menu)]
     4   [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'testSpringMvcController'
     5   [org.springframework.web.cors.DefaultCorsProcessor] - Skip CORS processing: request is from same origin
     6   [org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod] - Error resolving argument [0] [type=com.dg.bean.Menu]
     7 HandlerMethod details: 
     8 Controller [com.dg.action.TestSpringMvcController]
     9 Method [public void com.dg.action.TestSpringMvcController.getList(com.dg.bean.Menu)]
    10 
    11   org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
    12     at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:235)
    13     at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:149)
    14     at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:127)
    15     at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
    16     at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
    17     at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
    18     at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
    19     at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    20     at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    21     at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    22     at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    23     at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    24     at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    25     at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    26     at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
    27     at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    28     at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    29     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    30     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    31     at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    32     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    33     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    34     at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    35     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    36     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    37     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    38     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    39     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    40     at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
    41     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    42     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    43     at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    44     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    45     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
    46     at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1074)
    47     at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
    48     at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    49     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    50     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    51     at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    52     at java.lang.Thread.run(Thread.java:745)
    53 [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
    54   [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
    55   [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
    56   [org.springframework.web.servlet.DispatcherServlet] - Null ModelAndView returned to DispatcherServlet with name 'SpringMVC': assuming HandlerAdapter completed request handling
    57   [org.springframework.web.servlet.DispatcherServlet] - Successfully completed request
    58   

    看到这个报错提示的第一反应是把前台请求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也成功实现目标。

     (完)

  • 相关阅读:
    Kafka 生产者 自定义分区策略
    同步互斥
    poj 1562 Oil Deposits(dfs)
    poj 2386 Lake Counting(dfs)
    poj 1915 KnightMoves(bfs)
    poj 1664 放苹果(dfs)
    poj 1543 Perfect Cubes (暴搜)
    poj 1166 The Clocks (暴搜)
    poj 3126 Prime Path(bfs)
    处理机调度
  • 原文地址:https://www.cnblogs.com/frankwin608/p/spring-mvc.html
Copyright © 2011-2022 走看看