2021-05-26

springMVC的执行流程

当用户向服务器发送请求时。

在servlet阶段,用户发送请求后,servlet端会接收用户端传来的数据,并通过service层进行业务的处理,再将处理后的结果,通过请求转发或者重定向的方式,反馈给用户。

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        System.out.println(username);
        req.setAttribute("username", username);
        req.getRequestDispatcher("/test/a.jsp").forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

在整个过程中,我们需要再web.xml文件中配置相应的Servlet。当用户发送不同的请求,我们就需要创建不同的Servlet程序,并且在xml文件中进行配置。

    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/helloServlet</url-pattern>
    </servlet-mapping>

但是,在实际的开发过程中,一个web工程有很多不同的功能,如果这样,用户发送不一样的请求,就要新建一个servlet,就要配置一个servlet,这样会让代码冗余,而且工作量也十分大。那么怎么解决这个问题呢? SpringMVC很好的解决了这个问题。

在SpringMVC中,你不需要编写servlet程序,因此也不需要在  web.xml中对其进行配置。springMVC对其进行了分离,当用户发送请求时,SpringMVC会通过前端控制器(DispatcherServlet)对用户的请求进行拦截和过滤,分别通过处理器映射、处理器适配、视图解析器处理之后,将结果渲染到视图上。而在此过程中,在处理器适配完成之后,会找到相应的控制器(Controller),进行业务的执行。整个springMVC的执行看下图:

根据上图可以得出具体的执行原理

1.用户发送请求之后,请求由前端控制器(DispatcherServlet)接收,前端控制器是整个SpringMVC框架的核心。

2.HandlerMapping,即处理器映射,会根据用户的请求来映射对应的Handler,即处理器。

3.HandlerExecution,即处理器执行,通过处理器的执行来找到相应的控制器。

4.将得到的控制器返回

5.HandlerAdapter,处理器适配,根据特定的规则去查找适配的处理器。

6.Controller,控制器,执行适配的处理器,并处理具体的业务,再将ModelAndView返回给前端控制器

7.ViewResolver,视图解析器,将ModelAndView进行解析,并渲染到视图上

其实,在使用springMVC进行web开发的过程中,我们不需要关心前端控制器是如何来进行过滤拦截等操作的,我们只需要关注业务层的相关代码以及Controller,其他SpringMVC已经帮我们在底层实现了,我们直接用就可以了。但是为了搞清楚整个执行过程是很有必要的,可以帮助我们更好的去理解SpringMVC的优点。

编写一个实例如下:

前面说到,一切的工作都是由前端控制器来执行的,因此需要再web.xml配置DispatcherServlet的参数信息,设置参数,绑定到相对应的spring配置文件中

<!-- 用户发送请求,会通过DispatcherServlet 前端控制器,请求分发器 这是整个MVC的核心 -->
    <!-- 配置DispatcherServlet -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <!-- 配置参数, 需要绑定的spring的配置文件 -->
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
        <!-- 设置启动级别,1: 服务器启动就开启 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

配置好前端控制器,那么当用户发送请求的时候,就会被它所过滤和拦截。

接下来,按照图中的信息,我们需要三个部分的处理,分别是:处理器映射、处理器适配、视图解析。这些事情全部都在spring的配置文件中去配置,先上代码:

<!-- 处理器映射器 前端控制器会根据用户请求,调用处理器映射,根据请求的url来查找对应的Handler
     查到对应的处理器之后,会调用处理器你执行器,查找对应的控制器,并返回给前端控制器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
    <!-- 处理器适配器 前端控制器会调用处理器适配,并执行处理器,在将具体的业务交给适配的控制器去处理-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
    <!-- 视图解析器, 控制器处理相关业务之后,就会返回一个ModelAndView,视图解析器就会对其进行解析-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!-- 视图解析器会根据返回的参数,将数据拼接成一个完整的url,返回给用户 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

先不管上述代码,前面说到,我们只需要编写Controller以及业务层的相关代码就可以了,那Controller程序怎么编写呢?其实spring为我们提供了一个Controller接口,我们只需要去实现这个接口就可以了。

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.ModelAndView;

@FunctionalInterface
public interface Controller {
    @Nullable
    ModelAndView handleRequest(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
}

可以看出,Controller是一个函数型接口, 里面只有一个方法,而该方法刚好返回的就是一个ModelAndView对象,正是我们所需要的,

//适配器进过处理后,适配相对应的Controller控制器
public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //创建一个ModelAndView实例
        ModelAndView modelAndView = new ModelAndView();

        //具体业务
        String result = "HelloSpringMVC";
        modelAndView.addObject("msg", result);
        //视图跳转到具体的那个页面
        //视图解析器会自动拼接成完整的url
        modelAndView.setViewName("test");

        //返回一个模型视图
        return modelAndView;
    }
}

我们需要先new一个ModelAndView对象,然后调用业务方法完成业务操作,紧接着设置要跳转的页面,最后将视图返回。假设我们的业务是在对应的页面上打印“HelloSpringMVC”,addObject方法类似于req.serAttribute()方法, 参数是K-V的形式。最后,在spring配置文件中,初始化bean对象

