Spring MVC执行原理
总的来说,Spring MVC框架在之前的基础上增加了一层 DispatcherServlet(调度Servlet)。而它的作用是将请求分发到各个不同的处理器(Servlet)。
下图是整个执行过程,实现为spring自动实现的操作,虚线是我们手动。
当我们获得一个请求的时候会进入DispatcherServlet,首先通过HandlerMaping去寻找我们对应servlet的映射,其次进入HandlerExecution中查找这个控制器,然后返回到DispatcherServlet。
之后通过HandlerAdapter去适配这个控制器,通过这个适配器去执行我们编写的controller。
假设我们请求到 “/hello” ,Spring会寻找一个maping未 “/hello” 的映射器,然后再找到这个映射对应的“业务类”。而这个业务类会获取两个数据 “Model And View”,很显然,model是指要返回的数据,而view是指要返回的对应界面。
值得注意的是,我们现在都提倡前后端分离,所以一般情况下我们并不会按照这个逻辑进行返回view。
当controller执行完毕后,会通过适配器再返回到DispatcherServlet,再由它向ViewResolver进行解析model和view,最后拼合成一个完整的视图,
再由DispatcherServlet返回给用户。
通过以上流程一步步走,很显然,如果我们要编写Spring MVC,我们只需要创建一个Servlet调度器——DispatcherServlet,Controller,ViewResolver,三个东西就可以实现开发~
创建DispatcherServlet
首先,我们就需要在web.xml中加入以下代码。我们值得注意的是,我们需要在DispatcherServlet中配置它。所以需要另外创建一个配置文件springmvc-servlet.xml。
我们的所有配置其实都是基于DispatcherServlet。需要配置:ViewResolver视图解析器、注解支持..
<servlet>
<servlet-name>SringMVC</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>
</servlet>
<servlet-mapping>
<servlet-name>SringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
springmvc-servlet.xml配置
值得注意的是,这个名字是自定的。
首先,contex:component-scan,这个之前在spring记录文中有记录,即扫描该包名下的注解。
第二个的含义是让spring mvc不处理静态资源。如果不适用这个,当用户请求一个静态资源的时候,spring mvc也会按照上面那个流程走...
其次是让mvc的注解生效,后面我们会学到mvc中独有的几个注解。
再之后便是配置视图解析器,这里先不做记录。
<context:component-scan base-package="com.kum.controller"/>
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>
<!-- 视图解析器 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
自此,配置完毕。
controller
当配置完毕后,我们就需要编写一个控制器,我们只需要在一个类的标题上写上 @controller注解,便可以声明这是一个控制器。
在控制器中使用 @RequestMapping("h1") 便是对 “/hi” 这个请求进行处理。
可以说RequestMapping注解就是绑定一个请求地址。
在之前我们说过,controller会返回 model and view,我们直接加入一个Model的参数进行添加即可。它是一个键值对的结构。
之后返回的一个string,其实含义是指 /WEB-INF/jsp/ 文件夹下的 hello.jsp 文件。
此时返回到视图解析器配置文件中,是不是就突然懂了? 这样方便我们进行编写~
@RequestMapping("h1")
public String hello(Model model){
model.addAttribute("msg","Hello spring mav controller");
return "hello";
}
但视图解析器是需要将model放到hello.jsp之中的,很显然有一个key叫“msg”的数据,我们只需要在jsp中加入 “${msg}” 即可将“Hello spring mav controller"放置jsp其中。
自此便结束。
使用Json数据格式进行相应
前面说了,目前在一个前后端分离的趋势之中,后端其实只需要编写一个接口交给前端进行使用,而不再操控view层,这样降低很多的耦合性。
所以我们将抛弃视图解析器,直接返回一个字符串(Json也是一个字符串,只不过按照一个格式~)。
我们需要在@RequestMapping注解的基础上增加一个 @ResponseBody() 注解,这样就说明我们的方法直接返回一个数据。
@ResponseBody()
@RequestMapping("h2")
public String hello1(){
return "2333";
}
如上,当请求”/h2“的时候,只会返回一个 ”2333“ 这样的字符串。
我们都知道,实际上json只不过是一种有结构层次的字符串。很显然,只需要使用某个库转换一下就ok了。这里使用fastjson.
User user = new User("阿萨斯", 20, "男");
String str = JSON.toJSONString(user);
return str;
user类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private int age;
private String sex;
}
最终在界面中呈现的数据:
{"name":"阿萨斯","age":20,"sex":"男"}