首先在web.xml加上
<web-app>
<servlet>
<servlet-name>springServlet</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>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- DispatcherServlet是Spring Web MVC框架的核心,名字爲springServlet的DispatcherServlet會攔截所有以/開頭的請求,並進行處理
- 每個DispatcherServlet都有自己的WebApplicationContext
- 在DispatcherServlet初始的過程中,Spring會在web應用的WEB-INF文件下尋找名字爲 [servlet-name]-servlet.xml 的配置文件,該文件中聲明瞭你在Spring Web MVC框架中所有所使用的bean,和配置
- 你可以通過servlet的初始化參數來改變該文件的路徑,就像上面的那樣,它會去classpath下面找spring-mvc.xml配置文件來初始化
實體類
package com.modules.entity;
public class User {
private Integer id;
public SiteUser(Integer id){
this.id = id;
}
public SiteUser(){
}
@Override
public String toString(){
return "User" + id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
控制器
package com.modules.web;
@Controller
@RequestMapping(value="${adminPath}/user")
public class UserController{
@ModelAttribute("myUser")
public SiteUser get(@RequestParam(required=false) String id){
System.out.println("Get id" + id);
return new User(Integer.valueOf(id));
}
@RequestMapping(value="form")
public String form(@ModelAttribute("myUser") User user, Model model){
model.addAttribute("error", "getError");
for (String name : model.asMap().keySet()){
System.out.println(name);
}
System.out.println("get" + user);
return "userForm";
}
@RequestMapping(value="into")
public String into(@ModelAttribute("myUser") User user, Model model){
model.addAttribute("error1", "getError1");
System.out.println("get" + user);
return "userForm";
}
}
1.@RequestMapping(value=”${adminPath}/user”)這句話就是映射的請求的路徑,相當於將配置文件properties文件裏面的值拿出來,相當於/admin/user,adminPath爲key,他會將匹配的路徑統一交給該處理器處理
2.@ModelAttribute(“myUser”),相當於給get方法的返回值起了一個名字放入Model對象中(map),key爲myUser,value爲返回值。每次交給處理器處理的時候都會先執行get方法。
3.你可以看到into和form方法都有用上@ModelAttribute(“myUser”),因爲如果不加上執行該方法的時候它會默認在Model對象裏面尋找key爲user沒有就自己new出一個,這個時候如果沒有在User實體類裏面加上無參構造函數就會報錯。
4.兩個方法都有字符串返回值,這就是返回你需要用數據渲染的視圖的路徑,而Model對象也會隨之字符串一起返回,這樣你就可以在頁面時使用
5.在form方法裏面我遍歷了Model對象的key,裏面會輸出下面的結果,這樣就可以證明我上面的結論
org.springframework.validation.BindingResult.myUser
error
6.get方法的參數爲id並在旁邊加上@RequestParam,意味着這是一個請求參數key爲id,false表示即便是null也行
表單1
將第一個表單起名字爲userForm.jsp,放在WebRoot下面
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<c:set var="ctx" value="${pageContext.request.contextPath}/admin"/>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>測試1</title>
</head>
<body>
<form:form action="${ctx}/user/into" method="post">
<input type="text" name="id"/><br/>
<input type="submit" value="保 存"/>
</form:form>
</body>
</html>
- 在這個表單中,因爲沒有名爲myUser的對象所以不能綁定modelAttribute屬性,如果綁定就會報錯Neither BindingResult nor plain target object for bean name ‘myUser’ available as request attribute
- 也就是你在跳轉到該表單的時候在Controller裏面需要返回一個User對象名字爲myUser才能綁定到form:form標籤的modelAttribute屬性上
表單2
第二個表單我在WEB-INF下面的views文件夾裏面名字同樣叫做userForm.jsp
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<c:set var="ctx" value="${pageContext.request.contextPath}/admin"/>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>測試2</title>
</head>
<body>
<form:form modelAttribute="myUser" action="${ctx}/user/form" method="post">
<form:input path="id"/><br/>
<input type="submit" value="保 存"/>
</form:form>
${myUser.id}----------<br/>
${error1}<br/>
</body>
</html>
1.你可以看到只有後面的表單都有綁定一個myUser,而myUser正好就是後臺User對象的名字,第一次從控制器返回的時候,自動將User對象給綁定到頁面元素了
2.這個時候,如果你將UserController中的get方法改爲下面的樣子(前提是你的User要有無參的構造方法),你會發現id自動幫你set進去了(前提是你的User裏面要有get和set方法,否則會報錯javax.el.PropertyNotFoundException: Property ‘id’ not found on type com.modules.entity.User
)
3.modelAttribute作用:我猜想是因爲java對象User和表單元素映射(綁定),而User的id和path爲id的相對應,所以我們就可以將該對象顯示到頁面上去(比如你想要修改客戶信息,它可以將客戶信息顯示出來當然你要使用spring的標籤)
@ModelAttribute("myUser")
public User get(){
return new User();
}
大致的訪問流程
- 我先訪問http://localhost:8080/test/userForm.jsp然後輸入數據假設是11
- 點擊保存之後你會發送一個請求http://localhost:8080/test/admin/user/into,接下來DispatcherServlet會攔截你的請求,並委託請求給對應的處理器因爲和UserController的映射路徑相匹配所以就給了它
- 接着先執行了get方法接收了表單提交過來的的id參數輸出下面的結果,然後返回一個User,id爲11,放入Model對象裏面,起名爲myUser
Get id11
- 因爲將into方法映射在路徑into上面所以執行into方法,它會自動將model裏面key爲myUser和model對象傳入。在裏面加上error1,再次控制檯上輸出getUser11,返回視圖路徑。而在網頁上的URL就是http://localhost:8080/test/admin/user/into
- 通過顯示數據,可以知道控制器將model(模型數據)和視圖路徑返回給DispatcherServlet(Model對象和視圖名都放在ModelAndView對象中),然後再將其用來尋找並渲染視圖。(值得注意的是在form:input標籤中有11的值)
11----------
getError1
6.在文本框裏面輸入22,點擊保存發送請求http://localhost:8080/test/admin/user/form,同樣和上面過程一樣,將model對象裏面的key全部輸出,你會發現原來是error1現在沒了說明model已經不是同一個了
org.springframework.validation.BindingResult.myUser
error
getUser22
7.頁面上的結果就是,可以看到沒有顯示error1的值,說明這個值不存在
22----------
配置文件
最後是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: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">
<description>Spring MVC Configuration</description>
<context:property-placeholder location="classpath:my.properties" />
<context:component-scan base-package="com" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="${prefix}"/>
<property name="suffix" value="${suffix}"/>
</bean>
</beans>
- 加載屬性配置文件,因爲你控制器的映射路徑就需要裏面的值
- 掃描@Controller,就不用說了,不註冊爲bean,你怎麼知道這個控制器?
- mvc:annotation-driven,這個你要是不加上,@RequestMapping就沒什麼用了
- InternalResourceViewResolver視圖資源解析,上面的配置表示,將在控制器返回的ModelAndView的基礎上,加上目錄前綴/WEB-INF/views/,加後文件名稱後綴.jsp,這樣就能訪問/WEB-INF/下的文件。如果你是直接URL上自己打上/WEB-INF/這樣是不行的,它會報錯說找不到文件。