一、SpringMvc入门

Springmvc是什么?

Spring web mvc和Struts2都属于表现层的框架,它是Spring框架的一部分,我们可以从Spring的整体结构中看得出来:
在这里插入图片描述

SpringMVC处理流程图

在这里插入图片描述
由上图可知核心部分主要有4个,分别是前端控制器、处理器映射器、处理器设配器、以及视图解析器。

Spring MVC中一共有9大组件,全部都交由DispatcherServlet去初始化,也就是上图中的前端控制器。

这里我只介绍其中的3大组件,在介绍之前,先明确Handler的概念。

Handler

也就是处理器。它直接应对着MVC中的C也就是Controller层,它的具体表现形式有很多,可以是类,也可以是方法。在Controller层中@RequestMapping标注的所有方法都可以看成是一个Handler,只要可以实际处理请求就可以是Handler。

HandlerMapping

是用来查找Handler的。在SpringMVC中会有很多请求,每个请求都需要一个Handler处理,具体接收到一个请求之后使用哪个Handler进行处理呢?这就是HandlerMapping需要做的事。通过request可以拿到请求的url, 通过url和前端控制器的路径映射规则去匹配查找对应的符合要求的Handler

接口源码如下:

public interface HandlerMapping {

	//返回处理器执行链
	HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

}

HandlerAdapter

从名字上看,它就是一个适配器。因为SpringMVC中的Handler可以是任意的形式,只要能处理请求就ok,但是Servlet需要的处理方法的结构却是固定的,都是以request和response为参数的方法。如何让固定的Servlet处理方法调用灵活的Handler来进行处理呢?这就是HandlerAdapter要做的事情。任意形式的Handler通过使用适配器,可以“转换”成固定形式,然后交给Servlet来处理。每种Handler都要有对应的HandlerAdapter才能处理请求。

接口源码如下

public interface HandlerAdapter {

    /**
     * 判断是否支持传入的handler
     */
    boolean supports(Object handler);

    /**
     * 使用给定的handler处理请求,返回ModelAndView 
     */
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

    /**
     * 返回上次修改时间,可以返回-1表示不支持
     */
    long getLastModified(HttpServletRequest request, Object handler);

}

ViewResolver

ViewResolver用来将String类型的视图名和Locale解析为View类型的视图。View是用来渲染页面的,也就是将程序返回的参数填入模板里,生成html(也可能是其它类型)文件。这里就有两个关键问题:使用哪个模板?用什么技术(规则)填入参数?这其实是ViewResolver主要要做的工作,ViewResolver需要找到渲染所用的模板和所用的技术(也就是视图的类型)进行渲染,具体的渲染过程则交由不同的视图自己完成。

接口源码如下:

public interface ViewResolver {

	View resolveViewName(String viewName, Locale locale) throws Exception;
}

介绍完理论,下面开始搞一个Spring MVC的demo玩玩。

环境搭建

1.新建工程,添加jar包

导入相关jar包,我这里给出下载链接 ,提取码:qpa7
在这里插入图片描述
将上图框中的文件夹内的jar导入你的工程,一共15个jar包
在这里插入图片描述
你会发现其实大部分包在前面介绍Spring的时候都有用到,很显然Spring MVC也是离不开Spring的,可以看到spring-webmvc-4.1.3.RELEASE.jar 这个jar包就是和MVC相关的。

2.在web.xml中配置前端控制器

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>springmvc01</display-name>
	
	<!-- Spring MVC前端控制器,它本质就是一个servlet -->
	<servlet>
		<servlet-name>springMvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		
		<!--如果没有置顶springMvc核心配置文件,那么默认会去找/WEB-INF/<servlet-name>-servlet.xml 文件 -->
		<!--指定springMvc的配置文件位置为src目录下 -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:SpringMvc.xml</param-value>
		</init-param>
		
		<!-- tomcat 启动时加载这个servlet, 启动顺序为1 -->
		<load-on-startup>1</load-on-startup>
		
	</servlet>
	
	<servlet-mapping>
		<servlet-name>springMvc</servlet-name>
		<url-pattern>*.action</url-pattern>
	</servlet-mapping>


	
</web-app>

3.添加Spring MVC配置文件

在配置文件中开启注解扫描,然后将配置文件命名为SpringMvc.xml,保持和web.xml中指定名称一样即可,将其放置src目录下。

<?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:dubbo="http://code.alibabatech.com/schema/dubbo" 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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<!-- 开启注解的扫描,支持注解方式注册,这里直接设置扫描范围为整个根包下 -->
	<context:component-scan base-package="blog.csdn.net.mchenys" />

</beans>

4.创建实体类

public class Items {
	
    private Integer id;
    private String name;
    private Float price;
    private String pic;
    private Date createtime;
    private String detail;

	//getter setter...
}

5.创建Handler处理类

换个说法就是控制器类,即MVC中的C,相当于Struts2的角色。

//注解方式注入
@Controller
public class ItemsController {

	// 指定url到请求方法的映射
	// 例如http://192.168.30.217:8080/springmvc01/list.action ,访问的就是itemsList这个方法,
	// 注意.action不能省略,这里保持和web.xml中的url-pattern中配置的一样即可.
	@RequestMapping("/list")
	public ModelAndView itemsList() throws Exception {

		List<Items> itemList = new ArrayList<>();

		// 商品列表
		Items items_1 = new Items();
		items_1.setName("联想笔记本_3");
		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苹果手机!");

		itemList.add(items_1);
		itemList.add(items_2);
		
		//创建modelandView对象
		//model模型:存放返回给页面的数据
		//view视图:指定返回的页面的位置
		ModelAndView modelAndView = new ModelAndView();
		
		// 添加model
		modelAndView.addObject("itemList", itemList);

		// 添加视图路径
		modelAndView.setViewName("/jsp/itemList.jsp");//默认需要书写完整的路径(首个/代表WebContent目录)
		
		return modelAndView;

	}
}

@Controller注解声明在类上,表示控制器,这样Spring就会自动创建并注入到内存,无需在配置文件中进行注册。

@RequestMapping注解声明在方法上,表示所有匹配某个路径的请求都交由该注解声明的某个方法去处理,此时该方法就被称为Handler。注解的属性即括号中的“/list”就是用来标识请求的处理方法的。

过程是这样的:

例如请求http://192.168.30.217:8080/springmvc01/list.action, 由于list.action符合前端控制器的*.action的url-pattern,请求就会被前端控制器接收,然后交给HandlerMapping去处理,由它去根据url中的路径“/list”去查找对应的Handler,也就是标有@RequestMapping的处理方法,然后前端控制器再去调用HandlerAdapter去处理该Handler,说明了就是去执行标有@RequestMapping的处理方法。

当处理方法中的业务相关代码执行完后,需要返回一个ModelAndView 的对象,该对象封装了数据和视图路径。

最后通过视图解析器就可以将ModelAndView 对象进行解析成View对象进行渲染。

在上面代码注释中有说明添加视图路径默认是需要填写完整的路径,后面会介绍简便的方式,直接填写页面的文件名即可。

测试

在WebContent下创建 js 目录并新建 itemList.jsp 页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查询商品列表</title>
</head>
<body> 

	商品列表:
	<table width="100%" border=1>
		<tr>
			<td>商品名称</td>
			<td>商品价格</td>
			<td>生产日期</td>
			<td>商品描述</td>
			<td>操作</td>
		</tr>
		<!-- 取出ModelAndView中设置的数据,使用el表达式获取,类似从域中取数据一样 -->
		<c:forEach items="${itemList }" 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>
				
				<td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>
			
			</tr>
		</c:forEach>
	
	</table>

</body>

</html>

ok,然后在浏览器中输入地址 http://192.168.30.217:8080/springmvc01/list.action ,如下所示,页面和数据都显示正常,说明配置成功了。
在这里插入图片描述

看到这,你以为就完了吗,还没完,下面介绍一些优化的处理。

优化处理

1.手动配置处理器映射器和处理器适配器

上面介绍中你会发现SpringMvc.xml中什么类都没有注入,只是添加了开启注解的扫描的功能,会不会很好奇DispatcherServlet(前端控制器)是如何去查找对应的HandlerMapping和HandlerAdapter的实现去处理请求的呢?

其实Spring MVC默认会去spring-webmvc-4.1.3.RELEASE.jar 包中查找这个DispatcherServlet.properties配置文件

# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

其中DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter 对应的就是默认的支持注解形式的处理器映射器和适配器。

而InternalResourceViewResolver就是默认的视图解析器。

那么问题就来了,这样每一次的请求都会去该文件内查找依次判断符合条件的组件,这样的效率会很慢的。

所以建议直接在SpringMvc.xml中显示什么对应的处理器映射器和适配器。但是查看DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter 原码你会发现, 这2个类在3.2之后的版本已经过时了
在这里插入图片描述
在这里插入图片描述
原码中建议使用RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter替代。

看到这,你可能会直接毫不犹豫的把这2个类的完整路径copy到SpringMvc.xml进行注入,这样做也行,不过我这里还有一种更加完美的方案:

<mvc:annotation-driven></mvc:annotation-driven>

就是这么简单,在SpringMvc.xml中添加这样一句话就搞定了,它的作用就是帮你自动配置最新版的处理器映射器和处理器设配器。

2.配置视图解析器,简化书写视图路径

InternalResourceViewResolver是默认的视图解析器,无需显示配置都可以,但是如果配置的话,它可以设置视图路径的前缀和后缀,从而简化视图路径的书写。

在上面,我也提到过ModelAndView的setViewName方法默认是需要书写完整的路径,否则会报错,例如
modelAndView.setViewName("/jsp/itemList.jsp")

如果我想让其支持这样书写是不是很方便嘞
modelAndView.setViewName("itemList")

很简单,只需要这样配置一下即可

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- 真正的页面路径 = 前缀 + 去掉后缀名的页面名称 + 后缀 -->
		<!-- 配置前缀 -->
		<property name="prefix" value="/jsp/"></property>
		<!-- 配置后缀 -->
		<property name="suffix" value=".jsp"></property>
</bean>

搞定. 完整的SpringMvc.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:dubbo="http://code.alibabatech.com/schema/dubbo" 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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<!-- 开启注解的扫描,支持注解方式注册 -->
	<context:component-scan base-package="blog.csdn.net.mchenys" />


	<!-- 添加注解驱动,作用就是自动配置最新版的处理器映射器和处理器设配器 -->
	<mvc:annotation-driven></mvc:annotation-driven>


	<!-- 配置视图解析器,默认用的就是jsp解析器,可选配置 配置了的好处就是可以在controller中简化setViewName参数的书写 
		例如:modelAndView.setViewName("/jsp/itemList.jsp"); 配置了前缀和后缀就可以这样书写: modelAndView.setViewName("itemList"); -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- 真正的页面路径 = 前缀 + 去掉后缀名的页面名称 + 后缀 -->
		<!-- 配置前缀 -->
		<property name="prefix" value="/jsp/"></property>
		<!-- 配置后缀 -->
		<property name="suffix" value=".jsp"></property>

	</bean>

</beans>

项目结构如下:
在这里插入图片描述
图中爆红是eclipse的问题,配置是没有错的.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值