您的位置:首页 > 编程语言 > Java开发

Spring MVC配置介绍

2016-06-06 18:56 507 查看

一、Spring MVC 纵览

Spring MVC就是Spring框架对MVC设计模式的实现,通过Spring MVC ,我们可以快速的构建灵活、松耦合的web服务。再具体介绍Spring MVC 之前,我们先看一下它的请求处理过程:



1.1 springMVC 的请求过程

1. 请求会首先发送到DispatchServlet,这是spring的前置Servlet,它会接收请求并转发给spring的MVC controller,也就是业务controller
2. DispatchServlet通过HandlerMapping确定将请求转发给哪个controller,HandlerMapping主要通过请求中的URL确定映射关系的
3. DispatchServlet将请求转发给确定的controller之后,controller负责处理这个请求,一般会通过调用service层进行业务逻辑处理
4. 当controller处理完请求后,它会把业务处理结果封装成model,为了使处理结果的model在页面上更好的展示,controller还会指定展示model对应的view(比如一个JSP页面),当controller确定了model和view之后,会把它们以请求的形式再转发给DispatchServlet
5. DispatchServlet通过查询ViewResolver找到view对应的页面
6. DispatchServlet最终把model交给页面进行渲染
7. 页面对model进行渲染,将结果展示到客户端,整个请求结束


1.2 配置Spring MVC

其实Spring MVC的核心就是DispatchServlet,配置Spring MVC的过程就是配置DispatchServlet的过程。

1.2.1 配置DispatchServlet

Spring的配置有两种方式,一种通过web.xml配置,另一种就是通过Java配置,在这里我们主要讲如何在web.xml中配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener </listener-class>
</listener>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>


主要配置项:

<context-param>
<listener>
:配置Spring的
RootContext
,对应配置文件为
root-context.xml


<servlet>
<servlet-mapping>
:配置Spring的
WebContext
,对应配置文件默认为为
WEB-INF/{servlet-name}-servlet.xml


可能有些人还不太清楚为什么要这样配置,在具体讲解之前,先介绍Spring MVC中的两个context(上下文)。

理解两个context

我们知道,Spring有一个核心容器也就是ApplicationContext,所有的Spring组件都由这个ApplicationContext进行管理。但是在Web项目中,Spring会维护两个context:



1. WebContext

第一个Context就是由DispatchServlet创建的WebContext,负责装载web组件相关的bean,比如controllers、view resolvers、handler mapping等,对应的配置文件是
WEB-INF/{servlet-name}-servlet.xml
,在上面例子中我们配置的Servlet的名字是spring,所以它默认加载spring-servlet.xml配置文件作为上下文。

但是我们也可以自己指定一个WebContext配置文件位置,比如指定/WEB-INF/spring/appServlet/servlet-context.xml路径下的配置文件:

<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/appServlet/servlet-context.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>


2. RootContext

RootContext是由ContextListener加载的,它主要装载除web组件之外的应用程序组件,比如jdbc、mybatis等组件。
<context-param>
标签指定了RootContext配置文件的位置,并由
<listener>
标签指定的Listener类进行装载。

1.2.2 启用Spring MVC

上面的配置其实已经基本ok了,但是一个完整的Spring MVC应用还需要controller、service、view等web组件,所以我们还要在配置中启用注解及自动包扫描等功能,方便web组件的自动发现,这些应该在上面介绍的WebContext对应的配置文件中进行配置,也就是在spring-servlet.xml中配置:

<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/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> 
<mvc:annotation-driven/>
<context:component-scan base-package="com.springmvc.demo" />

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>

</beans>


主要配置项:

<mvc:annotation-driven/>
标签作用是开启注解

<context:component-scan/>
标签目的是启用自动包扫描,这样spring框架就会自动扫描被注解的类,纳入到WebContext中。

通过上面的配置,Spring MVC的主要配置就已经完成了,我们现在就可以编写Spring MVC的组件了,我们先从controller开始。

二、写一个controller

 2.1 写一个简单的controller

@Controller
public class HomeController {
@RequestMapping(value="/", method= RequestMethod.GET)
public String home() {
return "home";
}
}


声明controller组件:写一个controller很简单,@controller注解声明当前类是一个controller类,上面配置中我们开启了ComponentScan,被@controller注解的类会被自动装载到spring application context中。当然我们使用@component组件效果也是一样的,只不过@controller更能体现controller角色。

定义请求路径: HomeController类里面只有一个home()方法,并且还携带一个@RequestMapping注解,注解中的value属性定义了这个方法的访问路径是“/”,method属性定义了这个方法只处理get请求。

定义渲染view:我们可以看到,home()方法很简单,仅返回了一个“home”字符串。默认情况下,方法返回的字符串默认会被解析成view的名称,DispatcherServlet 会让ViewResolver解析这个view名称对应的真是view页面。我们上面已经配置了一个InternalResourceViewResolver,返回的home会被解析/WEB-INF/views/home.jsp。

写完controller之后我们可以通过测试类测试一下,写一个测试controller:

public class HomeControllerTest {
@Test
public void testHomePage() throws Exception {
HomeController controller = new HomeController();
Assert.assertEquals("home", controller.home());

}
@Test
public void testHomePageMVC() throws Exception {
HomeController controller = new HomeController();
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
mockMvc.perform(MockMvcRequestBuilders.get("/")).andExpect(MockMvcResultMatchers.view().name("home"));
}

}


2.2 定义一个类层次的路径映射

其实
@RequestMapping
注解既可以注解方法又可以注解类,当注解类时,访问类中所有的方法就必须加上类路径。另外
@RequestMapping
中的值可以是一个路径数组,当传入一个数组时,我们可以通过数组中的任何一个路径访问到这个类.

@Controller
@RequestMapping({"/", "/homepage"})
public class HomeController {
...
}


2.3 返回Model数据给view层

我们知道通常情况下,controller处理完业务后会返回结果数据给view层。为此,SpringMVC提供了Model类来封装结果数据,封装的过程是自动的,我们只需要在方法中加入Model参数即可:

public String getUsers(Model model) {
model.addAttribute( userService.findSpittles( Long.MAX_VALUE, 20));
return "userView";
}


Model其实就是一个Map,view层会自动解析model中的数据,然后渲染结果给client端。上面的
model.addAttribute
方法没有指定key,key值会被默认设置为对象的类型名,比如上例子中对象类型是
List<User>
,则key值默认为:
userList
。方法最后返回的String值
userView
会直接作为view的名称。

当然我们也可以明确指定返回数据模型的key值:

public String getUsers(Model model) {
model.addAttribute("userList", userService.findUsers( Long.MAX_VALUE, 20));
return "userView";
}


如果我们不想使用Spring的Model类,我们也可以用java.util.Map类替换Model,这两个效果是完全一样的:

public String getUsers(Map map) {
map.addAttribute("userList", userService.findUsers( Long.MAX_VALUE, 20));
return "userView";
}


除了上面两种方式之外,我们还可以这么写:

@RequestMapping(method=RequestMethod.GET)
public List<User> getUsers() {
return userService.findUsers(Long.MAX_VALUE, 20));
}


这种方式比较特殊,我们既没有设置返回的Model,又没有指定渲染Model的view,仅仅返回处理的结果对象。遇到这种情况时,Spring MVC会把返回的对象会自动放入Model中,其key就是对象的类型名,即
userList
。而对应的view名称则默认与请求路径名一致,例如我们的请求路径是这样:

@Controller
@RequestMapping("/users")
public class UserController {
... ...
}


那么对应渲染结果的view就是
users


三、 处理请求数据

SpringMVC提供了多种数据传输方式:

QueryParameter:查询参数

Form Parameters:表单参数

Path variables:路径变量

下面我们逐一说明。

3.1 获取查询参数

首先什么是查询参数呢?比如我们有一个这样的请求
http://localhost:8080/user/queryUsers?pageNo=1&count=5
,在这个请求中,参数值都是通过URL中?后面的参数传递过来的,这种方式就是查询参数传值。如果要解析查询参数中的值,我们需要用到@RequestParam注解,它会将请求参数映射到方法参数:

@RequestMapping(value = "/getUsersByPage", method = RequestMethod.GET)
public String getUsersByPage(@RequestParam(value = "pageNo",defaultValue = "1") long pageNo,@RequestParam(value = "count",defaultValue = "5") long count ,Model model) {
model.addAttribute(userService.getAllUsers());
return "userListPageView";
}


需要注意的是,我们在配置请求参数时可以指定参数的默认值,当client端传过来的参数值不存在或者为空时,就会采用这个默认值,还有一点,因为查询参数都是String类型,所以这里的默认值也都是String类型。

除了通过查询参数传递参数值之外,还有一种流行的方式就是通过请求路径传递参数值,特别是在讨论构建基于资源的服务时会经常用到这种方式。(注:基于资源的服务可以简单看做所有请求都是针对资源,所有的返回结果也是资源)

3.2 通过请求路经获取参数

比如我们有一个根据用户id查询用户信息的需求,通过上面介绍的方式我们可以这么做:

@RequestMapping(value = "/queryUser", method = RequestMethod.GET)
public String queryUser(@RequestParam(value = "employeeId") long employeeId,Model model){
model.addAttribute(manager.queryEmployeeVO(employeeId));
return "employee";
}


那么我们客户的的请求路径应该是这样:
/employee/queryEmployee ?employeeId=12345
,尽管也可以满足需求,但这样不太符合基于资源的理念。理想的情况是,资源应该是由请求路径决定的,而不是由请求参数决定。或者说,请求参数不应该被用来描述一个资源。
/employee/12345
这种请求方式显然比
/employee/queryEmployee ?employeeId=12345
更能合适,前者定义了要查询的资源,而后者更强调了通过参数进行操作。

为了达到构建基于资源的controller这个目标,Spring MVC允许请求路径中包含一个占位符,占位符名称需要用一对{}括起来。在客户的请求资源时,请求路径的其它部分还是用来匹配资源路径,而占位符部分则直接用来传输参数值。下面就是通过占位符的方式实现路径中传递参数值:

@RequestMapping(value ="/{userId}", method = RequestMethod.GET)
public String queryUser(@PathVariable(value = "userId") long userId, Model model){
model.addAttribute(userService.queryUser(employeeId));
return "userView";
}


上面例子可以看到,方法参数中有一个
@PathVariable
的注解,这个注解的意思就是不管请求路径中占位符处的值是什么,它都会被传递到
@PathVariable
注解的变量中。比如按照上面的配置,如果我们的请求是
/employee/12345
,则
123456
便会传入变成
userId
的值。需要注意的是,如果方法参数值和占位符名称一样,我们也可以省略
@PathVariable
中的属性值:

@RequestMapping(value ="/{userId}", method = RequestMethod.GET)
public String queryUser(@PathVariable long userId, Model model){
model.addAttribute(userService.queryUser(employeeId));
return "userView";
}


在请求的数据量很小的时候使用查询参数和路径参数还是可行的,但是有时候我们请求的数据量会很大,再用上面两种方式就显得有点不太合适,这时就需要考虑用第三种方式:表单参数。

四、处理表单数据

一个Web应用不单单只是给用户展示数据,很多时候它还需要与用户交互获取用户数据,表单就是获取用户数据最常见的方式。

比如我们有个注册表单:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Spittr</title>
<link rel="stylesheet" type="text/css"  >
</head>
<body>
<h1>Register</h1>
<form method="POST">
First Name: <input type="text" name="name" /><br/>
Last Name: <input type="text" name="accountNo" /><br/>
Password: <input type="password" name="password" /><br/>
<input type="submit" value="Register" />
</form>
</body>
</html>


4.1 写一个接收表单数据的controller

表单都是以post方式提交的,所以我们的controller接受的应该是个post请求:

@Controller
@RequestMapping("/user")
public class RegisterController {
@Autowired
private RegisterService registerService;
@RequestMapping(value="/register", method=RequestMethod.POST)
public String processRegistration(User user) {
registerService.register(user);
return "redirect:/user/" + user.getName();
}
}


在上面例子中,出了接收的请求是post之外,注册方法还有一个含有User对象的参数,这个User对象中含有name、password、accountNo属性,SpringMVC会根据名称从请求中解析相同名称参数并赋值到对象属性中。

当注册方法保存用户信息之后,会返回一个字符串
redirect:/user/
,这个字符串与前面讲到的都不同,它返回的并不是一个view的名称,而是一个redirect重定向请求。因为返回的字符串中含有一个
redirect:
重定向关键字,当
InternalResourceViewResolver
类遇到这个关键字时,它将会拦截这个字符串并把它解析成一个重定向请求而不是view名称。

InternalResourceViewResolver
除了能够识别redirect:关键字之外,它还能识别
forward:
关键字,并把包含
forward:
关键字的字符串解析成
forward
请求。

4.2 验证表单

在Spring3.0以后,SpringMVC便支持Java Validation API了,Java Validation API提供了一些注解来约束对象属性值,这些注解有:

注解解释
@AssertFalseThe annotated element must be a Boolean type and be false.
@AssertTrueThe annotated element must be a Boolean type and be true.
@DecimalMaxThe annotated element must be a number whose value is less than or equal toa given BigDecimalString value.
@DecimalMinThe annotated element must be a number whose value is greater than orequal to a given BigDecimalString value.
@DigitsThe annotated element must be a number whose value has a specified number of digits.
@FutureThe value of the annotated element must be a date in the future.
@MaxThe annotated element must be a number whose value is less than or equal to a given value.
@MinThe annotated element must be a number whose value is greater than or equal to a given value.
@NotNullThe value of the annotated element must not be null.
@NullThe value of the annotated element must be null.
@PastThe value of the annotated element must be a date in the past.
@PatternThe value of the annotated element must match a given regular expression.
@SizeThe value of the annotated element must be either a String, a collection, or an array whose length fits within the given range.
我们可以利用这些注解给User对象添加一些验证,比如非空和字符串长度验证:

public class User {
@NotNull
@Size(min=3,max=20)
private String name;
@NotNull
@Size(min=6,max=20)
private String password;
@NotNull
@Size(min=3,max=20)
private String accountNo;

}


我们还需要通过
@Valid
标签在方法中对User启用参数验证:

@RequestMapping(value="/register", method=RequestMethod.POST)
public String processRegistration(@Valid User user, Errors errors) {
if(errors.hasErrors()){
return "register";
}
registerService.register(user);
return "redirect:/user/" + user.getName();
}


在上面例子中,我们在方法中的User参数前面添加了@valid注解,这个注解会告诉Spring框架需要启用对这个对象的验证。如果发现任何验证错误,错误信息都将会被封装到Errors对象中,我们可以通过
errors.hasErrors()
方法判断是否验证通过。

Spring MVC其它相关文章:

Spring MVC 页面渲染( render view )

Spring MVC 中的异常处理 (handling exceptions)

Spring MVC 上传文件(upload files)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: