文档章节

springMVC笔记系列(17 特别篇的开始)——springMVC要点回顾及idea开发环境搭建

HappyBKs
 HappyBKs
发布于 2016/06/14 11:14
字数 4383
阅读 607
收藏 3

这次文章是springMVC笔记系列时隔一年之后的继续,但是我想先就其中的数据绑定写一串博文。

首先,这里做个插曲。之前的博客文章用的IDE是STS(eclipse的子子孙孙),这次springMVC数据绑定的几篇博客文章,我的示例用的是intellj idea,所以,给不熟悉这个IDE工具的同学做个把屎把尿的插曲介绍。

这里需要特别注意的是,idea和eclipse在一些概念上有区别,十分容易混淆,这里做个说明:

eclipse idea
workspace project
project module

idea中的project相当于eclipse中的workspace,而idea中的module相当于eclipse中的project。但是在组织形式上也会有些许的不同,这个我们后面再说。

我们先在idea下把Maven webapp项目建好,步骤如图,文字自行脑补。

 

(本文出自:http://my.oschina.net/happyBKs/blog/690926)

 

 

(这里说明一下,由于当中idea版本升过级,重新建了个项目所以这里截图看到的是ideaSpringMVC,其实应该是ideaSpringMVC2。)

idea新建maven webapp没有src,要自己建,T T。

 

idea建立的文件夹可以做用处标记,源文件文件夹、资源文件夹等等。不然右击文件夹新建的时候会找不到相应的模板。

方便还是挺方便的。

 

 

打住,要开始建立我们在idea下的第一个springMVC了,你还记得我一年多前本系列的前面的十几篇文章吗?好吧,如果你已经忘得差不多了,也别急着翻了,我将关键的原理在这里重新整理复习一下,做个插叙。

这是Spring团队贡献给我们的一种MVC的实现方式——前端控制器。

Front controller前端控制器 负责 分发、调度

Controller控制器 负责 业务数据抽取

View Template 负责页面呈现

首先,http请求由客户端发送给服务端的前端控制器,前端控制器知道该请求应该由谁来进行处理,将该请求分发给相应的控制器;之后,控制器知道业务逻辑的细节,调用相关的业务逻辑,生成业务数据即model,并将业务数据返回给前端控制器;此时,前端控制器再将控制器返回的业务数据发送给业务视图;然后,业务视图来呈现最后的业务页面,将该呈现页面返回给前端控制器;最后,前端控制器将呈现页面返回给浏览器端。

那为什么叫“前端控制器”(调度器)呢?打个比方,以上场景与医院前台类似,接受求医信息,分发挂号到不同的科室,不同的科室了解不同的业务细节。

MVC的核心思想是 业务数据抽取 同 业务数据呈现 分离!

MVC是一种架构模式:程序分层,分工合作;既相互独立,又协同工作。

MVC是一种思考方式:需要将什么信息展现给用户(C)?如何布局(V)?调用哪些业务逻辑(M)?

 

好,我们回到SpringMVC框架,这里需要提到它的几个概念。首先我们来看九大静态概念。

springMVC的九大静态概念

首先是DispatcherServlet,它正式SpringMVC对前端控制器的实现。

用户的请求正式通过springMVC的DispatcherServlet进行了分发,到达相应的Controller;Controller进而生成我们需要的业务数据model;这个model由Controller返回给DispatcherServlet进行传递,传递给相应的View,来完成最终的页面呈现。

第二个概念是Controller。

这个不多讲,它调用业务逻辑,生成相应的model

第三个概念是HandlerAdapter。首先,什么是Handler?Handler是在DispatcherServlet内部使用的一个类,它其实就是Controller的一个表现形式。在SpringMVC中并没有一个inteface叫做Controller,而是只有一个annotation(注解),@Controller,用以springMVC识别Controller。

既然没有Controller这样一个interface或者abstract class,那么springMVC的DispatcherServlet如何来知道各个Controller呢?那就是Handler。在springMVC的DispatcherServlet调用的各个控制器都是以Handler形式出现的。

那什么是HandlerAdapter呢?好吧,听名字就应该知道,这是一个适配器模式。它的作用就是将各种类型的Handler,是配成springMVC的DispatcherServlet可以使用的Handler。

这样,springMVC的DispatcherServlet就可以轻松调用控制器。

 

第四个概念是HandlerIntercepter。HandlerIntercepter是一个拦截器。(Intercepter是拦截器的意思)它在需要被拦截对象的两侧加入一些料。HandlerIntercepter是一个interface。

以下是HandlerIntercepter接口中的三个方法。

HandlerInterceptor 接口中定义了三个方法,我们就是通过这三个方法来对用户的请求进行拦截处理的。

   (1 )preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法。该方法将在请求处理之前进行调用。SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值Boolean 类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。

   (2 )postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解释我们知道这个方法包括后面要说到的afterCompletion 方法都只能是在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用。postHandle 方法,顾名思义就是在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。postHandle 方法被调用的方向跟preHandle 是相反的,也就是说先声明的Interceptor 的postHandle 方法反而会后执行,这和Struts2 里面的Interceptor 的执行过程有点类型。Struts2 里面的Interceptor 的执行过程也是链式的,只是在Struts2 里面需要手动调用ActionInvocation 的invoke 方法来触发对下一个Interceptor 或者是Action 的调用,然后每一个Interceptor 中在invoke 方法调用之前的内容都是按照声明顺序执行的,而invoke 方法之后的内容就是反向的。

   (3 )afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,该方法也是需要当前对应的Interceptor 的preHandle 方法的返回值为true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。 我们的系统日志的拦截在这个方法中,可以记录日志的相关的参数,检测方法的执行。

如果我们定义了实现HandlerIntercepter接口的类,就可以在我们真正调用Controller之前,调用Controller之后,以及最终我们的Mdoel发送到了页面或者说View完成了呈现之后可以做很多事情。

第五个概念是HandlerMapping。Hanldler是DispatcherServlet调用Controller的一个中间过渡对象。mapping则是前端控制器DispatcherServlet与各个控制器之间的映射。所以,HandlerMapping的第一个作用就是,当一个请求到达前端控制器DispatcherServlet时,告诉前端控制器DispatcherServlet这个请求应该由哪个控制器来响应。

HandlerMapping的第二个作用是,用HandlerIntercepter来包裹Controller。

在HandlerMapping执行完之后,它会给DispatcherServlet一个HandlerAdapter。这个HandlerAdapter里面就包含了(1)某个具体的Controller的实例以及(2)这个Controller需要被包裹的HandlerIntercepter。它们会构成一个执行的链条往下走。

第六个概念是HandlerExecutionChain。前面我们说了,HandlerMapping执行完之后返回的HandlerAdapter中包含了Controller和HandlerIntercepter,它们之间构成了一个执行链条。首选,要执行的是所有HandlerIntercepter里面的preHandle,然后再调用Controller里面的某个业务方法,之后执行HandlerIntercepter里面的postHandle,最后是afterCompletion。

 

这里,我插一句。这个看似复杂的机制在springMVC中实现时其实就是利用反射进行实现的。

 

第七个概念是 ModelAndView。它是springMVC中对Model的一种表现形式。当然,springMVC中还有Model类,另外也可以用Java中的Map类来实现Model的功能。如果你在Controller中见过有人用Map、Model这样的类,springMVC都会讲它们统统转换为ModelAndView。因此,这里我们把ModelAndView认为是一个Model的具体表现。

第八个概念是ViewResolver(视图解析器)。它负责告诉DispatcherServlet需要用哪个视图来进行视图的呈现。因此ViewResolver的作用就是根据我们的配置找出那一个视图对象。比如JSTL、JSP等等。

第九个概念是View。负责呈现页面

 

好吧,我们把这些概念串联一起,梳理一下springMVC的基本概念的原理过程:

DispatcherServlet处于核心的地位,它是整个springMVC的MVC实现的桥梁。Controller是springMVC的C;View是用户想看到的东西,即V。访问的过程如下:

Request从浏览器端过来,首选到达DispatcherServlet。因为它是一个servlet,所有Request都可以拦截得到。DispatcherServlet拦截到一个Request之后,它回去找相应的Controller,怎么找呢?通过HandlerMapping。因此,DispatcherServlet就把这个功能代理给了HandlerMapping。HandlerMapping根据自己的配置,这可以用注解来做。通过注解的方式告诉HandlerMapping,那一个Controller是我们要的。因此HandlerMapping可以很容易地找到相应的Controller,对了,还能找到HandlerInterceptor。

HandlerMapping找到了我们的Controller和HandlerInterceptor,把它们形成了我们的HandlerExecutionChain——一个执行链条。就这样,一个Handler或者说HandlerAdapter(一个适配器)返回给我们的DispatcherServlet。接下来,DispatcherServlet将会调用这个返回的一般化的处理器Handler或者HandlerAdapter。

写Controller的目的是什么?当然是生成我们的模型——ModelAndView。ModelAndView为我们的页面呈现提供一些显示的“料”。模型ModelAndView生成之后,被返回给DispatcherServlet。接着需要显示,但DispatcherServlet可不回去自己管显示的事情。这个时候,视图解析器出现了,视图解析器ViewResolver告诉我们哪个视图是用来解析当前这种场景的。因此,DispatcherServlet通过调用ViewResolver的方法返回我们的View对象。 然后,ModelAndView我们模型数据被传递给我们的View,完成了我们的呈现。DispatcherServlet返回给用户,这样用户就可以在浏览器端看到用户界面了。

 

好吧,也许你还是觉得过程好复杂。但是,SpringMVC已经为我们做了许多。DispatcherServlet好重要啊!但是SpringMVC框架已经为我们实现了,我们要做的仅仅是配置一下就可以了。HandlerMapping复杂的映射过程也不需要我们知道,我们只要用注解配置就可以了。Controller,这个还是自己得写点东西吧,springMVC才不知道你的业务逻辑是卖皮鞋,还是卖保险呢。HandlerInterceptor是一个接口,需要就实现相应的接口方法,不需要就不写了,毕竟不是所有的应用场景都需要在Controller的前后做点什么。Handler/HandlerAdapter如此紧密的联系需要你过问吗,springMVC自己搞定。ModelAndView仅仅是个类,用来存存数据,甚至可以用Map相关的类对象来存储,你别说你不会,一个key一个数可以了,springMVC或者说DispatcherServlet会自己把这个Map转换成ModelAndView。最后,视图解析器都是现成的,跟HandlerMapping差不多,你只需要知道是哪一种类型就可以了。

所以总结下来,我们所需要写的仅仅是Controller;HandlerInterceptor根据应用场景可以写也可以不写;ModelAndView不是必需的,可以给也可以不给;View等、HandlerMapping等配置的问题而已。Handler/HandlerAdapter不需要管。所以,我们只须要shixianController,其他配置一下就OK了。

下面这个图是从另外一个角度对上述概念进行了模块划分。我们只需要 注意的是,DispatcherServlet处于核心位置,相当于一个懂得放权的好老板,它只需要调度就可以了。

老板DispatcherServlet对员工HandlerMapping说:“你告诉我须要调哪个Controller啊”

老板DispatcherServlet对员工Handler说:“你让Controller工作吧”

老板DispatcherServlet对员工ViewResolver说:“你告诉我谁是我需要的View啊”

老板DispatcherServlet对员工View说:“你去把数据呈现以下,把页面做出来吧”

。。。 

 

 

好吧好吧,springMVC原理要点回顾完毕之后,还是回到intellj idea的本文示例上吧。

 

我们在com.happyBKs.controller下定义一个类TestController,用@Controller注解标记为一个控制器。我

package com.happyBKs.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Created by happyBKs on 2016/5/24.
 */

@Controller
@RequestMapping("/hello")
public class TestController {

    //localhost:8080/home/mvc或localhost:8080/web应用名称/home/mvc
    @RequestMapping("/world")
    public String helloMVC(){
        return "first";
    }

}

当然,springMVC在搜索控制器的时候需要定义搜索包的范围,所以,我们需要定义一个springMVC的配置文件。而定义springMVC的配置文件之前,需要在中定义好前端控制器DispatcherServlet,以及相应的配置文件路径。

web.xml如下:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!-- DispatcherServlet, Spring MVC的核心 -->
  <servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class> org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- DispatcherServlet对应的上下文配置, 默认为/WEB-INF/$servlet-name$-servlet.xml
     -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/configs/spring/mvc-dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <!-- mvc-dispatcher拦截所有的请求-->
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

注意:虽然springMVC的配置文件(其实是定义的相应的DispatcherServlet的对应的配置文件)是可以通过初始化参数contextConfigLocation来指定的,如果不配置指定,那就按照约定:DispatcherServlet对应的上下文配置, 默认为/WEB-INF/$servlet-name$-servlet.xml

DispatcherServlet对应的上下文配置

/WEB-INF/configs/spring/mvc-dispatcher-servlet.xml
<?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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 本配置文件是工名为mvc-dispatcher的DispatcherServlet使用, 提供其相关的Spring MVC配置 -->

    <!-- 启用Spring基于annotation的DI, 使用户可以在Spring MVC中使用Spring的强大功能。 激活 @Required
        @Autowired,JSR 250's @PostConstruct, @PreDestroy and @Resource 等标注 -->
    <context:annotation-config />

    <!-- DispatcherServlet上下文, 只管理@Controller类型的bean, 忽略其他型的bean, 如@Service -->
    <context:component-scan base-package="com.happyBKs.controller">
        <context:include-filter type="annotation"  expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <!-- HandlerMapping, 无需配置, Spring MVC可以默认启动。 DefaultAnnotationHandlerMapping
        annotation-driven HandlerMapping -->

    <!-- 扩充了注解驱动,可以将请求参数绑定到控制器参数 -->
    <mvc:annotation-driven />

    <!-- 静态资源处理, css, js, imgs -->
    <!--<mvc:resources mapping="/resources/**" location="/resources/" />-->


    <bean
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsps/" />
        <property name="suffix" value=".jsp" />
    </bean>


</beans>

这里注意,该配置文件其实归结起来做了四件事情:

1. 激活一些注解

2. 定义DispatcherServlet上下文,即刚才所说的搜索哪些包

3. 激活springMVC的几个注解

4. 定义请求和视图View资源之间映射

 

接下来,定义视图View,我们在\WEB-INF\jsps\下定义了first.jsp

\WEB-INF\jsps\first.jsp如下:

<html>
<body>
<h2>Hello! I am developing a springMVC project with intellj idea!</h2>
<h2>HappyBKs</h2>
</body>
</html>

最后,我们在idea下配置如何将webapp发布到tomcat上运行:

点击【Run | Edit Configurations...】

点击左上角的绿色加号。选择Tomcat server 的 local

然后配置Server

然后选择选项卡Deployment,配置部署方式

点加号,选择Artifact。

注意,这里我们还可以为应用配置一个请求中的web应用名称,默认是 "/"

如果我们不配置,请求的是localhost:8080/【Controller映射路径】

这里,我们为应用去个名字叫/mvc。一台服务器毕竟一般会部署很多个应用嘛!

请求的url则是localhost:8080/【web应用配置的名称】/【Controller映射路径】,即localhost:8080/mvc/hello/world

好,最好保存,点击运行。

webapp的首页会自动在默认浏览器中打开(用哪个浏览器,idea也可以配置的)。

之后我们请求http://localhost:8080/mvc/hello/world

 

好了,这篇博文虽然是承接springMC笔记系列,但是毕竟时隔一年了,我将springMVC的原理性的东西,尤其是前端控制器等重新整理了一遍。还有便是,算是把在intellj idea下如何配置你的第一个springMVC方法一步一步讲清楚了,用惯了eclipse的idea小白们不妨试试吧。

 

 

 

© 著作权归作者所有

HappyBKs

HappyBKs

粉丝 665
博文 306
码字总数 481268
作品 0
浦东
程序员
私信 提问
加载中

评论(3)

HappyBKs
HappyBKs 博主

引用来自“zplxm”的评论

WEB-INF中的jsp根本不能在浏览器中访问

当然不能
z
zplxm
WEB-INF中的jsp根本不能在浏览器中访问
z
zplxm
7
IntelliJ IDEA 中的 Maven 项目初体验及搭建 Spring MVC 框架

温馨提示:本教程的 GitHub 地址为「intellij-idea-tutorial」,欢迎感兴趣的童鞋、,纠错。 在「详述 IntelliJ IDEA 创建 Maven 项目及设置 java 源目录的方法」一文中,我们已经将 Intell...

qq_35246620
2018/04/23
0
0
springmvc学习笔记(6)-springmvc整合mybatis(IDEA中通过maven构建

springmvc学习笔记(6)-springmvc整合mybatis(IDEA中通过maven构建) 标签: springmvc mybatis [TOC] 本文主要展示如何在intellij IDEA中通过maven构建springmvc+mybatis框架的开发环境。 需求...

brianway
2016/03/10
506
0
Spring Boot系列——5分钟构建一个应用

5分钟构建一个应用?没错!一点没有夸张,甚至不用5分钟就可以快速搭建并启动一个应用。 环境配置 1、JDK版本:Java8 2、IDE版本:Intellij IDEA 2018.1 3、系统:MAC OS 构建步骤 1、创建项...

Jackie_Zheng
2018/08/19
0
0
IntelliJ IDEA 13 + Genymotion 2.3 开发环境搭建

【声明】 本文来自:http://www.cnblogs.com/smyhvae/p/4013535.html 【有修改】 【正文】 【开发环境】 物理机版本:Win 7旗舰版(32位) Java SDK版本:jdk1.8.0_20(32位) Android SDK版...

Lofo
2014/10/26
775
0
关于Spring Boot你不得不知道的事

1 Spring Boot官网[2.1.5 CURRENT GA] 1.1 Pivotal Wiki Pivotal Software, Inc. is a software and services company based in San Francisco and Palo Alto, California, with several ot......

Java架构资源分享
06/15
121
0

没有更多内容

加载失败,请刷新页面

加载更多

vue入门--简单路由配置

本文转载于:专业的前端网站➜vue入门--简单路由配置   在初始化vue init webpack <工程名>时,有一步是询问是否安装vue-router,选择yes,如果没有安装的话,后面需要自己安装。然后在目录...

前端老手
36分钟前
3
0
怎么给视频配音

很多刚开始尝试视频制作的小伙伴,帮助到怎么给制作完成的视频配音,其实给视频配音的方法非常简单,在手机上可以进行制作,下面一起来看看给视频配音的方法吧! 具体步骤如下: 1、首先在手...

白米稀饭2019
46分钟前
3
0
windows批处理bat脚本编写

什么是bat脚本 .bat结尾的文件其实就是windows上的批处理脚本,Windows中的bat文件相当于 Linux中shell编程的.sh脚本,批量执行DOS命令。 其最简单的例子,是逐行书写在命令行中会用到的各种...

孙幼凌
53分钟前
3
0
华为手机翻译功能怎么使用?这三种方法请务必收藏

华为手机翻译功能怎么使用?在我们的生活中会经常遇到翻译问题,许多外语不好的朋友该怎么办呢?华为手机已经为我们解决了这个问题,今天小编就教大家学会使用华为手机中的三种翻译技巧,需要...

翻译小天才
今天
5
0
企业服务软件开发中需要注意的三个问题

在开发企业服务软件时,我们需要分为:业务需求、用户需求、产品需求,三大需求层次,三个层次互相关联,企业服务软件开发首先要服务业务,需要满足业务的需求,再关注用户体验,也就是用户需...

积木创意科技
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部