SpringMVC

先回顾一下什么是MVC

1. 什么MVC?

MVC是模型(model)、视图(view)、控制器(controller)的简写,是一种软件设计规范, 1、Model(模型)表示应用程序核心(比如数据库记录列表)。
2、View(视图)显示数据(数据库记录)。
3、Controller(控制器)处理输入(写入数据库记录)。

  • mvc是将业务逻辑、数据、显示分离的方法来组织代码。
  • mvc主要的作用是降低了视图与业务逻辑之间的双向耦合
  • MVC不是一种设计模式而是一种架构模式。

最典型的例子就是JSP+servlet+javabean

2.SpringMVC简述

spring MVC是Spring Framework的一部分,设计用java写的一个轻量级别的Web框架。

SpringMVC的特点:
  1. 轻量级,简单易学
  2. 高效,基于请求响应的MVC框架
  3. 与spring兼容性好,无缝结合
  4. 约定大于配置
  5. 功能强大: RESTful、数据验证、格式化、本地化、主题
  6. 简介灵活。

SpringMVC原理

先展示一下我画的图,有点丑

DispatcherServlet表示前端控制器
HandleMapping为处理器映射器。
HandlerExecution为具体的处理器
HandlerAdapter为处理器适配器
ViewResolver为视图解析器

  1. 用户发出一个请求,假设这个url为http://localhost:8080/hello
  2. DispatcherServlet调用HandlerMapping,HandlerMapping根据请求来查找Handler
  3. HandlerExecution就是具体的Handler,就是根据url找到控制器,现在找到控制器是hello
  4. HandlerExecution将解析后的信息传递给DispatcherServlet.
  5. 通过hello就通过HandlerAdapter处理器适配器,按照其规则去执行Handler
  6. Handler让具体的Controller来执行,这就就是执行具体的业务啥的,
  7. 然后Controller又将具体的执行信息返回给HandlerAdapter,例如ModelAndView
  8. HandlerAdapter又将视图逻辑名或者模型传给DispatchServlet。
  9. DispatchServlet这里就调用视图解析器ViewResolver来解析HandlerAdapter传递的逻辑视图名
  10. DispatchServlet根据视图解析器的视图结果,调用具体的视图。
  11. 最终视图呈现给用户。

写一个Hello World

其实上面啥原理是很难的,看不懂话,就先来看看怎么写一个Hello World吧

工具&环境
maven 3.6.1
jdk 1.8
tomcat 7.0
idea 2019.3.1

  1. 创建一个maven项目。(不导入任何模板)
  2. 添加必要依赖pom.xml

    <dependencies>
     <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version>5.2.0.RELEASE</version>
     </dependency>
     <!-- https://mvnrepository.com/artifact/junit/junit -->
     <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.12</version>
         <scope>test</scope>
     </dependency>
     <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
     <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>javax.servlet-api</artifactId>
         <version>3.1.0</version>
         <scope>provided</scope>
     </dependency>
         <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
         <dependency>
             <groupId>javax.servlet.jsp</groupId>
             <artifactId>jsp-api</artifactId>
             <version>2.2</version>
             <scope>provided</scope>
         </dependency>
    
     <!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
     <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>jstl</artifactId>
         <version>1.2</version>
     </dependency>
    
         <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-web</artifactId>
             <version>5.2.0.RELEASE</version>
         </dependency>
         <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-webmvc</artifactId>
             <version>5.2.0.RELEASE</version>
         </dependency>
     </dependencies>
    
  3. 新建一个子项目,具体就是在当前的的项目上new->Model->maven

  4. 子项目添加web模板,如图

  5. 编写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">
     <!-- 第一部就是配置前端控制器 DispatcherServlet 这个是SpringMVC的核心-->
     <servlet>
         <servlet-name>spirngmvc</servlet-name>
         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
         <!--  DispatchServlet还要绑定一个配置文件-->
         <init-param>
             <param-name>contextConfigLocation</param-name>
             <param-value>classpath:springmvc-servlet.xml</param-value>
         </init-param>
         <!-- 设置启动级别为1,与服务是一起启动的 -->
         <load-on-startup>1</load-on-startup>
     </servlet>
     <!--    在Springmvc中 /和/* 是不同的两个
      1、/的意思是匹配所有的请求。但是不包括jsp
      2、/*的意思是匹配所有的请求,包括jsp。(可能会导致无穷的嵌套)
     -->
     <servlet-mapping>
         <servlet-name>spirngmvc</servlet-name>
         <url-pattern>/</url-pattern>
     </servlet-mapping>
    </web-app>
    
  6. 新建一个springmvc-servlet.xml
    这个文件放在resource目录下面比较好
<?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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://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="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
        <!--处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
        <!--视图解释器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
    <bean id="/hello" class="com.liliya.controller.HelloController"/>
</beans>
  1. 在主目录下编写HelloController这个类
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

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

public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView modelAndView = new ModelAndView("test");
        modelAndView.addObject("msg","Hello World!!!");
        return modelAndView;
    }
}
  1. 最后再编写一个jsp就可以运行了
    在上面的springmvc-servlet中我们配置了视图解释器的前缀
    所以这里要这样操作,在WEB-INF文件夹下面新建jsp文件夹
    新建test.jsp 在body里面写上${msg}

  2. 配置tomcat,部署项目。

  3. 运行,idea自动打开浏览器,然后在浏览器的后缀加上hello就可以看到效果了

注解

上面的例子可以初步的了解springmvc原理,但是实际的用的时候我们并不是这么用的,
因为,注解才是springmvc的灵魂、

下面写一些如何使用注解来完成HelloWorld项目

  1. 创建maven项目
  2. 导入各种依赖
  3. 配置web.xml,还是一样的不用改
  4. 配置springmvc-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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--    开启自动包扫描-->
    <context:component-scan base-package="com.liliya.controller"/>
<!--    过滤静态文件,不让他们通过这个mvc-->
    <mvc:default-servlet-handler/>
    <mvc:annotation-driven/>

    <!--视图解释器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>
  1. 编写测试类
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String hello(Model model){
        model.addAttribute("msg","HELLO WORLD");
        return "hello"; //被视图解释器处理为/WEB-INF/jsp/hello.jsp
    }
}

  1. 部署到tomcat
  2. 运行,到浏览器查看渲染效果

可以看到注解是简单了很多的。几乎无需配置。

404排查

有时候你可能会发现,没有任何错误,URL没有写错。
但是就是报了404

解决方案是在out这个输出文件夹中新建一个文件夹lib,然后把所有的jar包丢进去。


一个好奇的人