首先在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/这样是不行的,它会报错说找不到文件。