<!-- 初始化控制器bean对象 -->
    <bean id="/hello" class="com.springmvc.controller.HelloController" />

想必你还是不是很理解springMVC到底是怎么执行的,那么就对应着具体代码来分析。

首先,我们需要一个前端控制器,而这个前端控制器需要与网页进行交互,因此需要再web.xml文件中配置,而这个类springMVC已经为我们提供好了。并且,有上面的大致分析可以看出,前端控制器需要通过处理器映射、处理器适配对用户的请求进行相关的业务操作,最后再由视图解析对结果进行渲染。那么,通过一个spring的配置文件来实现一系列的操作。

处理器的映射与执行:假定用户现在访问的是这个url: http://localhost:8080/hello,    那么通过处理器的映射后拿到url,在通过处理器的执行器来查找对应的控制器,即“/hello”

<!-- 处理器映射器 前端控制器会根据用户请求,调用处理器映射,根据请求的url来查找对应的Handler
     查到对应的处理器之后,会调用处理器你执行器,查找对应的控制器,并返回给前端控制器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

 处理器适配; 前端控制器会将处理器进行适配,找到符合要求的控制器,即Controller,再由它进行业务操作

<!-- 处理器适配器 前端控制器会调用处理器适配,并执行处理器,在将具体的业务交给适配的控制器去处理-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />

通过上面两个步骤,就可以准确的找到对应的控制器,而这个控制器就是spring中配置的这个bean对象

<!-- 初始化控制器bean对象 -->
    <bean id="/hello" class="com.springmvc.controller.HelloController" />

 

//适配器进过处理后,适配相对应的Controller控制器
public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //创建一个ModelAndView实例
        ModelAndView modelAndView = new ModelAndView();

        //具体业务
        String result = "HelloSpringMVC";
        modelAndView.addObject("msg", result);
        //视图跳转到具体的那个页面
        //视图解析器会自动拼接成完整的url
        modelAndView.setViewName("test");

        //返回一个模型视图
        return modelAndView;
    }
}

HelloController经过操作以后返回了一个ModelAndView实例,上面的代码可以看出当完成业务之后,视图会跳转到指定的页面,而其中只设置了一个"test" , 很显然,这不是一个完整的页面url,因此,视图解析器需要出场了:

<!-- 视图解析器, 控制器处理相关业务之后,就会返回一个ModelAndView,视图解析器就会对其进行解析-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!-- 视图解析器会根据返回的参数,将数据拼接成一个完整的url,返回给用户 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

视图解析器有两个参数,分别表示的是前缀和后缀,意思就是,视图解析器会自动的帮你拼接url即: /WEB-INF/jsp/test.jsp, 那么现在就是一个完整的url了

最后就会将结果渲染在视图上

 

2021-03-26 20:54:33,596 - Model - INFO - Epoch 1 (1/200): 2021-03-26 20:57:40,380 - Model - INFO - Train Instance Accuracy: 0.571037 2021-03-26 20:58:16,623 - Model - INFO - Test Instance Accuracy: 0.718528, Class Accuracy: 0.627357 2021-03-26 20:58:16,623 - Model - INFO - Best Instance Accuracy: 0.718528, Class Accuracy: 0.627357 2021-03-26 20:58:16,623 - Model - INFO - Save model... 2021-03-26 20:58:16,623 - Model - INFO - Saving at log/classification/pointnet2_msg_normals/checkpoints/best_model.pth 2021-03-26 20:58:16,698 - Model - INFO - Epoch 2 (2/200): 2021-03-26 21:01:26,685 - Model - INFO - Train Instance Accuracy: 0.727947 2021-03-26 21:02:03,642 - Model - INFO - Test Instance Accuracy: 0.790858, Class Accuracy: 0.702316 2021-03-26 21:02:03,642 - Model - INFO - Best Instance Accuracy: 0.790858, Class Accuracy: 0.702316 2021-03-26 21:02:03,642 - Model - INFO - Save model... 2021-03-26 21:02:03,643 - Model - INFO - Saving at log/classification/pointnet2_msg_normals/checkpoints/best_model.pth 2021-03-26 21:02:03,746 - Model - INFO - Epoch 3 (3/200): 2021-03-26 21:05:15,349 - Model - INFO - Train Instance Accuracy: 0.781606 2021-03-26 21:05:51,538 - Model - INFO - Test Instance Accuracy: 0.803641, Class Accuracy: 0.738575 2021-03-26 21:05:51,538 - Model - INFO - Best Instance Accuracy: 0.803641, Class Accuracy: 0.738575 2021-03-26 21:05:51,539 - Model - INFO - Save model... 2021-03-26 21:05:51,539 - Model - INFO - Saving at log/classification/pointnet2_msg_normals/checkpoints/best_model.pth 我有类似于这样的一段txt文件,请你帮我写一段代码来可视化这些训练结果
02-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值