>简介
SpringMVC是Spring框架的一个模块,SpringMVC和Spring无需通过中间整合层进行整合。SpringMVC是一个基于MVC的web框架,即Spring Web MVC。Spring Web MVC和Struts2都属于表现层的框架,它是Spring框架的一部分,我们可以从Spring的整体结构中看得出来:
>WEB MVC基本原理
补充:传统界面编程的MVC是一个闭环结构,组件(view)触发事件监听函数(控制层),控制函数改变模型层数据(model),随之组件(view)更新。
首先来一下MVC,MVC是一种设计模式,在大量的软件开发过程中所积累出来的经验,然后根据经验抽象出来的一种开发模式。下面来看一下MVC设计模式B/S架构的系统下的应用:
>SpringMVC框架原理
从上图中看到MVC的基本框架后,那么下面学习SpringMVC框架就有了一个大体的思路。因为SpringMVC就是MVC模型的一种框架。所以学习SpringMVC框架主要就是来看SpringMVC中的C(控制层)、M(模型层)、V(视图层)的各种技术实现即可。如下图所示:
根据上图所示,使用SpringMVC的步骤如下:
- 发起请求到前端控制器DispatcherServlet("大总管,只是分发任务"),处理请求,但不执行具体操作(model层)
- 前端控制DispatcherServlet请求HandlerMapping("将请求url与处理对象去一一对应")查找Handler,(XML配置或注解)
- 处理器映射器HandlerMapping向前端控制器返回handler执行链
- 前端控制器调用处理器适配器去执行handler
- 处理器适配器执行handler
- handler执行完成后返回给处理器适配器ModelAndView(SpringMVC框架的一个底层对象,包括model、view)
- 处理器适配器向前端控制器返回ModelAndView
- 前端控制器请求视图解析器去进行视图解析,根据逻辑视图名解析成真正的视图(jsp)
- 视图解析器向前端控制器返回view
- 前端控制器进行视图渲染,将模型数据(在ModelAndView)填充到request域中。
- 前端控制器向用户响应结果。
以上步骤涉及到的组件:
>SpringMVC 入门程序
1、配置SpringMVC的前端控制器(相当于整个MVC的入口)
- 前端控制器DispatcherServlet,作用:接收请求,响应结果,相当于转发(不需要程序人员开发)
- 处理器映射器HandlerMapping,作用:根据请求url查找handler(不需要程序人员开发)
- 处理器适配器HandlerAdapter,作用:按照特定的规则去执行handler,所谓的特定规则,即HandlerAdapter指定的规则。(不需要程序人员开发)
- Handler处理器。(需要程序人员开发,还需要进行匹配映射)
- 视图解析器Viewresolver,作用:进行视图解析,根据逻辑视图名解析成真正的视图view(不需要程序人员开发)
- 视图View,作用:View是一个接口,实现类支持不同的View类型(jsp、freemarker等)(需要程序人员开发,View不需要但是页面需要开发)
<!-- 配置前端控制器,本质就是一个Servlet,分发器 -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
如何让DispatchServlet去处理那些需要业务逻辑处理的url,如何实现?
url-pattern的配置有两种方式:
第一种:*.action;访问以.action结尾的任何请求都由DispatcherServlet进行解析。
第二种:/,所有访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析,使用此种方式可以实现RESTful风格的url。
还要告知应用配置mvc文件的位置,进行配置:
<!-- 配置前端控制器,本质就是一个Servlet,分发器 -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:Spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
2、配置处理器映射器
以BeanNameUrlHandlerMapping为例子:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<!-- 配置SpringMVC的BeanNameUrlHandlerMapping处理器映射器,这个bean给Spring用,不用配置Id -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
</beans>
3、配置处理器适配器(用来执行handler这个bean)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<!-- 配置SpringMVC的BeanNameUrlHandlerMapping处理器映射器,这个bean给Spring用,不用配置Id -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--配置处理器适配器:根据映射返回的执行链中的Handler,由适配器来执行Handler -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
</beans>
适配器,会先去判断Handler是不是Controller类型:
4、Handler怎么写?
补充一种发布项目的方式:
handler代码:
package com.langsin.action;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
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.langsin.pojo.User;
public class TestAction implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {
// 这里如果去数据库查,需要整合MyBatis,先伪造一点数据
List<User> userlist=new ArrayList<>();
ServletContext application=req.getServletContext();
String webPath=application.getRealPath("/")+"WEB-INF/datas/data.txt";
BufferedReader reader=new BufferedReader(new FileReader(webPath));
String line=null;
while((line=reader.readLine())!=null){
String[] datas=line.split(",");
User user=new User();
user.setUserName(datas[0]);
user.setCname(datas[1]);
userlist.add(user);
}
reader.close();
ModelAndView mav=new ModelAndView();
//这里底层会调用 req.setAttributes()方法
mav.addObject("userlist",userlist);
mav.setViewName("/WEB-INF/jsp/user_list.jsp");
return mav;
}
}
配置handler:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<!-- 配置SpringMVC的BeanNameUrlHandlerMapping处理器映射器,这个bean给Spring用,不用配置Id -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--配置处理器适配器:根据映射返回的执行链中的Handler,由适配器来执行Handler -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 配置Handler以及对应的映射 name就是url class是对应的执行bean -->
<bean name="/user_list.action" class="com.langsin.action.TestAction"/>
</beans>
jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!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>Insert title here</title>
</head>
<body>
<table>
<tr><th>用户名</th><th>昵称</th></tr>
<c:forEach items="${userlist}" var="user" >
<tr><td>${user.userName}</td><td>${user.cname}</td></tr>
</c:forEach>
</table>
</body>
</html>
运行结果: