SSM框架实战系列之九_SpringMVC框架
从前面的文章中我们可以看到,Spring框架并不复杂,我们暂时只用到了Spring框架自动创建组件和自动注入依赖的特性,更多的特性在后面用到时再提及。
事实上,Spring框架作为一个万用型框架,它可以粘合各种独立框架。可以说其它框架都可能过时并被替代,但Spring框架作为JavaEE应用程序开发的事实上的标准框架,应该能无悬念地持续生存下去。
值得一提的是,Spring框架还出了一个Spring Boot版本,进一步简化配置,让开发人员易于入手是它的服务理念。
本节将介绍SpringMVC框架。
一、MVC编程模式
SpringMVC框架是Spring框架的一部分,以前用得较多的是Struts框架,现在Struts框架的地位已经逐渐地被SpringMVC框架所取代。
SpringMVC框架主要作用在控制器层。
MVC编程模式:
在MVC编程模式中,应用程序根据其作用分为三块:Controller(控制器)、Model(模型)、View(视图)。
用户请求===>控制器,控制器===>模型(完成实际业务、取得数据),控制器===>视图(使用数据填充视图),控制器===>用户(返回响应结果)。
业务逻辑层、数据处理层、实体类都属于模型。
视图部分有很多技术,除了传统的JSP之外,还有Velocity、Freemarker等。大部分技术都是通过编写模板,然后接收数据并填充模板。
二、Web项目中配置SpringMVC框架
前面说过,SpringMVC框架主要作用在控制器层,因此SpringMVC框架必须拦截所有的用户请求,这一点是在web.xml中配置的:
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
SpringMVC框架的核心是一个Servlet,名叫DispatcherServlet(Dispatcher:转发)。
通过配置url-pattern,将拦截所有后缀为.do的请求。当然也可以写成/*,拦截任何请求。
三、SpringMVC配置文件
在resources/config文件夹下,添加一个名为spring-mvc.xml的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:p="http://www.springframework.org/schema/p"
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.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
<!-- 配置JSON -->
<bean id="mappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json; charset=UTF-8</value>
</list>
</property>
</bean>
<!-- 配置视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
在此配置文件中,配置了视图解析器,当控制器方法返回一个字符串时,SpringMVC便会调用InternalResourceViewResolver(内部资源视图解析器)为此字符串加上前缀和后缀,例如控制器方法返回“/usr/add”时,视图资源对应为:“/WEB-INF/jsp/user/add.jsp”。
另外还定义了JSON格式转换器。
四、控制器方法
SpringMVC控制器类的作用类似于Struts2框架中的Action类。
SpringMVC框架的控制器类可以是一个普通的Java类,一般需要在控制器类前加上@Controller注解。
SpringMVC的控制器与Struts2的Action类最大的区别是:Struts2的Action类是以类为一个基本单元,数据交互通常定义为类的属性;SpringMVC的控制器是以控制器方法为一个基本单元,数据交互在方法参数上传递。
控制器方法示例:
@Controller
public class UserController {
@RequestMapping("/login.do")
public String login(String username, String password) {
if (!"admin".equals(username) || !"admin".equals(password)) {
return "failure"; // 视图解析器会加上前缀和后缀;
}
return "success";
}
}
控制器方法前有一个@RequestMapping注解,该注解表示请求映射,即与此控制器方法相对应的访问路径,当用户访问login.do时进入此方法。
1、从页面向控制器传值
从页面向控制器值,例如登录时,页面需要向登录方法传递用户名和密码。这时,一般是通过定义控制器方法的入参来实现。
(1) 方式一:直接定义入参
@RequestMapping("/login.do")
public String login(String username, String password) {
if (!"admin".equals(username) || !"admin".equals(password)) {
return "failure";
}
return "success";
}
这里直接定义了两个入参:username和password,那么页面上就要有两个name为username和password的表单元素,表单元素的值将赋给username和password。
(2) 方式二:定义实体类型的入参
@RequestMapping("/login.do")
public String login(User user) { // 需要先定义User实体类
System.out.println("username:" + user.getUsername());
System.out.println("password:" + user.getPassword());
return "success";
}
如果定义了一个User实体类,则入参可以是实体类型。页面代码不变,仍有两个名为username和password的表单元素。
(3) 方式三:使用request接收
@RequestMapping("/login.do")
public String login(HttpServletRequest request) {
String username = request.getParameter("username");
String password = request.getParameter("password");
return "success";
}
可以将入参定义为HttpServletRequest类型,此时request变量的用法与JSP的内置对象request一致。
控制器方法的入参非常灵活,你还可以在控制器方法中使用如下参数:
× HttpServletRequest:请求对象,相当于JSP中的request对象
× HttpServletResponse:响应对象,相当于JSP中的response对象
× HttpSession:会话对象,相当于JSP中的session对象
2、从控制器向页面传值
可以在控制器方法的入参中添加Map类型的参数或Model类型的参数,以达到向页面传值的目的:
@RequestMapping("/hello.do")
public String hello(Map<String,Object> map) {
map.put("hello", "world"); // 页面使用${hello}取出
return "hello";
}
@RequestMapping("/hello.do")
public String hello(Model model) {
model.addAttribute(“hello", "world"); // 页面使用${hello}取出
return "hello";
}
Map(映射)是传统的Java集合,代表键值对,使用put方法存值。Model是SpringMVC框架的东西,使用其addAttribute(添加属性)方法添加一个属性。
用起来差不多。
在JSP页面上可以使用EL表达式取得值。