【SpringMVC】学习总结(一篇就够了)

一、什么是 MVC?

1.1 什么是 MVC?

  • MVC 是模型(Model)、视图(View)和控制器(Controller)的简写,是一款软件设计规范
  • 将业务的逻辑、数据、展示分离的方法来组织代码的
  • MVC 主要作用降低了视图与业务逻辑间的相互耦合
  • MVC 不是一种设计模式,是一种架构模式。不同的 MVC 存在有差异

1.2 Model、View、Controller

  1. Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可认为是领域模型或者是 JavaBean 的组件。一般是分开来写的,包括 Value Object(数据DAO)和 服务层(行为 Service)。可以说是模型提供了模型数据查询和模型数据状态更新等功能,包括数据和业务。
  2. View(视图):负责进行模型的展示,一般就是看到的用户界面,客户想看到的东西。
  3. Controller(控制器):接受用户请求,委托给模型进行处理(状态改变),处理完毕之后把返回的数据返回给视图,由视图进行展示,可以说 Controller 是做了中间调度的动作。

最典型的 MVC 模式是 JSP + servlet + javabean 的模式。
在这里插入图片描述
在这里插入图片描述

1.3 MVC 架构要做哪些事?

  1. 将 url 映射到 Java 类或者 Java 类的方法
  2. 封装用户提交的数据
  3. 处理请求–调用业务相关处理–封装响应数据
  4. 将响应的数据进行渲染成 html 表示层的数据

1.4 基于 Servlet 的 MVC 流程模型

在这里插入图片描述

二、什么是 Spring MVC?

2.1 概述:

Spring MVC 是Spring Framework 的一部分,是基于 Java 实现的 MVC 轻量级的 Web 框架。
官方生肉:
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#spring-web
翻译版本:(翻译版本是4.2.4的)(https://www.w3cschool.cn/spring_mvc_documentation_linesh_translation/spring_mvc_documentation_linesh_translation-dgcm27r3.html)
https://www.w3cschool.cn/spring_mvc_documentation_linesh_translation/spring_mvc_documentation_linesh_translation-dgcm27r3.html

2.2 Spring MVC 有什么特点?为什么要学?

  1. 轻量级,简单易学
  2. 高效,基于请求响应的 MVC 框架
  3. 与 Spring 兼容性好,可以做到无缝结合
  4. 约定优于配置( SpringBoot 也是)
  5. 功能强大:RESTFUL(一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务接口的场景,实现第三方OTT调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源)、数据验证、格式化、本地化、主题等
  6. 简洁灵活

Spring 的 Web 框架围绕 DispatcherServlet(调度 Servlet)设计。

DispatcherServlet 的作用就是讲请求分发到不同的处理器。Spring 2.5 开始,使用 Java 5 以上版本可以基于注解开发,十分简洁

最重要的是:公司用的多

2.3 中心控制器

上面说到,Spring 的 Web 框架围绕 DispatcherServlet(调度 Servlet)设计。DispatcherServlet 的作用就是讲请求分发到不同的处理器。现在基本采用基于注解的 Controller 声明方式。

Spring MVC 框架像许多其他的 MVC 框架一样,以请求为驱动,围绕一个中心 Servlet 分派请求及提供其他的功能,DispatcherServlet 是一个实际的 Servlet(继承Http Servlet)

关于HttpServlet介绍可以看大神的总结 https://blog.csdn.net/qq_41007534/article/details/99696559
在这里插入图片描述

2.3 Spring MVC 原理

Spring MVC 框架是高度可配置的,包括多种视图技术,例如JSP技术、Velocity、Tiles、iText和POI。SpringMVC框架并不关心使用的视图技术,也不会强迫开发者只使用JSP技术,但是这里只讨论JSP。

SpringMVC框架主要由DispatcherServlet、处理器映射、控制器、视图解析器、视图组成。其工作原理如下图所示:
在这里插入图片描述
在这里插入图片描述

2.4 Spring MVC 执行原理

中文图片便于理解:
在这里插入图片描述
完整图
![在这里插入图片描述](https://img-blog.csdnimg.cn/b9b44b861e5449bfb4d04a4208aad8ac.png
在这里插入图片描述
基于完整图:实线代表的是 Spring 提供的技术,不需要开发者进行实现,虚线是需要开发者进行实现的。

简单分析执行流程:

  • DispatcherServlet 表示的是前端控制器,是整个 Spring MVC 的控制中心。用户发出请求,DispatcherServlet 接受请求并拦截请求。
    假设请求的 url 为:http://localhost:8080/Spring/hello
    上面的 url 可以分为三部分:
    • http://localhost:8080 服务器域名
    • Spring 部署在服务器上的站点
    • hello 控制器
      可以得出,url 表示为:请求位于服务器 localhost:8080 上的 Spring 站点的 hello 控制器
  1. HandlerMapping 为处理器映射。DispatcherServlet 调用 HandlerMapping,HandlerMapping 根据请求的 url 查找 Handler。
  2. HandlerExecution 表示具体的 Handler ,主要作用是根据 url 查找控制器,如上的 url 查找的控制器为 hello
  3. HandlerExecution 讲解析后的信息传递给 DispatcherServlet,如解析控制器映射等。
  4. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
  5. Handler让具体的Controller执行。
  6. Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
  7. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
  8. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
  9. 视图解析器将解析的逻辑视图名传给DispatcherServlet。
  10. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
  11. 最终视图呈现给用户。

三、RestFul 和控制器

3.1 什么是控制器(Controller)?

  • 控制器复杂访问应用程序的行为,通常通过接口定义或者注解定义两种方法实现。
  • 控制器负责解析用户的请求并将其转换为一个模型。
  • 在 Spring MVC 中一个控制器可以包含多个方法
  • 在 Spring MVC 中,对于控制器的配置有很多种

3.2 实现 Controller 接口

Controller 是一个接口,在 org.springframework.web.servlet.mvc 包下,接口只有一个方法:

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

3.3 MVC 程序:

  1. 新建一个 Moudle

  2. 添加框架支持,选Web
    在这里插入图片描述

  3. 确定导入 MVC 的依赖
    在这里插入图片描述

  4. 配置 web.xml ,注册 DispatcherServlet(已经自动注册好)

  5. 配置 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--添加处理映射器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <!--添加处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    <!--视图解析器:DispatcherServlet给他的ModelAndView-->
    <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. 编写操作业务 Controller ,实现Controller 接口,增加注解,需要返回一个 ModelAndView ,装数据,装视图
public class HellowController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView mv = new ModelAndView();
        //封装对象,放在ModelAndView中。Model
        mv.addObject("msg","HelloSpringMVC!");
        //封装要跳转的视图,放在ModelAndView中
        mv.setViewName("/hello"); //: /WEB-INF/jsp/hello.jsp
        return mv;
    }
}

  1. 配置Tomcat
    关于如何在IDEA配置请参考:配置Tomcat
  2. 将自己的类交给SpringIOC 容器,注册 bean
<bean id="/hello" class="com.si.controller.HellowController"/>

9、写跳转的 jsp 文件,显示 ModelAndView 存放的数据,以及正常的页面

3.4 注解版

  1. 新创建模块,引入Web、SpringMVC
  2. 修改pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>SpringMVC</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>SpringMVC-03</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

</project>
  1. 修改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">

    <!--1.注册servlet-->
    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
        <!-- 启动顺序,数字越小,启动越早 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!--所有请求都会被springmvc拦截 -->
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>
  1. 在 src/main/resources 包下创建 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: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
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="com.si.controller"/>
    <!--Spring MVC不处理静态资源 -->
    <mvc:default-servlet-handler />
    <!--
    支持mvc注解驱动
        在spring中一般采用@RequestMapping注解来完成映射关系
        要想使@RequestMapping注解生效
        必须向上下文中注册DefaultAnnotationHandlerMapping
        和一个AnnotationMethodHandlerAdapter实例
        这两个实例分别在类级别和方法级别处理。
        而annotation-driven配置帮助我们自动完成上述两个实例的注入。
     -->
    <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>

在视图解析器中我们把所有的视图都存放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问。

  1. 在pom.xml文件引入相关的依赖:主要有Spring框架核心库、Spring MVC、servlet , JSTL等。我们在父依赖中已经引入了
  2. 创建 Controller
package com.si.controller;

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

@Controller
@RequestMapping("/HelloController")
public class HelloController {
    //真实访问地址:项目名/HelloController/hello
    @RequestMapping("/hello")
    public String sayHello(Model model){
        model.addAttribute("msg","HelloController");
        return "hello";
    }
}

@Controller是为了让Spring IOC容器初始化时自动扫描到;

@RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;

方法中声明Model类型的参数是为了把Action中的数据带到视图中;

方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp。

  1. 创建视图层,在WEB-INF/jsp 目录中创建 hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>hello</title>
</head>
<body>
    <h1>
        ${msg}
    </h1>
</body>
</html>
  1. 启动tomcat

使用springMVC必须配置三大件:处理器映射器、处理器适配器、视图解析器
一般只需要手动配置视图解析器,另外两个可以通过主机驱动

四、数据处理和跳转

4.1 结果跳转方式

4.1.1 ModelAndView

设置 ModelAndView 对象,根据 view 的名称,和视图解析器跳到指定的页面。

页面:{视图解析器}+ viewName +{视图解析器后缀}

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

对应的 Controller 类

public class ControllerTest1 implements Controller {

   public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
       //返回一个模型视图对象
       ModelAndView mv = new ModelAndView();
       mv.addObject("msg","ControllerTest1");
       mv.setViewName("test");
       return mv;
  }
}

4.1.2 ServletAPI

通过设置 Servlet API ,不需要视图解析器

  1. 通过 HttpSevletResponse 进行输出
  2. 通过 HttpSevletResponse 实现重定向
  3. 通过 HttpSevletResponse 实现转发
package com.si.forward;

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

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
public class Forward {
    @RequestMapping("/result/t1")
    public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
        rsp.getWriter().println("Hello,Spring BY Servlet Api");
    }
    @RequestMapping("/result/t2")
    public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
        rsp.sendRedirect("/index.jsp");
    }
    @RequestMapping("/result/t3")
    public void test3(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
        //转发
        req.setAttribute("msg","/result/t3");
        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp");
    }
}

4.1.3 SPringMVC

通过 SpringMVC 来实现转发和重定向 - 无需视图解析器
测试前:把视图解析器注释掉

@Controller
public class ResultSpringMVC {
   @RequestMapping("/rsm/t1")
   public String test1(){
       //转发
       return "/index.jsp";
  }

   @RequestMapping("/rsm/t2")
   public String test2(){
       //转发二
       return "forward:/index.jsp";
  }

   @RequestMapping("/rsm/t3")
   public String test3(){
       //重定向
       return "redirect:/index.jsp";
  }
}

有视图解析器:

重定向 , 不需要视图解析器 , 本质就是重新请求一个新地方嘛 , 所以注意路径问题.
可以重定向到另外一个请求实现 .

@Controller
public class ResultSpringMVC2 {
   @RequestMapping("/rsm2/t1")
   public String test1(){
       //转发
       return "test";
  }

   @RequestMapping("/rsm2/t2")
   public String test2(){
       //重定向
       return "redirect:/index.jsp";
       //return "redirect:hello.do"; //hello.do为另一个请求/
  }
}

4.2 数据处理

4.2.1 处理提交数据

  1. 提交的域名称和处理方法的参数名一致
    提交数据:http://localhost:9220/hello?name = weiyi
    处理方法:

    @RequestMapping("/hello")
    public String hello(String name){
       System.out.println(name);
       return "hello";
    }
    

    后台输出:weiyi

  2. 提交的域名称和处理方法的参数名不一致
    提交数据:http://localhost:9220/hello?name = weiyi
    处理方法:

    //@RequestParam("username") : username提交的域的名称 .
    @RequestMapping("/hello")
    public String hello(@RequestParam("username") String name){
       System.out.println(name);
       return "hello";
    }
    

    后台输出:weiyi

  3. 提交的是一个对象
    要求提交的表单域和对象的属性名一致 , 参数使用对象即可
    (1)实体类

    public class User {
       private int id;
       private String name;
       private int age;
       //构造
       //get/set
       //tostring()
    }
    

(2)提交数据 : http://localhost:8080/mvc04/user?name=kuangshen&id=1&age=15
(3)处理方法:

	@RequestMapping("/user")
		public String user(User user){
		   System.out.println(user);
		   return "hello";
		}

后台输出 : User { id=1, name=‘kuangshen’, age=15 }

说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。

4.2.2 数据显示传到前端

  1. 通过 ModelAndView
    我们一直就是这样使用的

    public class ControllerTest1 implements Controller {
    
       public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
           //返回一个模型视图对象
           ModelAndView mv = new ModelAndView();
           mv.addObject("msg","ControllerTest1");
           mv.setViewName("test");
           return mv;
      }
    }
    
  2. 第二种 : 通过ModelMap

    @RequestMapping("/hello")
    public String hello(@RequestParam("username") String name, ModelMap model){
       //封装要显示到视图中的数据
       //相当于req.setAttribute("name",name);
       model.addAttribute("name",name);
       System.out.println(name);
       return "hello";
    }
    
  3. 通过 Model

    @RequestMapping("/ct2/hello")
    public String hello(@RequestParam("username") String name, Model model){
       //封装要显示到视图中的数据
       //相当于req.setAttribute("name",name);
       model.addAttribute("msg",name);
       System.out.println(name);
       return "test";
    }
    

三种方法对比:
Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解;
ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;
ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。

四、数据处理和跳转

4.1 结果跳转方式

4.1.1 ModelAndView

设置 ModelAndView 对象,根据 view 的名称,和视图解析器跳到指定的页面。

页面:{视图解析器}+ viewName +{视图解析器后缀}

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

对应的 Controller 类

public class ControllerTest1 implements Controller {

   public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
       //返回一个模型视图对象
       ModelAndView mv = new ModelAndView();
       mv.addObject("msg","ControllerTest1");
       mv.setViewName("test");
       return mv;
  }
}

4.1.2 ServletAPI

通过设置 Servlet API ,不需要视图解析器

  1. 通过 HttpSevletResponse 进行输出
  2. 通过 HttpSevletResponse 实现重定向
  3. 通过 HttpSevletResponse 实现转发
package com.si.forward;

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

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
public class Forward {
    @RequestMapping("/result/t1")
    public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
        rsp.getWriter().println("Hello,Spring BY Servlet Api");
    }
    @RequestMapping("/result/t2")
    public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
        rsp.sendRedirect("/index.jsp");
    }
    @RequestMapping("/result/t3")
    public void test3(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
        //转发
        req.setAttribute("msg","/result/t3");
        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp");
    }
}

4.1.3 SPringMVC

通过 SpringMVC 来实现转发和重定向 - 无需视图解析器
测试前:把视图解析器注释掉

@Controller
public class ResultSpringMVC {
   @RequestMapping("/rsm/t1")
   public String test1(){
       //转发
       return "/index.jsp";
  }

   @RequestMapping("/rsm/t2")
   public String test2(){
       //转发二
       return "forward:/index.jsp";
  }

   @RequestMapping("/rsm/t3")
   public String test3(){
       //重定向
       return "redirect:/index.jsp";
  }
}

有视图解析器:

重定向 , 不需要视图解析器 , 本质就是重新请求一个新地方嘛 , 所以注意路径问题.
可以重定向到另外一个请求实现 .

@Controller
public class ResultSpringMVC2 {
   @RequestMapping("/rsm2/t1")
   public String test1(){
       //转发
       return "test";
  }

   @RequestMapping("/rsm2/t2")
   public String test2(){
       //重定向
       return "redirect:/index.jsp";
       //return "redirect:hello.do"; //hello.do为另一个请求/
  }
}

4.2 数据处理

4.2.1 处理提交数据

  1. 提交的域名称和处理方法的参数名一致
    提交数据:http://localhost:9220/hello?name = weiyi
    处理方法:

    @RequestMapping("/hello")
    public String hello(String name){
       System.out.println(name);
       return "hello";
    }
    

    后台输出:weiyi

  2. 提交的域名称和处理方法的参数名不一致
    提交数据:http://localhost:9220/hello?name = weiyi
    处理方法:

    //@RequestParam("username") : username提交的域的名称 .
    @RequestMapping("/hello")
    public String hello(@RequestParam("username") String name){
       System.out.println(name);
       return "hello";
    }
    

    后台输出:weiyi

  3. 提交的是一个对象
    要求提交的表单域和对象的属性名一致 , 参数使用对象即可
    (1)实体类

    public class User {
       private int id;
       private String name;
       private int age;
       //构造
       //get/set
       //tostring()
    }
    

(2)提交数据 : http://localhost:8080/mvc04/user?name=kuangshen&id=1&age=15
(3)处理方法:

	@RequestMapping("/user")
		public String user(User user){
		   System.out.println(user);
		   return "hello";
		}

后台输出 : User { id=1, name=‘kuangshen’, age=15 }

说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。

4.2.2 数据显示传到前端

  1. 通过 ModelAndView
    我们一直就是这样使用的

    public class ControllerTest1 implements Controller {
    
       public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
           //返回一个模型视图对象
           ModelAndView mv = new ModelAndView();
           mv.addObject("msg","ControllerTest1");
           mv.setViewName("test");
           return mv;
      }
    }
    
  2. 第二种 : 通过ModelMap

    @RequestMapping("/hello")
    public String hello(@RequestParam("username") String name, ModelMap model){
       //封装要显示到视图中的数据
       //相当于req.setAttribute("name",name);
       model.addAttribute("name",name);
       System.out.println(name);
       return "hello";
    }
    
  3. 通过 Model

    @RequestMapping("/ct2/hello")
    public String hello(@RequestParam("username") String name, Model model){
       //封装要显示到视图中的数据
       //相当于req.setAttribute("name",name);
       model.addAttribute("msg",name);
       System.out.println(name);
       return "test";
    }
    

三种方法对比:
Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解;
ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;
ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。

五、整合 SSM 框架

前言:需要会 Spring、SpringMVC、Mybatis,以及简单的前端知识

5.1 搭建数据库环境

传建数据库表:(本人使用的是 Navicat)

CREATE DATABASE `ssmbuild`;

USE `ssmbuild`;

DROP TABLE IF EXISTS `books`;

CREATE TABLE `books` (
                         `bookID` INT(10) NOT NULL AUTO_INCREMENT COMMENT '书id',
                         `bookName` VARCHAR(100) NOT NULL COMMENT '书名',
                         `bookCounts` INT(11) NOT NULL COMMENT '数量',
                         `detail` VARCHAR(200) NOT NULL COMMENT '描述',
                         KEY `bookID` (`bookID`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT  INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)VALUES
(1,'Java',1,'从入门到放弃'),
(2,'MySQL',10,'从删库到跑路'),
(3,'Linux',5,'从进门到进牢');

在这里插入图片描述
IDEA 连接数据库:
在这里插入图片描述

5.2 基本环境搭建

  1. 新建一个 Maven 项目(ssmbuild),添加 web 支持
  2. 导入pom依赖
<dependencies>
   <!--Junit-->
   <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.12</version>
   </dependency>
   <!--数据库驱动-->
   <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
       <version>5.1.47</version>
   </dependency>
   <!-- 数据库连接池 -->
   <dependency>
       <groupId>com.mchange</groupId>
       <artifactId>c3p0</artifactId>
       <version>0.9.5.2</version>
   </dependency>

   <!--Servlet - JSP -->
   <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>servlet-api</artifactId>
       <version>2.5</version>
   </dependency>
   <dependency>
       <groupId>javax.servlet.jsp</groupId>
       <artifactId>jsp-api</artifactId>
       <version>2.2</version>
   </dependency>
   <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>jstl</artifactId>
       <version>1.2</version>
   </dependency>

   <!--Mybatis-->
   <dependency>
       <groupId>org.mybatis</groupId>
       <artifactId>mybatis</artifactId>
       <version>3.5.2</version>
   </dependency>
   <dependency>
       <groupId>org.mybatis</groupId>
       <artifactId>mybatis-spring</artifactId>
       <version>2.0.2</version>
   </dependency>

   <!--Spring-->
   <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-webmvc</artifactId>
       <version>5.1.9.RELEASE</version>
   </dependency>
   <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-jdbc</artifactId>
       <version>5.1.9.RELEASE</version>
   </dependency>
</dependencies>
  1. Maven 资源过滤设置
<build>
   <resources>
       <resource>
           <directory>src/main/java</directory>
           <includes>
               <include>**/*.properties</include>
               <include>**/*.xml</include>
           </includes>
           <filtering>false</filtering>
       </resource>
       <resource>
           <directory>src/main/resources</directory>
           <includes>
               <include>**/*.properties</include>
               <include>**/*.xml</include>
           </includes>
           <filtering>false</filtering>
       </resource>
   </resources>
</build>
  1. 构建项目基本架构
  • com.si.pojo
  • com.si.dao
  • com.si.service
  • com.si.controller
  • mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
       PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
       "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

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

</beans>

5.2 Mybatis 层编写

  1. 数据库配置文件 database.properties
# 如果使用mysql 8.0 以上,需要加上时区设置
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
  1. 编写 MyBatis 的核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
       PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
       "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
   <typeAliases>
       <package name="com.si.pojo"/>
   </typeAliases>
   <mappers>
       <mapper resource="com/si/dao/BookMapper.xml"/>
   </mappers>
</configuration>

5.3 编写数据库对应的实体类 com.si.pojo.Books

使用 Lombok 插件

添加插件

<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>

编写实体类

package com.si.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books {
    private int bookID;
    private String bookName;
    private  int bookCounts;
    private  String detail;
}

5.4 编写 Dao 层的 Mapper 接口

package com.si.dao;

import com.si.pojo.Books;
import java.util.List;


public interface BookMapper {
    //增加一个 book
    int add(Books book);

    //根据 ID 删除一个 book
    int deleteBookById(int id);

    //更新 book
    int updateBook(Books book);

    //根据 ID 查询,返回一个 book
    Books queryBookById(int id);

    //查询全部 Book
    List<Books> queryAllBook();
}

5.5 编写对应的 Mapper.xml 文件。需要导入 MyBatis 的包。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.si.dao.BookMapper">

    <!--增加一个Book-->
    <insert id="addBook" parameterType="Books">
        insert into ssmbuild.books(bookName,bookCounts,detail)
        values (#{bookName}, #{bookCounts}, #{detail})
    </insert>

    <!--根据id删除一个Book-->
    <delete id="deleteBookById" parameterType="int">
        delete from ssmbuild.books where bookID=#{bookID}
    </delete>

    <!--更新Book-->
    <update id="updateBook" parameterType="Books">
        update ssmbuild.books
        set bookName = #{bookName},bookCounts = #{bookCounts},detail = #{detail}
        where bookID = #{bookID}
    </update>

    <!--根据id查询,返回一个Book-->
    <select id="queryBookById" resultType="Books">
        select * from ssmbuild.books
        where bookID = #{bookID}
    </select>

    <!--查询全部Book-->
    <select id="queryAllBook" resultType="Books">
        SELECT * from ssmbuild.books
    </select>

</mapper>

5.6 编写 Service 接口 和 实现类

接口:

package com.si.service;

import com.si.pojo.Books;

import java.util.List;

public interface BookService {
    //增加一个 book
    int addBook(Books book);

    //根据 ID 删除一个 book
    int deleteBookById(int id);

    //更新 book
    int updateBook(Books book);

    //根据 ID 查询,返回一个 book
    Books queryBookById(int id);

    //查询全部 Book
    List<Books> queryAllBook();
}

实现类:

package com.si.service;

import com.si.dao.BookMapper;
import com.si.pojo.Books;
import java.util.List;

public class BookServiceImpl implements BookService{
    //调用dao层的操作,设置一个set接口,方便Spring管理
    private BookMapper bookMapper;

    public BookMapper getBookMapper() {
        return bookMapper;
    }

    public void setBookMapper(BookMapper bookMapper) {
        this.bookMapper = bookMapper;
    }

    @Override
    public int addBook(Books book) {
        return bookMapper.addBook(book);
    }

    @Override
    public int deleteBookById(int id) {
        return bookMapper.deleteBookById(id);
    }

    @Override
    public int updateBook(Books book) {
        return bookMapper.updateBook(book);
    }

    @Override
    public Books queryBookById(int id) {
        return bookMapper.queryBookById(id);
    }

    @Override
    public List<Books> queryAllBook() {
        return bookMapper.queryAllBook();
    }
}

到这里,底层需求操作编写完毕

5.7 Spring 层

  1. 配置Spring整合MyBatis,我们这里数据源使用c3p0连接池;
  2. 编写 Spring 整合 MyBatis 的相关配置文件:spring-dao.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">

   <!-- 配置整合mybatis -->
   <!-- 1.关联数据库文件 -->
   <context:property-placeholder location="classpath:database.properties"/>

   <!-- 2.数据库连接池 -->
   <!--数据库连接池
       dbcp 半自动化操作 不能自动连接
       c3p0 自动化操作(自动的加载配置文件 并且设置到对象里面)
   -->
   <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
       <!-- 配置连接池属性 -->
       <property name="driverClass" value="${jdbc.driver}"/>
       <property name="jdbcUrl" value="${jdbc.url}"/>
       <property name="user" value="${jdbc.username}"/>
       <property name="password" value="${jdbc.password}"/>

       <!-- c3p0连接池的私有属性 -->
       <property name="maxPoolSize" value="30"/>
       <property name="minPoolSize" value="10"/>
       <!-- 关闭连接后不自动commit -->
       <property name="autoCommitOnClose" value="false"/>
       <!-- 获取连接超时时间 -->
       <property name="checkoutTimeout" value="10000"/>
       <!-- 当获取连接失败重试次数 -->
       <property name="acquireRetryAttempts" value="2"/>
   </bean>

   <!-- 3.配置SqlSessionFactory对象 -->
   <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
       <!-- 注入数据库连接池 -->
       <property name="dataSource" ref="dataSource"/>
       <!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
       <property name="configLocation" value="classpath:mybatis-config.xml"/>
   </bean>

   <!-- 4.配置扫描Dao接口包,动态实现Dao接口注入到spring容器中 -->
   <!--解释 :https://www.cnblogs.com/jpfss/p/7799806.html-->
   <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
       <!-- 注入sqlSessionFactory -->
       <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
       <!-- 给出需要扫描Dao接口包 -->
       <property name="basePackage" value="com.si.dao"/>
   </bean>

</beans>
  1. Spring整合service层
    关联xml
    在这里插入图片描述
    创建 spring-service.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
   http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 扫描service相关的bean -->
    <context:component-scan base-package="com.si.service" />

    <!--BookServiceImpl注入到IOC容器中-->
    <bean id="BookServiceImpl" class="com.si.service.BookServiceImpl">
        <property name="bookMapper" ref="bookMapper"/>
    </bean>

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource" />
    </bean>

</beans>

5.8 springMVC层

  1. 配置 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-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!--一定要注意:我们这里加载的是总的配置文件,之前被这里坑了!-->
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--encodingFilter-->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>
            org.springframework.web.filter.CharacterEncodingFilter
        </filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--Session过期时间-->
    <session-config>
        <session-timeout>15</session-timeout>
    </session-config>

</web-app>
  1. 创建 spring-mvc.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
   https://www.springframework.org/schema/mvc/spring-mvc.xsd">

   <!-- 配置SpringMVC -->
   <!-- 1.开启SpringMVC注解驱动 -->
   <mvc:annotation-driven />
   <!-- 2.静态资源默认servlet配置-->
   <mvc:default-servlet-handler/>

   <!-- 3.配置jsp 显示ViewResolver视图解析器 -->
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
       <property name="prefix" value="/WEB-INF/jsp/" />
       <property name="suffix" value=".jsp" />
   </bean>

   <!-- 4.扫描web相关的bean -->
   <context:component-scan base-package="com.si.controller" />

</beans>
  1. applicationContext.xml 导入三层架构

在这里插入图片描述
配置文件,暂时结束!Controller 和 视图层编写

5.9 BookController 类编写

  1. BookController 类编写
package com.si.controller;

import com.si.pojo.Books;
import com.si.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
@RequestMapping("/book")
public class BookController {
    //创建 Service 对象
    @Autowired
    @Qualifier("BookServiceImpl")
    private BookService bookService;

    public BookService getBookService() {
        return bookService;
    }

    public void setBookService(BookService bookService) {
        this.bookService = bookService;
    }

    //查询全部书籍
    @RequestMapping("/allBook")
    public String lict(Model model){
        List<Books> books = bookService.queryAllBook();
        model.addAttribute("list",books);
        return "allBook";
    }
}

  1. 编写首页
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2022/5/19
  Time: 18:59
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>首页</title>
  <style type="text/css">
    a{
      text-decoration: none;
      color: black;
      font-size: 18px;
    }
    h3 {
      width: 180px;
      height: 38px;
      margin: 100px auto;
      text-align: center;
      line-height: 38px;
      background: deepskyblue;
      border-radius: 4px;
    }
  </style>
</head>
<body>
<h3>
  <a href="${pageContext.request.contextPath}/book/allBook">点击进入列表页</a>
</h3>

</body>
</html>


  1. 写 allBook 页
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>书籍列表</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 引入 Bootstrap -->
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <div class="col-md-12 column">
            <div class="page-header">
                <h1>
                    <small>书籍列表 —— 显示所有书籍</small>
                </h1>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-4 column">
            <a class="btn btn-primary" href="${pageContext.request.contextPath}/book/toAddBook">新增</a>
        </div>
    </div>

    <div class="row clearfix">
        <div class="col-md-12 column">
            <table class="table table-hover table-striped">
                <thead>
                <tr>
                    <th>书籍编号</th>
                    <th>书籍名字</th>
                    <th>书籍数量</th>
                    <th>书籍详情</th>
                    <th>操作</th>
                </tr>
                </thead>

                <tbody>
                <c:forEach var="book" items="${requestScope.get('list')}">
                    <tr>
                        <td>${book.getBookID()}</td>
                        <td>${book.getBookName()}</td>
                        <td>${book.getBookCounts()}</td>
                        <td>${book.getDetail()}</td>
                        <td>
                            <a href="${pageContext.request.contextPath}/book/toUpdateBook?id=${book.getBookID()}">更改</a> |
                            <a href="${pageContext.request.contextPath}/book/del/${book.getBookID()}">删除</a>
                        </td>
                    </tr>
                </c:forEach>
                </tbody>
            </table>
        </div>
    </div>
</body>
</html>

  1. addBook 页
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>
<head>
    <title>新增书籍</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 引入 Bootstrap -->
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">

    <div class="row clearfix">
        <div class="col-md-12 column">
            <div class="page-header">
                <h1>
                    <small>新增书籍</small>
                </h1>
            </div>
        </div>
    </div>
    <form action="${pageContext.request.contextPath}/book/addBook" method="post">
        书籍名称:<input type="text" name="bookName"><br><br><br>
        书籍数量:<input type="text" name="bookCounts"><br><br><br>
        书籍详情:<input type="text" name="detail"><br><br><br>
        <input type="submit" value="添加">
    </form>

</div>

  1. updateBook 页
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>修改信息</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 引入 Bootstrap -->
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">

    <div class="row clearfix">
        <div class="col-md-12 column">
            <div class="page-header">
                <h1>
                    <small>修改信息</small>
                </h1>
            </div>
        </div>
    </div>

    <form action="${pageContext.request.contextPath}/book/updateBook" method="post">
        <input type="hidden" name="bookID" value="${book.getBookID()}"/>
        书籍名称:<input type="text" name="bookName" value="${book.getBookName()}"/>
        书籍数量:<input type="text" name="bookCounts" value="${book.getBookCounts()}"/>
        书籍详情:<input type="text" name="detail" value="${book.getDetail() }"/>
        <input type="submit" value="提交"/>
    </form>

</div>

5.10 配置 tomcat

5.11 测试

在这里插入图片描述
在这里插入图片描述
成功了 中间找 Bug 找了好久,真的是刚上手不容易啊 现在想一下 似乎也不是那么难了

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值