springmvc-入门

spring mvc 简介

springMVC是一种很流行的web层mvc框架。通过把Model,View,Controller分离,把较为复杂的web应用分成逻辑清晰的几部分,是为了简化开发,减少出错。spring mvc 是spring的一个子框架,拥有spring的特性,比如 依赖注入。

Hello mvc

依赖:

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>RELEASE</version>
        </dependency>

        <!--增加对jsp的支持-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
        </dependency>
    </dependencies>

准备一个 Controller,即一个处理浏览器请求的接口,用于处理请求

public class Mycontroller implements Controller {

    /**
     * 这个请求 用来处理请求
     *
     * @param request  前端发来的请求
     * @param response 给前端的的响应
     * @return 返回一个数据模型视图  数据模型 + 视图
     * @throws Exception
     */
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView mv = new ModelAndView("hello"); // 视图的名字
        mv.addObject("name", "lang"); // 数据
        return mv;
    }
}

创建一个视图 这里我们采用jsp作为视图。文件名字为 hello.jsp ,名字要与controller里的一致 :

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
Hello ${name}!
</body>
</html>

现在的问题是,前端发送这个请求 ,我们后端怎样才可以执行这个方法,给前端返回视图呢?

配置mvc

1) resources 目录下,创建一个名为 spring-servlet.xml 的 springmvc 的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--首先在spring中注册controller实例-->
    <bean class="org.lang.controller.Mycontroller" name="/hello"/>

    <!--配置一个处理器映射器。用于映射请求与controller的关系。 处理器映射器有很多,这里使用最简单的-->
    <!--这个是根据bean的名字跟bean作映射的,上面的 Mycontroller 已经跟 /hello 作了映射关系-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" id="handlerMapping">
        <property name="beanName" value="/hello"/>
    </bean>

    <!--处理器适配器 这里也是用最简单的-->
    <!--作用:可以理解为 负责执行相对应的controller 方法-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" id="handlerAdapter"/>

    <!--视图解析器-->
    <!--作用: 创建视图的时候,根据视图解析器配置的内容去找视图-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver">
        <property name="prefix" value="/jsp/"/> <!--配置前缀 我这里放在webapp里面,它默认也会去webapp里面找-->
        <property name="suffix" value=".jsp"/> <!--配置后缀-->
    </bean>
</beans>

  1. 加载 springmvc 配置文件 在 web 项目启动时,加载 springmvc 配置文件,这个配置是在 web.xml 中完成的。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--把spring-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:spring-servlet.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
  1. 最后 部署tomcat上 就可以运行了
    在这里插入图片描述

Spring mvc 工作流程

在这里插入图片描述
1.DispatcherServlet:前端控制器

用户请求到达前端控制器,它就相当于 mvc 模式中的c,DispatcherServlet 是整个流程控制的中心,相当于是 SpringMVC 的大脑,由它调用其它组件处理用户的请求,DispatcherServlet 的存在降低了组件之间的耦合性。

2.HandlerMapping:处理器映射器

HandlerMapping 负责根据用户请求找到 Handler 即处理器(也就是我们所说的 Controller),SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等,在实际开发中,我们常用的方式是注解方式。

3.Handler:处理器

Handler 是继 DispatcherServlet 前端控制器的后端控制器,在DispatcherServlet 的控制下 Handler 对具体的用户请求进行处理。由于 Handler 涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发 Handler。(这里所说的 Handler 就是指我们的 Controller)

4.HandlAdapter:处理器适配器

通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。

5.ViewResolver:视图解析器

ViewResolver 负责将处理结果生成 View 视图,ViewResolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。 SpringMVC 框架提供了很多的 View 视图类型,包括:jstlView、freemarkerView、pdfView 等。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。

spring + springmvc 分开配置

在前面 只配置了springmvc的配置,没有配置spring 的配置
这里新建一个类 HelloService:

@Service
public class HelloService {
    public String hello(String name) {
        return "Hello" + name;
    }
}

默认情况下 是spring不会扫描这个类 需要自己配置 在 resource 目录下 新建 spring 的配置文件,applicationContext.xml ,这个文件用来扫描除了@Controller 的其他注解

applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--如果 use-default-filters = true 就是默认把所有组件都扫描了,比如 @service @component等。但是这里我们不需要扫描@controller 因为在@controller 在springmvc中配置的-->
    <context:component-scan base-package="com.java.lang" use-default-filters="true">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <!--排除 @controller 这个注解-->
    </context:component-scan>
</beans>

随后在web.xml中加载此配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--加载Spring的配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!--监听器 用于监听状态-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--加载SpringMvc的配置文件-->
    <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-servlet.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

之后在 spring-servlet 中扫描 @Controller :

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--使用注解代替了-->
    <!--    <bean class="com.java.lang.controller.MyController" name="/hello"/>-->

    <context:component-scan base-package="com.java.lang" use-default-filters="false"> <!--什么都不扫 只扫Controller-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" id="mapping">
        <property name="beanName" value="/hello"/>
    </bean>

    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" id="handlerAdapter"/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver">
        <property name="prefix" value="/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

这时候,分工就很明确了

  • applicationContext.xml 扫描的是除了@controller 的注解
  • spring-servlet.xml 扫描的是@controller 的注解

之后在Controller中注入使用:

package com.java.lang.controller;

import com.java.lang.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@org.springframework.stereotype.Controller("/hello")
public class MyController implements Controller {

    /*注入*/
    @Autowired
    private HelloService helloService;

    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView mv = new ModelAndView("hello");
        mv.addObject("name", "Lang");
        System.out.println(helloService.hello("TestHello"));
        return mv;
    }
}

在这里插入图片描述

到这里就完成了spring + springmvc 分开配置 项目地址

两个容器

当 Spring 和 SpringMVC 同时出现,我们的项目中将存在两个容器,一个是 Spring 容器,另一个是 SpringMVC 容器,Spring 容器通过 ContextLoaderListener (applicationContext.xml)来加载,SpringMVC 容器则通过 DispatcherServlet(spring-servler.xml)来加载,这两个容器不一样:
在这里插入图片描述
从图中可以看出:

ContextLoaderListener 初始化的上下文加载的 Bean 是对于整个应用程序共享的,不管是使用什么表现层技术,一般如 DAO 层、Service 层 Bean;
DispatcherServlet 初始化的上下文加载的 Bean 是只对 Spring Web MVC 有效的 Bean,如 Controller、HandlerMapping、HandlerAdapter 等等,该初始化上下文应该只加载 Web相关组件。
为什么不在 Spring 容器中扫描所有 Bean?
这个是不可能的。因为请求达到服务端后,找 DispatcherServlet 去处理,只会去 SpringMVC 容器中找,这就意味着 Controller 必须在 SpringMVC 容器中扫描。

2.为什么不在 SpringMVC 容器中扫描所有 Bean?

这个是可以的,可以在 SpringMVC 容器中扫描所有 Bean。不写在一起,有两个方面的原因:

为了方便配置文件的管理
在 Spring+SpringMVC+Hibernate 组合中,实际上也不支持这种写法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值