SpingMVC学习笔记

目录

1.回顾MVC

1.1 什么是MVC

 1.2 回顾servlet

2.SpringMVC

2.1 什么是SpringMVC

2.1.1 概述

2.1.2 中心控制器

 2.1.3 SpringMVC的执行原理

3.HelloSpringMVC

3.1 配置版

3.2 注解版

3.3小结

4. Controller和RestFul

4.1 Controller(控制器)

4.2 Controller的实现方式

4.3 RequestMapping

4.4 RestFul风格

 5.结果跳转方式

5.1 ModelAndView

5.2 ServletAPI

5.3 SpringMVC

6.数据处理

6.1 提交的域名称和处理方法的参数名一致

 6.2 提交的域名称和处理方法的参数名不一致

 6.3 提交的是一个对象

6.4 数据显示到前端

6.5 乱码问题

7.SSM整合

7.1 环境

7.2 数据库环境

7.3 基本环境搭建

 7.4 Mybatis层编写

7.5 Spring层

7.6 SpringMVC


1.回顾MVC

1.1 什么是MVC

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

Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。

View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。

Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。 也就是说控制器做了个调度员的工作

职责分析:

Controller:控制器

  • 取得表单数据
  • 调用业务逻辑
  • 转向指定的页面

Model:模型

  • 业务逻辑
  • 保存数据的状态

View:视图

  • 显示页面

 1.2 回顾servlet

创建一个Maven工程当做父工程,导入pom依赖

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
    <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>
</dependencies>

建立一个子Maven工程 springMVC-01-servlet 添加web-app支持 

导入servlet 和 jsp 的 jar 依赖

<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>

编写一个servlet用来处理用户的请求

/**
 * @author xiaow
 * @data 2021/11/17
 */
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取前端参数
        String method = req.getParameter("method");
        if ("add".equals(method)) {
            req.getSession().setAttribute("msg", "使用了add方法");
        } else if ("delete".equals(method)) {
            req.getSession().setAttribute("msg", "使用了delete方法");
        }
        // 调用业务层
        // 转发或重定向
        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

编写jsp页面,在WEB-INF目录下新建一个jsp文件夹,并在里面新建一个test.jsp文件

<html>
<head>
    <title>test</title>
    <base href="<%=basePath%>">
</head>
<body>
    ${msg}
</body>
</html>

在web.xml中注册servlet

<?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">
    <!-- 注册servlet -->
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.xiaow.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>

配置Tomcat进行测试

  • localhost:8080/hello?method=add
  • localhost:8080/hello?method=delete

MVC框架要做哪些事情

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

说明:

​ 常见的服务器端MVC框架有:Struts、Spring MVC、ASP.NET MVC、Zend Framework、JSF;常见前端MVC框架:vue、angularjs、react、backbone;由MVC演化出了另外一些模式如:MVP、MVVM 等等….

2.SpringMVC

2.1 什么是SpringMVC

2.1.1 概述

官方文档Web on Servlet Stack

Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架

SpringMVC的特点

  • 轻量级,简单易学
  • 高效 , 基于请求响应的MVC框架
  • 与Spring兼容性好,无缝结合
  • 约定优于配置
  • 功能强大:RESTful、数据验证、格式化、本地化、主题等
  • 简洁灵活

Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计。

DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁;

正因为SpringMVC好 , 简单 , 便捷 , 易学 , 天生和Spring无缝集成(使用SpringIoC和Aop) , 使用约定优于配置 . 能够进行简单的junit测试 . 支持Restful风格 .异常处理 , 本地化 , 国际化 , 数据验证 , 类型转换 , 拦截器 等等……所以我们要学习 

2.1.2 中心控制器

Spring的web框架围绕DispatcherServlet设计。 DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解的controller声明方式。

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

 当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者

 2.1.3 SpringMVC的执行原理

图为SpringMVC的一个较完整的流程图,实线表示SpringMVC框架提供的技术,不需要开发者实现,虚线表示需要开发者实现。

简要分析执行流程

DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。

我们假设请求的url为 : http://localhost:8080/SpringMVC/hello

如上url拆分成三部分:

http://localhost:8080服务器域名

SpringMVC部署在服务器上的web站点

hello表示控制器

通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的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. 最终视图呈现给用户

3.HelloSpringMVC

3.1 配置版

新建一个Moudle springMVC-02-hellomvc 添加web-app支持 导入相关依赖

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

确定配置SpringMVC所需要的依赖后

配置web.xml,注册DispatcherServlet

<?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>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- DispatcherServlet要绑定spring的配置文件 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
    </servlet>

    <!--
    在springMVC中:/ /*
    /  : 会匹配所有的请求,但是不包括jsp
    /* : 不仅会匹配所有的请求,还包括jsp
     -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

编写SpringMVC 的 配置文件!名称:springmvc-servlet.xml : [servletname]-servlet.xml

说明,这里的名称要求是按照官方来的

  1. 添加处理器映射器
  2. 添加处理器适配器
  3. 添加视图解析器
<?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"/>
    <!-- 视图解析器 : 模板引擎 Thymeleaf Freemarker -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

编写我们要操作业务Controller ,要么实现Controller接口,要么增加注解;需要返回一个ModelAndView,装数据,封视图

/**
 * @author xiaow
 * @data 2021/11/18
 */
public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView modelAndView = new ModelAndView();

        // 业务代码
        String msg = "Hello springMvc!";
        modelAndView.addObject("msg", msg);

        // 视图跳转
        modelAndView.setViewName("hello");

        return modelAndView;
    }
}

 将自己的类交给SpringIOC容器,注册bean

    <!-- BeanNameUrlHandlerMapping需要根据bean的id映射 -->
    <bean id="/hello" class="com.xiaow.controller.HelloController"/>

编写需要跳转的jsp页面,显示ModelandView存放的数据,以及我们的正常页面

<html>
<head>
    <title>Title</title>
    <base href="<%=basePath%>">
</head>
<body>
    ${msg}
</body>
</html>

配置Tomcat启动测试

可能遇到的问题:访问出现404,排查步骤:

  1. 查看控制台输出,看一下是不是缺少了什么jar包。
  2. 如果jar包存在,显示无法输出,就在IDEA的项目发布中,添加lib依赖!
  3. 重启Tomcat 即可解决!

小结:用配置实现mvc是为了理解原理,在真实开发中使用注解,这才是SpringMVC的精髓

3.2 注解版

新建一个Moudle,springmvc-03-hello-annotation ,添加web支持

建立包结构:com.xiaow.controller

在pom.xml中引入核心依赖:主要有Spring框架核心库、Spring MVC、servlet , JSTL等

解决项目的资源过滤问题

    <!-- 资源过滤问题 -->
    <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>

配置web.xml

注意点:

  • 注意web.xml版本问题,要最新版!
  • 注册DispatcherServlet
  • 关联SpringMVC的配置文件
  • 启动级别为1
  • 映射路径为 / 【不要用/*,会404】
<?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>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
        <!-- DispatcherServlet要绑定spring的配置文件 -->
        <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中:/ /*
        /  : 会匹配所有的请求,但是不包括jsp
        /* : 不仅会匹配所有的请求,还包括jsp
    -->
    <!--所有请求都会被springmvc拦截 -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

编写springmvc-servlet.xml配置文件

  • 让IOC的注解生效
  • 静态资源过滤 :HTML . JS . CSS . 图片 , 视频 …..
  • MVC的注解驱动
  • 配置视图解析器
    • 在视图解析器中我们把所有的视图都存放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问
<?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">

    <!-- 自动扫描包,让指定包下的注解生效,交给ICO容器统一管理 -->
    <context:component-scan base-package="com.xiaow.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>

创建controller

编写一个java控制类:com.xiaow.controller.HelloController

/**
 * @author xiaow
 * @data 2021/11/20
 */
@Controller
@RequestMapping("/HelloController")
public class HelloController {

    // 真实访问地址:/HelloController/hello
    @RequestMapping("/hello")
    public String helloSpringmvc(Model model) {
        // 向模型中添加属性msg与值,可以在jsp页面取出并渲染
        model.addAttribute("msg", "helloSpringMVC!");
        // WEB-INF/jsp/hello.jsp
        return "hello";
    }

}
  • @Controller是为了让Spring IOC容器初始化时自动扫描到
  • @RequestMapper是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;
  • 方法中声明Model类型的参数是为了把Action中的数据带到视图中;
  • 方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp

创建视图层

  • 在WEB-INF/ jsp目录中创建hello.jsp , 视图可以直接取出并展示从Controller带回的信息
  • 可以通过EL表示取出Model中存放的值,或者对象
<html>
<head>
    <title>springmvc</title>
    <base href="<%=basePath%>">
</head>
<body>
    ${msg}
</body>
</html>

配置Tomcat运行

访问对应的请求链接

 运行成功

3.3小结

实现步骤其实非常的简单:

  1. 新建一个web项目
  2. 导入相关jar包
  3. 编写web.xml , 注册DispatcherServlet
  4. 编写springmvc配置文件
  5. 接下来就是去创建对应的控制类 , controller
  6. 最后完善前端视图和controller之间的对应
  7. 测试运行调试.

使用springMVC必须配置的三大件:

处理器映射器、处理器适配器、视图解析器

通常,我们只需要手动配置视图解析器,而处理器映射器处理器适配器只需要开启注解驱动即可,而省去了大段的xml配置

4. Controller和RestFul

4.1 Controller(控制器)

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

4.2 Controller的实现方式

方式一:实现Controller接口

新建一个Moudle,springmvc-04-controller,将刚才的03 拷贝一份

  • 删掉HelloController
  • mvc的配置文件只留下 视图解析器

编写一个Controller类,ControllerTest1

/**
 * @author xiaow
 * @data 2021/11/20
 */
// 只要实现了Controller接口的类,就说明这是一个控制器
public class ControllerTest1 implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg", "ControllerTest1");
        modelAndView.setViewName("test");
        return modelAndView;
    }
}

编写完毕后,去Spring配置文件中注册请求的bean;name对应请求路径,class对应处理请求的类

    <bean id="/test1" class="com.xiaow.controller.ControllerTest1"/>

编写前端test.jsp,注意在WEB-INF/jsp目录下编写,对应我们的视图解析器

<html>
<head>
    <title>test</title>
    <base href="<%=basePath%>">
</head>
<body>
    ${msg}
</body>
</html>

小结:

  • 实现接口Controller定义控制器是比较古老的方法
  • 缺点是:一个控制器中只有一个方法,如果要多个方法则要定义多个Controller,定义的方式比较麻烦

方式二:使用注解@Controller

  • @Controller注解类型用于声明Spring类的实例是一个控制器(还有另外三种:@Service、@Component)
  • Spring可以使用扫描机制来找到应用程序中所有基于注解的控制器类,为了保证Spring能找到你的控制器,需要在配置文件中声明组件扫描 
  •      <!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 -->
        <context:component-scan base-package="com.xiaow.controller"/>
    wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
  • 增加一个ControllerTest2使用注解实现

  • /**
     * @author xiaow
     * @data 2021/11/20
     */
    //@Controller注解的类会自动添加到Spring上下文中
    @Controller
    public class ControllerTest2 {
        //映射访问路径
        @RequestMapping("test2")
        public String controllerTest2(Model model) {
            //Spring MVC会自动实例化一个Model对象用于向视图中传值
            model.addAttribute("msg", "ControllerTest2");
            // /WEB-INF/jsp/test.jsp
            return "test";
        }
    
    }
  •  运行Tomcat测试  

小结:可以发现,我们的两个请求都可以指向一个视图,但是页面结果的结果是不一样的,从这里可以看出视图是被复用的,而控制器与视图之间是弱偶合关系

4.3 RequestMapping

  •  @RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径
@Controller
public class ControllerTest2 {
    //映射访问路径
    @RequestMapping("/test2")
    public String controllerTest2(Model model) {
        //Spring MVC会自动实例化一个Model对象用于向视图中传值
        model.addAttribute("msg", "ControllerTest2");
        // /WEB-INF/jsp/test.jsp
        return "test";
    }

}

访问路径:localhost:8080/项目名/test2

同时注解类和方法

//@Controller注解的类会自动添加到Spring上下文中
@Controller
@RequestMapping("/ControllerTest2")
public class ControllerTest2 {
    //映射访问路径
    @RequestMapping("/test2")
    public String controllerTest2(Model model) {
        //Spring MVC会自动实例化一个Model对象用于向视图中传值
        model.addAttribute("msg", "ControllerTest2");
        // /WEB-INF/jsp/test.jsp
        return "test";
    }
}

访问路径:localhost:8080 / 项目名 / ControllerTest2 / test2

4.4 RestFul风格

概念
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制

功能
资源:互联网所有的事物都可以被抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
分别对应 添加、 删除、修改、查询

传统方式操作资源 :通过不同的参数来实现不同的效果!方法单一,post 和 get

​ http://127.0.0.1/item/queryItem.action?id=1 查询,GET
​ http://127.0.0.1/item/saveItem.action 新增,POST
​ http://127.0.0.1/item/updateItem.action 更新,POST
​ http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST

使用RESTful操作资源 : 可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!

​ http://127.0.0.1/item/1 查询,GET
​ http://127.0.0.1/item 新增,POST
​ http://127.0.0.1/item 更新,PUT
​ http://127.0.0.1/item/1 删除,DELETE

新建一个RestFulController类

在Spring MVC中可以使用 @PathVariable 注解,让方法参数的值对应绑定到一个URI模板变量上

/**
 * @author xiaow
 * @data 2021/11/20
 */
@Controller
public class RestFulController {
    // 映射访问路径
    @RequestMapping("/add/{a}/{b}")
    public String test1(@PathVariable int a, @PathVariable int b, Model model) {
        int res = a + b;
        //Spring MVC会自动实例化一个Model对象用于向视图中传值
        model.addAttribute("msg", "结果为:" + res);
        //返回视图位置
        return "test";
    }
}

测试请求

  

使用路径变量的好处

  • 使路径变得更加简洁;

  • 获得参数更加方便,框架会自动进行类型转换。

  • 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,如这里访问是的路径是/add/1/a,则路径与方法不匹配,而不会是参数转换失败

   

修改参数类型在测试

/**
 * @author xiaow
 * @data 2021/11/20
 */
@Controller
public class RestFulController {
    // 映射访问路径
    @RequestMapping("/add/{a}/{b}")
    public String test1(@PathVariable int a, @PathVariable String b, Model model) {
        String res = a + b;
        //Spring MVC会自动实例化一个Model对象用于向视图中传值
        model.addAttribute("msg", "结果为:" + res);
        //返回视图位置
        return "test";
    }
}

  

使用method属性指定请求类型

 用于约束请求的类型,可以收窄请求范围。指定请求谓词的类型如GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE等

添加一个方法进行测试

method = RequestMethod.POST

我们使用浏览器地址栏进行访问默认是Get请求,会报错405

  

将 method = RequestMethod.POST改为method = RequestMethod.GET再次测试

    //映射访问路径,必须是POST请求
    @RequestMapping(value = "/test2", method = RequestMethod.GET)
    public String test2(Model model) {
        model.addAttribute("msg", "Post请求");
        return "test";
    }

  

小结:Spring MVC 的 @RequestMapping注解能够处理 HTTP 请求的方法, 比如 GET, PUT, POST, DELETE 以及 PATCH 

所有的地址栏请求默认都会是 HTTP GET 类型的

方法级别的注解变体有如下几个: 组合注解

@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping

@GetMapping是一个组合注解 =  @RequestMapping(method = RequestMethod.GET)

 5.结果跳转方式

5.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类

/**
 * @author xiaow
 * @data 2021/11/20
 */
// 只要实现了Controller接口的类,就说明这是一个控制器
public class ControllerTest1 implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        // 返回一个模型视图对象
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg", "ControllerTest1");
        modelAndView.setViewName("test");
        return modelAndView;
    }
}

5.2 ServletAPI

通过设置ServletAPI , 不需要视图解析器 .

  1. 通过HttpServletResponse进行输出
  2. 通过HttpServletResponse实现重定向
  3. 通过HttpServletResponse实现转发
@Controller
public class ResultGo {
    @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 Exception {
        //转发
        req.setAttribute("msg","/result/t3");
        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,rsp);
    }
}

5.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";
    }
}

通过SpringMVC来实现转发和重定向 - 有视图解析器;

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

可以重定向到另外一个请求实现 

@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为另一个请求/
    }
}

6.数据处理

6.1 提交的域名称和处理方法的参数名一致

提交数据:http://localhost:8080/hello?name=xiaow​​​​​​​​​​​

处理方法

    @GetMapping("/hello")
    public String hello(String name) {
        System.out.println("请求数据name---> " + name);
        return "test";
    }

后台结果

 6.2 提交的域名称和处理方法的参数名不一致

提交数据:http://localhost:8080/hello?username=xiaow

处理方法

    @GetMapping("/hello")
    public String hello(@RequestParam("username") String name, Model model) {
        // 接收前端的参数
        System.out.println("请求数据name---> " + name);
        // 将参数传递给前端 model
        model.addAttribute("msg", name);
        return "test";
    }

后台结果

 6.3 提交的是一个对象

要求提交的表单域和对象的属性名一致 , 参数使用对象即可

编写实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String userName;
    private String passWord;
    private int age;
}

处理方法

    @GetMapping("/user")
    public String user(User user) {
        System.out.println("前端数据---> " + user);
        return "test";
    }

后台结果

注意: 如果使用对象传递,前端传递的参数名和对象属性名一致

6.4 数据显示到前端

第一种:通过ModelAndView

// 只要实现了Controller接口的类,就说明这是一个控制器
public class ControllerTest1 implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        // 返回一个模型视图对象
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg", "ControllerTest1");
        modelAndView.setViewName("test");
        return modelAndView;
    }
}

第二种:通过ModelMap

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

提交数据:http://localhost:8080/hello?username=xiaow

后台结果

第三种:通过Model

    @RequestMapping("/t1")
    public String test1(Model model, @RequestParam("username") String name) {
        // 接收前端的参数
        System.out.println(name);
        // 将参数传递给前端 model
        model.addAttribute("msg", name);
        // 视图跳转
        return "test";
    }

对比区别:

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

6.5 乱码问题

第一种:通过过滤器解决

这里SpringMVC给我们提过了一个过滤器,在web.xml中配置

    <!-- 配置SpringMVC的过滤器解决乱码问题 -->
    <filter>
        <filter-name>encoding</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>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

在极端情况下,这种过滤器对get请求的支持不是很友好,所以第二种解决方案

第二种:修改Tomcat配置文件

设置编码

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" 
			   URLEncoding="UTF-8"
			   relaxedPathChars="|{}[],%" relaxedQueryChars="|{}[],%"/>

第三种:自定义过滤器(搬)

注:这个也是我在网上找的一些大神写的,一般情况下,SpringMVC默认的乱码处理就已经能够很好的解决了!(这句话也是搬的)

package com.kuang.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
 * 解决get和post请求 全部乱码的过滤器
 */
public class GenericEncodingFilter implements Filter {
    @Override
    public void destroy() {
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //处理response的字符编码
        HttpServletResponse myResponse=(HttpServletResponse) response;
        myResponse.setContentType("text/html;charset=UTF-8");
        // 转型为与协议相关对象
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        // 对request包装增强
        HttpServletRequest myrequest = new MyRequest(httpServletRequest);
        chain.doFilter(myrequest, response);
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}
//自定义request对象,HttpServletRequest的包装类
class MyRequest extends HttpServletRequestWrapper {
    private HttpServletRequest request;
    //是否编码的标记
    private boolean hasEncode;
    //定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
    public MyRequest(HttpServletRequest request) {
        super(request);// super必须写
        this.request = request;
    }
    // 对需要增强方法 进行覆盖
    @Override
    public Map getParameterMap() {
        // 先获得请求方式
        String method = request.getMethod();
        if (method.equalsIgnoreCase("post")) {
            // post请求
            try {
                // 处理post乱码
                request.setCharacterEncoding("utf-8");
                return request.getParameterMap();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        } else if (method.equalsIgnoreCase("get")) {
            // get请求
            Map<String, String[]> parameterMap = request.getParameterMap();
            if (!hasEncode) { // 确保get手动编码逻辑只运行一次
                for (String parameterName : parameterMap.keySet()) {
                    String[] values = parameterMap.get(parameterName);
                    if (values != null) {
                        for (int i = 0; i < values.length; i++) {
                            try {
                                // 处理get乱码
                                values[i] = new String(values[i]
                                        .getBytes("ISO-8859-1"), "utf-8");
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                hasEncode = true;
            }
            return parameterMap;
        }
        return super.getParameterMap();
    }
    //取一个值
    @Override
    public String getParameter(String name) {
        Map<String, String[]> parameterMap = getParameterMap();
        String[] values = parameterMap.get(name);
        if (values == null) {
            return null;
        }
        return values[0]; // 取回参数的第一个值
    }
    //取所有值
    @Override
    public String[] getParameterValues(String name) {
        Map<String, String[]> parameterMap = getParameterMap();
        String[] values = parameterMap.get(name);
        return values;
    }
}

然后在web.xml中配置此过滤器即可!

尽量保持在能设置编码的地方 全部保持为UTF-8!

7.SSM整合

7.1 环境

  • IDEA
  • MySQL8.0
  • Tomcat9
  • Maven3.8

7.2 数据库环境

创建了一个书籍数据库表

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,'从进门到进牢');

7.3 基本环境搭建

新建一个Maven项目, 添加web支持,导入相关依赖

    <!-- 依赖:junit、mysql-connect、连接池、mybatis、
        servlet、jsp
        mybatis-spring、spring、spring-connect、springMVC-->
    <dependencies>
        <!-- junit lombok -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
        </dependency>
        <!-- 数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>
        <!-- 数据库连接池 -->
        <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.5</version>
        </dependency>
        <!-- jsp、servlet、jstl -->
        <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>
        <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.3</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
        <!-- spring -->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.19.RELEASE</version>
        </dependency>

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

Maven资源过滤设置

 <!-- 资源过滤问题 -->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

建立项目基本结构和框架配置

  • com.xiaow.pojo
  • com.xiaow.dao
  • com.xiaow.service
  • com.xiaow.controller
  • mybatis-config.xml
    • <?xml version="1.0" encoding="UTF8" ?>
      <!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">
      
          <import resource="classpath:spring-dao.xml"/>
          <import resource="classpath:spring-service.xml"/>
          <import resource="classpath:spring-mvc.xml"/>
      </beans>

      ​​​​​​​

 7.4 Mybatis层编写

数据库配置文件database.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
# mysql 8.0+ 需要配置时区
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=root

编写Mybatis的核心配置文件

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 别名 -->
    <typeAliases>
        <package name="com.xiaow.pojo"/>
    </typeAliases>

    <!-- 绑定mapper -->
    <mappers>
        <mapper class="com.xiaow.dao.BooksMapper"/>
    </mappers>
</configuration>

编写数据库对应的实体类com.xiaow.pojo.Books(这里使用Lombok插件)

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

编写Dao层的Mapper接口

public interface BooksMapper {
    // 增加一本书
    int addBook(Books books);

    // 删除一本书
    int deleteBookById(@Param("bookID") int id);

    // 修改一本书
    int updateBook(Books books);

    // 查询一本书
    Books selectBookById(@Param("bookID") int id);

    // 查询所有书
    List<Books> selectAllBooks();

    // 通过书籍名查询书籍
    Books selectBookByName(@Param("bookName") String bookName);
}

编写Mapper接口对应的Mapper.xml文件(需要导入Mybatis依赖)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaow.dao.BooksMapper">
    <insert id="addBook" parameterType="books">
        insert into books (bookName, bookCounts, detail)
        values (#{bookName},#{bookCounts},#{detail});
    </insert>

    <delete id="deleteBookById" parameterType="_int">
        delete from books where bookID = #{bookID}
    </delete>

    <update id="updateBook" parameterType="books">
        update books
        set bookName = #{bookName},
            bookCounts = #{bookCounts},
            detail = #{detail}
        where bookID = #{bookID};
    </update>

    <select id="selectBookById" resultType="books">
        select *
        from books where bookID = #{bookID};
    </select>

    <select id="selectAllBooks" resultType="books">
        select *
        from books;
    </select>

    <select id="selectBookByName" resultType="books">
        select *
        from books
        where bookName = #{bookName}
    </select>
</mapper>

编写Service层的接口和实现类

接口

public interface BooksService {
    // 增加一本书
    int addBook(Books books);

    // 删除一本书
    int deleteBookById(int id);

    // 修改一本书
    int updateBook(Books books);

    // 查询一本书
    Books selectBookById(int id);

    // 查询所有书
    List<Books> selectAllBooks();

    // 通过书籍名查询书籍
    Books selectBookByName(String bookName);
}

实现类

public class BooksServiceImpl implements BooksService {

    private  BooksMapper booksMapper;
    public void setBooksMapper(BooksMapper booksMapper) {
        this.booksMapper = booksMapper;
    }

    @Override
    public int addBook(Books books) {
        return booksMapper.addBook(books);
    }

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

    @Override
    public int updateBook(Books books) {
        return booksMapper.updateBook(books);
    }

    @Override
    public Books selectBookById(int id) {
        return booksMapper.selectBookById(id);
    }

    @Override
    public List<Books> selectAllBooks() {
        return booksMapper.selectAllBooks();
    }

    @Override
    public Books selectBookByName(String bookName) {
        return booksMapper.selectBookByName(bookName);
    }
}

底层需求操作编写完毕!

7.5 Spring层

配置Spring整合Mybatis(这里使用c3p0连接池)

编写Spring整合Mybatis的相关配置文件 spring-dao.xml

<?xml version="1.0" encoding="UTF8"?>
<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">

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

    <!--
     连接池
     dbcp:半自动化操作,不能自动连接
     cp30:自动化操作(自动化的加载配置文件,并且可以自动设置到对象中)
     druid
     hikari
     -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="driverClass" value="${jdbc.driver}"/>

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

    <!-- SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 绑定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>

    <!-- 配置dao接口扫描包,动态的实现了dao接口可以注入到spring容器中-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 注入sqlSessionFactory-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!-- 要扫描的dao包-->
        <property name="basePackage" value="com.xiaow.dao"/>
    </bean>
</beans>

Spring整合Service层 spring-service.xml

<?xml version="1.0" encoding="UTF8"?>
<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">

    <!-- 扫描包 -->
    <context:component-scan base-package="com.xiaow.service"/>

    <!-- 将业务类注入到bean中,可以通过配置或注解实现-->
    <bean id="booksServiceImpl" class="com.xiaow.service.BooksServiceImpl">
        <property name="booksMapper" ref="booksMapper"/>
    </bean>

    <!-- 配置声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

Spring层编写完毕!大杂烩!一个容器!

7.6 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">
    
    <!-- Dispatcher -->
    <servlet>
        <servlet-name>Dispatcher</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>Dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- 乱码过滤 -->
    <filter>
        <filter-name>CharacterEncoding</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>CharacterEncoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <session-config>
        <session-timeout>15</session-timeout>
    </session-config>
</web-app>

spring-mvc.xml

<?xml version="1.0" encoding="UTF8"?>
<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">

    <!-- 注解驱动 -->
    <mvc:annotation-driven/>
    <!-- 静态资源过滤 -->
    <mvc:default-servlet-handler/>
    <!-- 扫描包 -->
    <context:component-scan base-package="com.xiaow.controller"/>
    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

Spring配置整合文件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">

    <import resource="classpath:spring-dao.xml"/>
    <import resource="classpath:spring-service.xml"/>
    <import resource="classpath:spring-mvc.xml"/>
</beans>

配置文件暂且结束!开始编写Controller和视图层!

BooksController类编写

@Controller
@RequestMapping("/books")
public class BooksController {
    // controller调用service层
    @Autowired
    private BooksService booksService;

    @RequestMapping("/allBooks")
    // 查询所有书籍
    public String getAllBooks(Model model) {
        // 查询数据库数据
        List<Books> list = booksService.selectAllBooks();
        model.addAttribute("books", list);
        return "allBooks";
    }

    // 跳转到添加书籍页面
    @RequestMapping("/addBookPage")
    public String addBookPage() {
        return "addBookPage";
    }

    // 添加书籍业务
    @RequestMapping("/addBook")
    public String addBook(Books books) {
        int rows = booksService.addBook(books);
        System.out.println("addBook影响行数:=》" + rows);
        // 添加数据后 重定向到 @RequestMapping("/allBooks")请求
        return "redirect:/books/allBooks";
    }

    // 跳转到修改书籍页面
    @RequestMapping("/updateBookPage/{bookId}")
    public String updateBookPage(@PathVariable int bookId, Model model) {
        // 根据前端的数据查询book
        Books book = booksService.selectBookById(bookId);
        // 返回到前端
        model.addAttribute("tempBook", book);
        return "updateBookPage";
    }

    // 修改书籍请求
    @RequestMapping("/updateBook")
    public String updateBook(Books books) {
        int rows = booksService.updateBook(books);
        System.out.println("updateBook影响行数:=》" + rows);
        // 修改数据后 重定向到 @RequestMapping("/allBooks")请求
        return "redirect:/books/allBooks";
    }

    // 删除书籍请求
    @RequestMapping("/deleteBook/{bookId}")
    public String deleteBook(@PathVariable int bookId) {
        int rows = booksService.deleteBookById(bookId);
        System.out.println("deleteBook影响行数:=》" + rows);
        // 删除书籍后 重定向到 @RequestMapping("/allBooks")请求
        return "redirect:/books/allBooks";
    }

    // 根据书籍名查询书籍
    @RequestMapping("/selectBook")
    public String seleteBookByName(String queryBookName, Model model) {
        Books book = booksService.selectBookByName(queryBookName);
        List<Books> list = new ArrayList<>();
        list.add(book);
        model.addAttribute("books", list);
        return "allBooks";
    }
}

首页index.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
  <head>
    <title>$Title$</title>
    <base href="<%=basePath%>">
    <style>
      a{
        text-decoration: none;
        color: pink;
        font-size: 40px;
      }

      h1{
        width: 500px;
        height: 250px;
        margin: 100px auto;
        text-align: center;
        line-height: 250px;
        background: black;
        border-radius: 5px;
      }
    </style>
  </head>
  <body>
<h1 id="butt"><a href="${pageContext.request.contextPath}/books/allBooks">进入书籍</a></h1>
  </body>
</html>

书籍列表页面 allBooks.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: Chen
  Date: 2021/11/23
  Time: 17:08
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
    <title>allBooks</title>
    <base href="<%=basePath%>">
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"/>
</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>

    <div class="row">
        <div class="col-md-4 column">
            <a class="btn btn-primary" href="${pageContext.request.contextPath}/books/addBookPage">添加书籍</a>
        </div>

        <form class="form-inline" action="${pageContext.request.contextPath}/books/selectBook" method="post">
            <div class="form-group">
                <label class="sr-only" for="bookName">书籍名</label>
                <input type="text" class="form-control" id="bookName" name="queryBookName" placeholder="请输入要查询的书籍名">
            </div>
            <button type="submit" class="btn btn-default">查询</button>
        </form>

    </div>

    <div class="rwo 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="${books}">
                        <tr>
                            <th>${book.bookID}</th>
                            <th>${book.bookName}</th>
                            <th>${book.bookCounts}</th>
                            <th>${book.detail}</th>
                            <th>
                                <a href="${pageContext.request.contextPath}/books/updateBookPage/${book.bookID}">修改</a> &nbsp;|&nbsp;
                                <a href="${pageContext.request.contextPath}/books/deleteBook/${book.bookID}">删除</a>
                            </th>
                        </tr>
                    </c:forEach>
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>

添加书籍页面 addBookPage.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
    <title>addBook</title>
    <base href="<%=basePath%>">
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"/>
</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}/books/addBook" method="post">
        <div class="form-group">
            <label for="bookName">书籍名称</label>
            <input type="text" class="form-control" name="bookName" id="bookName">
        </div>
        <div class="form-group">
            <label for="bookCount">书籍数量</label>
            <input type="text" class="form-control" name="bookCounts" id="bookCount">
        </div>
        <div class="form-group">
            <label for="detail">书籍概述</label>
            <input type="text" class="form-control" name="detail" id="detail">
        </div>
        <div class="form-group">
            <input type="submit" class="form-control" value="添加">
        </div>
    </form>

</div>
</body>
</html>

修改书籍页面 updateBookPage.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
    <title>updateBook</title>
    <base href="<%=basePath%>">
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"/>
</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}/books/updateBook" method="post">
        <input type="hidden" name="bookID" value="${tempBook.bookID}">
        <div class="form-group">
            <label for="bookName">书籍名称</label>
            <input type="text" class="form-control" name="bookName" value="${tempBook.bookName}" id="bookName">
        </div>
        <div class="form-group">
            <label for="bookCount">书籍数量</label>
            <input type="text" class="form-control"  name="bookCounts" value="${tempBook.bookCounts}" id="bookCount">
        </div>
        <div class="form-group">
            <label for="detail">书籍概述</label>
            <input type="text" class="form-control" name="detail" value="${tempBook.detail}" id="detail">
        </div>
        <div class="form-group">
            <input type="submit" class="form-control" value="修改">
        </div>
    </form>

</div>
</body>
</html>

配置Tomcat进行测试!!

项目结构图

 待补充...

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值