一、介绍
通过学习了 Spring MVC 框架原理,我们将更好的掌握 Spring MVC。废话不多说,我们现在正式开始 Spring MVC 快速入门程序——以查询商品信息为例。
二、Spring MVC 入门程序
用到的工具有 Eclipse,Google 浏览器…,按照 Spring MVC 框架原理步骤,一步一步的进行编写我们的项目。
1. 首先我们新建一个 WEB 项目
开始前第一步不能少的,那就是新建项目,工程结构如下图:
2. 导入 jar 包
官网下载点击下载,本项目中使用3.2的 jar, Spring MVC jar 包有:
3. 配置前端控制器
打开 web.xml 文件,在文件中加入 DispatcherServlet ,配置 contextConfigLocation 的值为自己定义的springmvc.xml的路径, 如果不配置,默认加载的是 /WEB-INF/[DispatcherServlet 的Servlet 名字]-servlet.xml 文件,这里如果不配置的话默认加载是 WEB-INF目录下的 SpringMVC-servlet.xml 文件。
<!-- 配置SpringMVC -->
<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:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
其中 servlet-mapping 的 url-pattern 有三种配置方式,第一种是:*.action 或者 .do ,对访问以 .action 或 .do 结尾的由 DispatcherServlet 进行解析,这种方法的好处是对静态资源不做拦截,是最简单的方式;第二种是:/ ,拦截所有资源,这种方式能够实现 RESTful 风格的 URL,但是会对静态资源也进行拦截,需要特殊的处理;第三种是: / * ,会拦截所有但这种方式是错误的。
这里就采用最简单的方式进行配置。并且 Spring MVC 的配置文件为根目录下的 springmvc.xml。
4. 配置 springmvc.xml 文件
这里就是上述的代码,上面说的很详细了,这里就不多说。
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
5. 配置处理器适配器
在配置处理映射器前,我们先配置处理器适配器,这样能更容易去理解。在 Spring MVC 中,springmvc.xml 配置文件中可配置多个非注解处理器适配器,每个非注解处理器适配器互不影响,但是如果使用注解处理器适配器就需要和注解处理器映射器配对使用。常用的非注解处理器适配器有 SimpleControllerHandlerAdapter,HttpRequestHandlerAdapter 等等,注解处理器适配器有 RequestMappingHandlerAdapter 等等。配置方式如下:
- SimpleControllerHandlerAdapter 配置方式:
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
使用此处理器适配器需要重写 handleRequest 方法并返回 ModelAndView 对象。
- HttpRequestHandlerAdapter 配置方式:
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
使用此处理器适配器可通过修改 response,设置响应的数据格式,并返回。
- RequestMappingHandlerAdapter 配置方式:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />
注意:此注解处理器适配器需要和注解处理器映射器(RequestMappingHandlerMapping)配对使用,更不能单独使用。
6. 编写处理器(Controller)
我们将针对上述三个处理器适配器编写对应的三个处理器,为什么呢?如果你看了Spring MVC 框架原理就应该知道, 处理器的编写要遵循处理器适配的规则,不同的处理器适配器有不同的规则。因为每个处理器适配器都有一个 supports() 方法对编写的处理器进行规则检查,检查通过才可以。 如果不知道 Spring MVC 框架原理,请看 SpringMVC学习笔记(一)——SpringMVC框架原理
- 针对 SimpleControllerHandlerAdapter 处理器适配器编写处理器 ItemsController1:
注意:本 Controller 实现接口 Controller,并返回 ModelAndView 对象。
package com.ssm.controller;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import com.ssm.po.Items;
/**
* @Description 实现 Controller 接口的 处理器
* @author 欧阳
* @since 2018年11月13日
* @version V1.0
*/
public class ItemsController1 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//1.调用service 查找数据库的商品查询
List<Items> itemsList = new ArrayList<Items>();
Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone6苹果手机!");
itemsList.add(items_1);
itemsList.add(items_2);
//2.返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
//2.1 指定数据
modelAndView.addObject("itemsList",
itemsList);//相当于request.setAttribut()
//2.2 指定视图
modelAndView.setViewName("itemsList");
//2.3 返回
return modelAndView;
}
}
2.针对 HttpRequestHandlerAdapter 处理器适配器编写处理器 ItemsController2:
注意:本 Controller 实现的接口是 HttpRequestHandler ,并且返回的是 void 。
package com.ssm.controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.HttpRequestHandler;
import com.ssm.po.Items;
/**
* @Description 实现 Controller 接口的 处理器
* @author 欧阳
* @since 2018年11月13日
* @version V1.0
*/
public class ItemsController2 implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.调用service 查找数据库的商品查询
List<Items> itemsList = new ArrayList<Items>();
Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone6苹果手机!");
itemsList.add(items_1);
itemsList.add(items_2);
//2.指定数据
request.setAttribute("itemsList", itemsList);
//3.转发
request.getRequestDispatcher("/WEB-INF/jsp/itemsList.jsp")
.forward(request, response);
/*
* 从上边可以看出此适配器器的handleRequest方法没有返回ModelAndView,
* 可通过response修改定义响应内容,比如返回json数据:
*/
// response.setCharacterEncoding("utf-8");
// response.setContentType("application/json;charset=utf-8");
// response.getWriter().write("json串");
}
}
- 针对 RequestMappingHandlerAdapter 处理器适配器编写处理器 ItemsController3:
注意:这里使用注解 @Controller 标识为一个 Controller,并没有继承任何类,返回的是一个 ModelAndView 对象,后续还可以返回一个 String 类型的字符串或者 void 。
package com.ssm.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.ssm.po.Items;
/**
* @Description 注解开发 Handler
* @author 欧阳
* @since 2018年11月13日
* @version V1.0
*/
//使用 @Controller 定义标识为一个 Controller
@Controller
public class ItemsController3 {
//商品查询
//一般建议将 url 和 方法名写成一样
//@RequestMapping 实现对queryItems方法和url进行映射,一个方法对应一个url
@RequestMapping("/queryItems")
public ModelAndView queryItems() {
//1.调用service 查找数据库的商品查询
List<Items> itemsList = new ArrayList<Items>();
Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone6苹果手机!");
itemsList.add(items_1);
itemsList.add(items_2);
//2.返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
//2.1 指定数据
modelAndView.addObject("itemsList",
itemsList);//相当于request.setAttribut()
//2.2 指定视图
//如果在视图解析器中配置了前缀和后缀,修改为
//modelAndView.setViewName("/WEB-INF/jsp/itemsList.jsp");
modelAndView.setViewName("itemsList");
//2.3 返回
return modelAndView;
}
}
7. 配置处理器
在 springmvc.xml 文件中配置非注解处理器适配器编写的处理器(Controller)。因为 ItemsController3 是使用注解编写的,配置的url 使用 @RequestMapping 注解可指定,所以不需要配置 id 属性,itemsController1 也不需要配置 id 属性,只是因为后面的处理器映射器也可以配置为它,就需要 id 了。
<bean id="itemsController1" name="/queryItems0.action" class="com.ssm.controller.ItemsController1" />
<bean id="itemsController2" class="com.ssm.controller.ItemsController2" />
<bean class="com.ssm.controller.ItemsController3" />
对于使用注解开发,可以使用 context:component-scan 标签进行配置某个包下的所有 Controller ,实际开发中也是使用此方法。配置方式:
<context:component-scan base-package="com.ssm.controller"></context:component-scan>
8. 配置处理器映射器
在 Spring MVC 中,springmvc.xml 配置文件中可配置多个非注解处理器映射器,每个非注解处理器映射器互不影响,但是如果使用注解处理器映射器就需要配对使用。常用的非注解处理器映射器有 BeanNameUrlHandlerMapping , SimpleUrlHandlerMapping 等等,注解处理器映射器有 RequestMappingHandlerMapping 等等。配置方式如下:
- BeanNameUrlHandlerMapping 配置方式:
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
- SimpleUrlHandlerMapping 配置方式:
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!-- <prop>中配置 handler 对应bean的ID -->
<prop key="/queryItems1.action">itemsController1</prop>
<prop key="/queryItems2.action">itemsController1</prop>
<prop key="/queryItems3.action">itemsController2</prop>
</props>
</property>
</bean>
- RequestMappingHandlerMapping 配置方式:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
注意:此注解处理器映射器需要和注解处理器适配器(RequestMappingHandlerAdapter)配对使用,更不能单独使用。
这里如果使用注解开发,可以不用配置 RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter ,而使用 mvc:annotation-driven,其标签还加入了很多参数绑定方法。实际开发中,一般是使用此配置。
<mvc:annotation-driven></mvc:annotation-driven>
9. 配置视图解析器
配置如下:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置JSP模板页面需要使用JSTL标签库 -->
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
InternalResourceViewResolver : 支持 JSP 视图的解析;
prefix 和 suffix 的配置意思分别表示前缀和后缀,最终视图地址为:
前缀+逻辑视图名+后缀,逻辑视图名需要在 Controller 中返回的 ModelAndView 中指定,比如这里的逻辑视图名为 itemsList ,则最终返回的 jsp 视图地址是 WEB-INF/jsp/itemsList.jsp。
这里就对 springmvc.xml 文件的编写配置已经完了,完整的 springmvc.xml 配置信息是:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
<!-- 配置 非注解的handler -->
<bean id="itemsController1" name="/queryItems0.action" class="com.ssm.controller.ItemsController1" />
<bean id="itemsController2" class="com.ssm.controller.ItemsController2" />
<!-- 配置注解的handler -->
<!-- 对于注解的handler可单个配置
也可使用组件扫描批量配置 ,实际开发中一般用组件扫描
-->
<!-- 单个配置 -->
<!-- <bean class="com.ssm.controller.ItemsController3" /> -->
<!-- 组件扫描配置 -->
<context:component-scan base-package="com.ssm.controller"></context:component-scan>
<!-- 处理器映射器可同时存在多个处理器映射器,系统也默认加载一些默认的处理器映射器 -->
<!-- 非注解处理器映射器 -->
<!-- 第一个处理器映射器 -->
<!-- 根据bean的name进行查找Handler 将action的url配置在bean的name中 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<!-- 第二个处理器映射器 -->
<!-- 简单url映射 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<!-- <prop>中配置 handler对应bean的ID -->
<props>
<prop key="/queryItems1.action">itemsController1</prop>
<prop key="/queryItems2.action">itemsController1</prop>
<prop key="/queryItems3.action">itemsController2</prop>
</props>
</property>
</bean>
<!-- 处理器适配器可同时存在多个处理器适配器,系统也默认加载一些默认的处理器适配器 -->
<!-- 非注解处理器适配器 -->
<!-- 第一个处理器适配器 -->
<!-- 所有处理器适配器都实现了 HandlerAdapter接口 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!-- 第二个处理器适配器 -->
<!-- 使用此处理器适配器可通过修改response,设置响应的数据格式,并返回 -->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
<!-- 注解处理器映射器 和 注解处理器适配器 必须配对使用,不能一个非注解的一个注解的-->
<!-- 注解处理器映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
<!-- 注解处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />
<!--
使用 mvc:annotation-driven 可替代上边注解处理器映射器和注解处理器适配器
同时,mvc:annotation-driven 默认还加载了很多参数绑定方法,比如json转换解析器就默认加载了
即,如果使用了 mvc:annotation-driven 就不用配置上面的注解处理器映射器和注解处理器适配器了
建议使用,使用开发也用 mvc:annotation-driven 。 这暂时使用简单的
-->
<!-- <mvc:annotation-driven></mvc:annotation-driven> -->
<!-- 视图解析器
解析jsp解析,默认使用jstl标签,需要使用jstl包
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置JSP模板页面需要使用JSTL标签库 -->
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
10. 编写 JSP
jsp 文件名及路径为 /springmvc01/WebContent/WEB-INF/jsp/itemsList.jsp 。关键代码:
<table width="100%" border="1" cellpadding="1" cellspacing="1">
<tr>
<td>商品名称</td>
<td>商品价格</td>
<td>生产日期</td>
<td>商品描述</td>
</tr>
<c:forEach items="${itemsList }" var="item">
<tr>
<td>${item.name }</td>
<td>${item.price }</td>
<td><fmt:formatDate value="${item.createtime}"
pattern="yyyy-MM-dd HH:mm:ss" /></td>
<td>${item.detail }</td>
</tr>
</c:forEach>
</table>
11. 测试
给每个 Controller 中的方法打上断点,部署并启动 Tomcat 。访问路径:
http://localhost:8080/springmvc/queryItems0.action
http://localhost:8080/springmvc/queryItems1.action
http://localhost:8080/springmvc/queryItems2.action
http://localhost:8080/springmvc/queryItems3.action
http://localhost:8080/springmvc/queryItems.action
都可正常进入断点并页面显示数据如上图所示,说明测试成功。