标签:springmvc
MavenWeb工程,核心jar包:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.0.0.RELEASE</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.0.RELEASE</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.0.RELEASE</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.0.0.RELEASE</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.0.0.RELEASE</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.0.0.RELEASE</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.0.0.RELEASE</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<type>jar</type>
</dependency>
其中javax.servlet提供servlet-api支持。如有tomcat,可以直接关联tomcat的相应jar包。
总体感觉spring的配置文件还是比较精炼的(相比于webx。。),主要有两大块:web.xml和applicationContext.xml(可用dispatcherServlet-servlet.xml替换,后面再说。)
所有的web工程都会用到。对于使用springMVC来说要实现请求的分发处理,需要配置以下基本组件:
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置 DispatcherServlet 的一个初始化参数: 配置 SpringMVC 配置文件的位置和名称 -->
<!--
实际上也可以不通过 contextConfigLocation 来配置 SpringMVC 的配置文件, 而使用默认的.
默认的配置文件为: /WEB-INF/<servlet-name>-servlet.xml
(比如本例中可替换为dispatcherServlet-servlet.xml)
-->
<!--
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
-->
<!--
load-on-startup参数如果非零,则表示在容器初始化的时候就会对该servlet进行初始化,通常用于监听类等服务于spring框架的类。
-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--
servlet映射规则(对所有请求进行映射)
-->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
scan扫描注解组件,用于扫描对应base-package下的所有类的注解。
InternalResourceViewResolver(内部资源映射组件)
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
配置了controller处理后返回的页面对应的资源地址匹配。
4.0.0版的springframework中注解相当普遍和强大了。
在本次学习到的有以下几个:
@Controller
@RequestMapping
@PathVariable
@RequestParam
@RequestHeader
@CookieValue
@ModelAttribute
在作为controller的类上标记该注解。dispatcherServlet可将对应url-pattern转发给这些Controller。如何确定给哪个Controller呢?
见@RequestMapping
该注解用于控制url分发方向,可标注类或者方法,用法为:
@RequestMapping(“/xxx”)
标注方法的时候,需要加上所在类的RequestMapping路径(若没有则不用)。
则符合该url的会找到该方法执行。
springMVC支持REST风格的urlpath类型。
如:@requestMapping(xxx/{id}/yyy)
则方法的参数可以使用@PathVariable("id") Integer id
进行获取。如下为例:
@RequestMapping(value="sayhello/{id}")//, method=RequestMethod.GET, params={"id=1","age!=1"}
public String hello(@PathVariable("id") Integer i){
System.out.println("hello world "+i);
return SUCCESS;
}
这三个注解都是用于修饰方法的入参的。
@RequestParam(value="id", required=false) Integer id
表示入参接受id,但是id不一定有。在默认情况下,不写required属性意味着id必须有,如果没有,则报错。
@RequestHeader(value="Accept-Language") String actLang
道理相同,将请求头中的字段绑定到方法入参中。
@CookieValue() String xxx
同理,将请求中的CookieValue的字段绑定到方法入参中。
在说ModelAttribute注解之前,需要说一下表单的提交,因为ModelAttribute是针对表单-对象映射这种类型的提交项进行优化的步骤。
表单的提交支持级联,即组合关系。
直接看例子:
User.java
public class User {
private String username;
private String password;
private int age;
private Address address;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "User [username=" + username + ", password=" + password
+ ", age=" + age + ", address=" + address + "]";
}
}
Address.java (作为User的一个级联属性)
public class Address {
private String province;
private String city;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
表单对应到实体类已经就绪,下面看表单:
<form action="HelloWorld/testPojo" method="post">
username: <input type="text" name="username" /> <br>
password: <input type="password" name="password"/> <br>
age: <input type="text" name="age" />
<br>
province: <input type="text" name="address.province" />
<br>
city: <input type="text" name="address.city" /> <br>
<input type="submit" value="Submit" />
</form>
对于级联的属性name可以用address.province来表示。
对应的controller应该这么写:
@RequestMapping("/testPojo")
public String testPojo(User user){
System.out.println(user);
return SUCCESS;
}
上述表单直接映射为了User类。
那么@ModelAttribute有什么用呢?它跟表单的提交有什么关系?
先看由其标注的方法:
@ModelAttribute
public void prehand(Map<String, Object> map){
User user = new User();//模拟数据库提取(业务逻辑,可自行调整)
user.setUsername("shanjie");
user.setAge(23);
user.setPassword("123");
map.put("user", user);
}
我们看下图:
当User这个form映射成实体作为入参的时候,这个User实际上是一个新建的对象,这就有个问题:如果对已经填写过的表单进行个别项的修改,而其余各项的值不允许修改,那我在修改表单的时候该怎么办?单纯的新建对象会使得固定字段为空,因为不能填写该项,那么在更新到db中的时候会导致固定项为空。如果先得到固定相的值传给页面,作为hidden域似乎可行,但是不安全性和参数复杂性都会增加。那么怎么办?
@ModelAttribute提供了完美的解决办法,如下图:
标注了@ModelAttribute的方法会先于form的映射方法执行。
即一个表单从前端映射到后台存入数据库的流程是这样的:
因此,在没有@ModelAttribute修饰的方法时,我们使用的目标函数其实就是第三步中的过程。有了ModelAttribute修饰的方法,则第一步也就有了意义。
注:@ModelAttribute方法是如何识别目标对象的呢?
我们知道第一步和第三步都是我们人为定制的,而第二步是由spring为我们做的,它根据什么去从map中取得第三步需要传入的对象呢?
答案就是,它默认将对象类的首字母小写作为key值。本例中,User类对应着user这个key。如果key变了,那么spring也就找不到对应的User 了。
这是springMVC中的重要约定之一。
标签:springmvc
原文地址:http://blog.csdn.net/langduhualangdu/article/details/46377439