快速入门(IDEA版无注解)
IDEA建立Maven项目后,添加web框架后,导入以下的jar依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
随后,手动配置注册Servlet,如下
<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-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
再在resources目录下创建xml文件(起到SpringIOC容器的作用),文件名要和web.xml中<init-param>
的value值
如web.xml中写的springmvc-servlet.xml名中添加bean组件如下
- 添加处理映射器
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
- 添加处理器适配器
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
- 添加视图解析器
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
- 添加Controller自定义类
<bean id="/hello" class="controlller.MyController"/>
这里,id就是用户请求的url最后的请求
然后在java中新建类com.sang.controller.MyController
package com.sang.controlller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyController implements Controller {
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;
}
}
ModelAndView 是一个类,表示模型和视图,返回给DispatcherServlet前端控制器,这里传递了一个msg的变量,值为字符串“HelloSpringMVC!",viewName是hello.jsp,随后会讲解原理
在WEB-INF下新建目录jsp,在里面新建hello.jsp前端页面,这里就写上如下
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
然后部署Tomcat中后,启动服务器,访问localhost:8080/springmvc-01/hello
结果如下:
原理细解
先看如下的图:
首先 用户通过url访问服务器
URL形如
(127.0.0.1:8080)/(springmvc-01)/(hello)
- 第一个括号是服务器的ip
- 第二个括号是服务器的项目
- 第三个括号是一系列的请求
我们在web.xml中写了如下映射
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
意思就是所有请求都会去找名为springmvc的servlet,而这个servlet的注册就是对应DispatcherServlet这个类,这个中央控制器(又称前端控制器)会将请求/hello
交给处理器映射器,映射器(HandlerMapping)会把请求映射为HandlerExecutionChain类型的handler对象交给这个中央控制器;然后中央处理器将handler对象作为参数传递给适配器(HandlerAdapter)的实例化对象,适配器对其进行处理,还会调用其他模型层最后返回ModelAndView给中央处理器。
处理器映射器,处理器适配器,这两个类我们在web.xml中引入了springmvc-servlet.xml的
SpringIOC
容器,在这个容器中我们注册有处理器映射器和处理器适配器
细看我们的controller,它实现了Controller接口,也就是默认为一个处理器,点开观察源码需要实现一个类如下
ModelAndView handleRequest(HttpServletRequest var1,
HttpServletResponse var2) throws Exception;
这个类的返回类型是ModelAndView,意思就是模型和视图,他会携带模型返回给中央处理器,告诉中央处理器模型将要去哪一个视图,于是中央处理器对其进行已经配置一个或多个视图解析器,视图解析器对视图处理,响应给用户,用户最后会得到想要的页面。
原理深入
以上讲了大致的流程,我觉得有些细节和深层的知识没有列出,这里总结一下吧
SpringMvc的核心就三个处理器映射器,处理器适配器,视图解析器。
处理器映射器
这里我们在IOC里配置的mapping是比较low的,但是比较适合原理解剖。
BeanNameUrlHandlerMapping
这个类会对请求名在IOC内进行Bean组件的id进行匹配
然后把请求映射为HandlerExecutionChain类型的handler对象交给中央控制器;可以明确HandlerExecutionChain与HanderMapping关系非常紧密,HandlerExecutionChain只能通过HanderMapping接口中的唯一方法来获得,而我们这里用到的映射器只是其中一个。
注意:映射器不仅仅封装的有handler对象,还封装了拦截器,日后细解。
处理器适配器
只需要理解的就是适配器接受了中央处理器传递过来的handler对象,在IOC容器里有注册了的controller,适配器执行的handler对象在我们看来就是执行对应的controller,这里可能会调用其它层,业务层,数据库dao等等,最终都会封装一个ModelAndView类。这个类有Object类和String的视图名,适配器会将这个对象传递给中央处理器。
视图解析器
在我们的IOC容器里我们配置了如下图的bean
这bean中配置了prefix和suffix,就是视图的前缀和后缀,ioc会注入的方式给视图解析器赋值,这里我们设置了前缀为/WEB-INF/jsp/
意味着我们解析器会在这个项目路径下的这个目录下开始找页面;后缀我们写的是.jsp
,意思就是jsp格式的页面;我们在之前的处理器适配器中说到了最红处理器适配器会将ModelAndView这个对象传进中央处理器,然后中央处理器会将这个对象传递给视图解析器,前缀和后缀都规划好了,view的视图名在中间,最终形成完整的视图路径名,ViewResolver就会把该逻辑视图路径解析为真正的View视图对象,然后通过View的渲染,将最终结果返回给中央处理器,然后呈现给用户。
小结
今天有同学找我解决问题就是快速建立就会报的404错误,看了代码,都是对的,那就是环境的问题,后来去网上看了一下,lib目录没有导入我们把所有的jar引入即可,IDEA有时会有这个问题。
原理方面的知识,结合一下图片,就能轻松的解决这些面试基础回答,但是深层的知识还需要进一步去探索,源码的解剖室最为有效的学习方法,我见过有的大牛,自己动手写SpringBoot简易版,当然了,成功的背后总是漫漫长路,我们需要不停的学习和努力!