SpringMVC(一):简介和第一个程序
-
SpringMVC重点
-
执行流程
-
-
回顾MVC
-
MVC就是模型(model)、视图(View)、控制层(Controller),是一种软件设计规范。
-
是将业务逻辑、数据、显示分离的方法来组织代码。
-
MVC主要作用是降低了视图与业务逻辑间的双向偶合。
-
MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。以前我们是这样编写的:
-
M:dao, service
-
V:Jsp
-
C:servlet
-
定义
-
Model(模型):实体类和业务逻辑:Value Object(数据Dao) 和 服务层(行为Service)。
-
View(视图):客户直接看到的页面。
-
Controller(控制器):接收客户请求,调用业务逻辑,转向指定的页面。
-
最典型的MVC就是JSP + servlet + javabean的模式。
回顾Servlet
-
创建maven项目,导入依赖。
<!--导入依赖--> <dependencies> <!--spring--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.5.RELEASE</version> </dependency> <!--spring connect to db--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.5.RELEASE</version> </dependency> <!--aop--> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.5</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.19</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.4</version> </dependency> <!--Mybatis and spring --> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.4</version> </dependency> <!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!--servlet依赖--> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <!--jsp依赖--> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.1</version> </dependency> <!--jstl表达式--> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl-api</artifactId> <version>1.2</version> </dependency> <!--standard标签库--> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!--工具类,可以复制对象--> <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils --> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.9.4</version> </dependency> </dependencies>
-
添加Web框架
-
HelloServlet
package com.rzp.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取前端参数 String method = req.getParameter("method"); if (method.equals("add")){ req.getSession().setAttribute("msg","执行了add方法"); } if (method.equals("delete")){ req.getSession().setAttribute("msg","执行了delete方法"); } //TODO:调用业务层 //转发 req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
-
web.xml注册
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.rzp.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
-
jsp/test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>${msg}</title>
</head>
<body>
${msg}
</body>
</html>
-
测试
小结
用户通过输入url和参数可以进入到对应的页面,这里MVC框架做的事情:
-
封装用户输入的信息(request),根据url,通过wel.xml中注册的信息,映射到Java的类里面。
-
处理用户的请求,业务处理,封装响应的数据。
-
把响应的数据转发/重定向到页面中。
-
转发/重定向回顾:
-
转发不会改变url,使用的是request的方法getRequestDispatcher
-
重定向会改变url,使用的是response的方法sendRedirect。
-
SpringMVC简介
-
Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。
-
Spring MVC的特点:
-
轻量级,简单易学
-
高效 , 基于请求响应的MVC框架
-
与Spring兼容性好,无缝结合
-
SpringMVC中所有的的都可以在Spring中注册。
-
-
约定优于配置
-
功能强大:RESTful、数据验证、格式化、本地化、主题等
-
简洁灵活
-
-
Spring的web框架围绕DispatcherServlet [ 本质是继承了Servlet ] 设计。
-
DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁;
第一个SpringMVC程序
-
创建4个文件
-
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--注册DispatcherServlet--> <!--这个类是Spring写好的,我们直接注册就可以了--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--导入spring的配置文件--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <!--启动级别--> <load-on-startup>1</load-on-startup> </servlet> <!--所有的请求都会经过这个类--> <!--/ 匹配所有的请求(不包括jsp)--> <!--/* 匹配所有的请求(包括jsp)--> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-
springmvc-servlet
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--添加 处理映射器--> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <!-- 添加 处理器适配器--> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!--视图解析器:DispatcherServlet给他的ModelAndView--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver"> <!--页面前缀--> <property name="prefix" value="/WEB-INF/jsp/"/> <!--页面后缀--> <property name="suffix" value=".jsp"/> </bean> <!--Handler--> <bean id="/hello" class="com.rzp.controller.HelloController"/> </beans>
-
HelloController
package com.rzp.controller; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //注意:这里我们先导入Controller接口 public class HelloController implements Controller { public HelloController() { System.out.println("构造HelloController"); } public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { //ModelAndView 模型和视图 ModelAndView mv = new ModelAndView(); //封装对象,放在ModelAndView中。Model mv.addObject("msg","HelloSpringMVC!"); //封装要跳转的视图,放在ModelAndView中 mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp return mv; } }
-
hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> ${msg} </body> </html>
-
测试:在url的项目名后面输入/hello即可:
http://localhost:8080/项目名/hello
发布的问题
发布后由于jar包需要提供给Tomcat,程序才能正常启动,因此要这样配置,否则可能会出现程序一切正常,但是输入地址后就是404:
这样就会把依赖的jar包发布到项目中。
-
测试,在发布后的浏览器中
SpringMVC的执行流程
-
首先用户在浏览器上输入地址,一定会经过DispatcherServlet。
-
因为DispatcherServlet就是我们在servlet的web.xml中唯一需要注册的类
-
用户发出请求,首先就会经过DispatcherServlet接收请求并拦截请求
-
相对的,其他的类我们都不再需要在servlet中注册了,简化了大量的代码,全部都经过SpringMVC帮我们处理。DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。
-
我们假设请求的url为 : http://localhost:8080/SpringMVC/hello
-
如上url拆分成三部分:
-
SpringMVC部署在服务器上的web站点
-
hello表示控制器--也就是我们写的Controller层的类
-
通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。
-
-
DispatcherServlet得到url后,调用HandlerMapping,HandlerMapping根据请求url查找Handler。
-
HandlerMapping为处理器映射,是一个接口。
-
HandlerExecution表示具体的Handler,会根据我们输入的url--hello查找对应的类。
-
HandlerExecution将找到的类传递给DispatcherServlet。
-
DispatcherServlet再传递给HandlerAdapter。
-
Handler执行Controller的ModeAndView方法,也就是我们继承Controller重写的方法。
-
在这里我们可以调用Mode层,并把要显示的信息、要用来显示的界面封装到ModeAndView这个对象里----正是Controller层应该做的事。
-
Controller将ModeAndView对象返回给HandlerAdapter。
-
HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
-
DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名
-
视图解析器将解析的逻辑视图名传给DispatcherServlet。
-
DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
-
最终视图呈现给用户。
备注:
实际开发中我们并不会使用这个方式,而是使用注解开发。
另外,即使使用这个方式,其实也不需要注册映射器和适配器,在这里只是为了更好的说明MVC的流程。