1. 程式人生 > >Spring MVC常見bug總結----持續更新中

Spring MVC常見bug總結----持續更新中

一、

  Spring MVC的配置檔案Springmvc-servlet.xml報錯,在新增

<context:component-scan base-package="controller" />
  來指定控制器所在的包時,視窗顯示紅叉,報錯內容為:

Multiple annotations found at this line:
    - schema_reference.4: Failed to read schema document 'http://www.springframework.org/schema/
     springcontext.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root
     element of the document is not <xsd:schema>.
    - cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element
     'context:component-scan'.

  經過檢查,發現時springmvc-servlet的頭中,關於名稱空間(是不是這麼說的。。。)的定義有誤,導致找不到我對應的檔案。

  之前,我的頭定義如下:

<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:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	                    http://www.springframework.org/schema/beans/spring-beans.xsd
	                    http://www.springframework.org/schema/mvc
	                    http://www.springframework.org/schema/mvc/spring-mvc.xsd
	                    http://www.springframework.org/schema/context
	                    http://www.springframework.org/schema/springcontext.xsd">

xsd等沒有指定正確的檔案版本,根據自己的jar包版本做修改如下:
<beans xmlns:beans="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" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd ">

二、依然是坑爹的配置bug

 我在實驗一個簡單的Spring MVC的demo的時候,所有的程式碼和jar、環境均已經搞定,但是run as server之後,出現:

org.xml.sax.SAXParseException; lineNumber: 12; columnNumber: 75; cvc-elt.1: 找不到元素 'beans' 的宣告
這樣的報錯。

在實驗切xmlns中的檔案版本等等方法之後,依然沒有效果。但是奇怪的是,我之前一個類似的專案,該配置檔案極其類似,只是從傳統控制器風格變成了使用註解控制器,程式並沒有報錯!

後修改,在beans元素前面加上一個名稱空間beans,然後就不報錯了。

前後對比圖如下:

1.發生錯誤的時候:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:beans="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" 
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc 
	    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
		http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-3.0.xsd">
		
		 
	                
	<mvc:annotation-driven/>   
    <!-- ①:對web包中的所有類進行掃描,以完成Bean建立和自動依賴注入的功能 -->
    <context:component-scan base-package="controller" />
    <mvc:resources mapping="/*.html" location="/"/>
    
    <bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	  <property name="prefix" value="/WEB-INF/jsp/" />
	  <property name="suffix" value=".jsp" />
	</bean>
</beans>

2.新增beans名稱空間之後:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="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" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd ">
	<mvc:annotation-driven />
	<!-- ①:對web包中的所有類進行掃描,以完成Bean建立和自動依賴注入的功能 -->
	<context:component-scan base-package="net.use" />

	<!-- 這兩個類用來啟動基於Spring MVC的註解功能,將控制器與方法對映加入到容器中 -->
	<beans:bean
		class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
	<beans:bean
		class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

	<!-- 這個類用於Spring MVC檢視解析 -->
	<beans:bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/pages/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
</beans:beans>
不報錯了。。。

坑爹。。。

到現在還不知道是什麼原因。

3.今天準備嘗試一下實現依賴注入,途中發生了一個有趣的bug。

嚴重: Servlet.service() for servlet [s nested exception is org.springframewo
具體的描述沒了

主要是怎麼回事呢。

說表單資料提交後自動繫結到User類的時候發生了一個錯誤,無法從String物件轉換成自己定義的Connection物件。

恍然想起來,form提交到伺服器的全部是String,但是我們自己定義的類的屬性可能是double,可能是一個物件。

所以為了解決這個問題,參考了之前看到的某篇文章,在轉成User類之前,先換成一個所有屬性都用String表示,屬性值和User類一一對應的UserForm類。如下:

package net.use.info;

import java.io.Serializable;

import net.use.connection.Connection;

public class User implements Serializable {
	/**
	 * @author zjn
	 */
	private static final long serialVersionUID = 1L;
	private String name; // name
	private String pwd; // pwd
	private Integer age; // age
	
	private String sex;
	
	private Connection connection;//connection是介面
	//全部實現了set和get方法�? 以此完成依賴注入(設值注入)
	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex=sex;
	}


	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public Connection getConnection() {
		return connection;
	}

	public void setConnection(Connection connection) {
		this.connection = connection;
	}

}

然後是userForm類
package net.use.form;

public class UserForm {
	private String name; // name
	private String pwd; // pwd
	private Integer age; // age
	
	private String sex;
	
	private String connection;//connection是介面
	private String connection_type;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getConnection() {
		return connection;
	}
	public void setConnection(String connection) {
		this.connection = connection;
	}
	public String getConnection_type() {
		return connection_type;
	}
	public void setConnection_type(String connection_type) {
		this.connection_type = connection_type;
	}
	
	

}

這樣,在Controller中,就可以先把Form資料換成UserForm物件,然後再一個一個把屬性值賦給User物件。如下:
	@RequestMapping("register")
	public String Save(@ModelAttribute("form") UserForm userForm, Model model) { // user:檢視層傳給控制層的表單物件;model:控制層返回給檢視層的對�?
		//model.addAttribute("user", user);
		//System.out.println(user.getName()+","+user.getSex()+","+user.getPwd()+","+user.getAge());
		
		//first,to convert the userform to the user
		User user = new User();
		user.setName(userForm.getName());
		user.setAge(userForm.getAge());
		user.setSex(userForm.getSex());
		user.setPwd(userForm.getPwd());
		
		Connection con;
		if(userForm.getConnection_type().equals("phone")) {
			con = new Phone();
			con.setNumber(userForm.getConnection());
			user.setConnection(con);
		}else if(userForm.getConnection_type().equals("msn")) {
			con = new MSN();
			con.setNumber(userForm.getConnection());
			user.setConnection(con);
		}

怪不得之前看的那篇文章要用什麼Form類,原來是這個鬼。。。。get!