SpringMVC

SpringMVC

### 1. 框架的作用

SpringMVC主要解决了控制器如何接收客户端的请求,并将处理结果响应给客户端的问题。

在传统的Java EE开发中,控制器是`Servlet`,主要存在的问题有:
1. 每个`Servlet`都需要在`web.xml`中配置,一个完整的项目可能需要大量代码完成所有`Servlet`的配置,所以,存在配置过多、管理难度大的问题;
2. 由于一个完整的项目中可能有大量的`Servlet`,则项目启动后,会消耗大量的内存去存储这些`Servlet`的对象;
3. 由于一个完整的项目中可能有大量的`Servlet`,在编码时,管理难度也会增加;
4. 原生的Java EE中的API使用并不便利!

### 2. 框架的核心组件

在SpringMVC中,有以下5大核心组件(还有其它组件):

- `DispatcherServlet`:接收请求,并分发给各个控制器
- `HandlerMapping`:处理请求路径与控制器的映射关系
- `ModelAndView`:控制器的处理结果
- `ViewResolver`:处理视图名与具体使用的视图组件的映射关系
- `Controller`:具体处理请求并给出响应结果

SpringMVC图解:

### 3. Spring MVC - Helloworld

**目标**

在浏览器中输出`http://localhost:8080/项目名/hello.do`后,能显示某页面,页面中有`Hello, SpringMVC!`字样。

**创建项目**

创建Maven Project,`Group Id`为`cn.tedu.spring`,`Artifact Id`为`SPRINGMVC-01-HELLO`,`Packaging`为`war`。

然后,生成`web.xml`文件,添加`spring-webmvc`依赖,复制此前项目中的`spring.xml`到当前项目中并清除原有的配置,添加Tomcat运行环境。

**配置DispatcherServlet**

由于希望SpringMVC框架能接收到相关的请求,所以,首先应该对`DispatcherServlet`进行配置:

    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

> 关于DispatcherServlet的包名,可以在任意Java类中声明DispatcherServlet变量,由Eclipse完成导包,则在import语句中就有了该类的包名。

以上配置中,`<url-pattern>`中配置的是`*.do`,表示SpringMVC框架将接收所有以`.do`作为资源名后缀的请求,而并不处理例如`.html`、`.jpg`等请求,如果希望接收并处理所有请求,可以使用`/*`或其它使用了通配符的配置。

为了使得Spring的运行环境是正常的,应该保证在项目部署到Tomcat的第一时间就加载Spring的配置,要实现这样的效果,可以使得:`DispatcherServlet`是默认启动的(配置`<load-on-startup>`节点),并且,它启动时加载Spring的配置文件(`DispatcherServlet`的父类`FrameworkServlet`中有`contextConfigLocation`属性,表示初始化时加载哪个配置文件)!

    <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:spring.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

至此,项目的运行效果为:启动时,会直接初始化`DispatcherServlet`,并且在初始化时,还会自动加载`spring.xml`配置文件。

如果需要检查配置是否成功,可以:使得某个类被Spring管理,且在构造方法中添加输出语句!如果启动项目时可以看到输出语句,则成功!

**接收并处理请求**

在实际开发中,并不会使用专门的配置文件去记录请求路径与处理请求的控制器的映射关系,即:不配置`HandlerMapping`(当然,这并不影响SpringMVC的工作流程,只是从代码上不这样体现而已)。

可以直接创建控制器类,例如`cn.tedu.spring.HelloController`,需要该类在组件扫描范围之内,且应该添加`@Controller`注解,然后,在类中自定义处理请求的方法。

关于处理请求的方法,访问权限应该是`public`,返回值类型暂时使用`String`,方法的名称可以自行定义,参数暂时留空,即不添加任何参数,然后,在方法之前添加`@RequestMapping("路径")`配置请求路径:

    @Controller
    public class HelloController {
        
        // 处理请求的方法
        // 权限:public
        // 返回值:String(暂定)
        // 方法名:自定义
        // 参数列表:无(暂定)
        @RequestMapping("hello.do")
        public String showHello() {
            System.out.println("HelloController.showHello()");
            return null;
        }
    
    }


至此,`hello.do`的请求已经可以被以上自定义的`showHello()`方法处理,在浏览器输出`http://localhost:8080/SPRINGMVC-01-HELLO/hello.do`后,虽然在浏览器中无法正确的显示内容,但是,在Eclipse控制台可以观察到`showHello()`方法已经被正确的调用。

**配置视图解析器**

处理完请求后,方法返回的`String`类型数据表示的就是视图名,例如返回`"helloworld"`,接下来,框架会根据视图名找到视图解析器,从而确定最终的视图组件,典型的视图解析器是`InternalResourceViewResolver`:

<!-- ViewResolver:视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    </bean>


`InternalResourceViewResolver`的工作模式是:将**前缀 + 控制器方法返回的视图名 + 后缀**拼接起来,以项目的`webapp`为根目标,找到对应的页面文件,例如:

    <!-- ViewResolver:视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix"
            value="/WEB-INF/" />
        <!-- 后缀 -->
        <property name="suffix"
            value=".jsp" />
    </bean>

结合此前方法返回的字符串值为`"helloworld"`,则视图解析器会找到`webapp/WEB-INF/helloworld.jsp`文件作为最终显示的视图组件!所以,创建对应的jsp文件,然后重新部署项目运行,即可看到最终运行效果。

原文地址:https://www.cnblogs.com/topzhao/p/10290534.html