Java学习总结 SpringBoot整合Spring MVC

1.SpringMVC概述

MVC(Model–view–controller)是软件工程中的一种软件架构模式,基于此模式把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。目的是通过这样的设计使程序结构更加简洁、直观,降低问题的复杂度。其中各个组成部分的职责为:
视图(View) - UI设计人员进行图形界面设计,负责实现与用户交互。
控制器(Controller)- 负责获取请求,处理请求,响应结果。
模型(Model) - 实现业务逻辑,数据逻辑实现。

我们在软件设计时,通常要遵循一定的设计原则。MVC架构模式的设计中,首先基于单一职责原则(SRP-Single responsibility principle)让每个对象各司其职,各尽所能。
然后再基于“高内聚,低耦合”的设计思想实现相关层对象之间的交互。这样可以更好提高程序的可维护性和可扩展性。
JavaEE技术体系中,MVC设计思想的实现,如图-14所示:

在上图中,Servlet充当MVC中的Controller,负责调用model处理业务,负责转发或重定向某个页面,在页面(view)上呈现数据。
模块封装了对Servlet的技术的应用,简化了程序员对请求和响应过程中数据的处理。Spring MVC 是Spring 框架中基于MVC设计思想实现的一个用于处理Web请求的模块。其简易架构分析,如下图所示:

DispatcherServlet :前端控制器, 处理请求的入口。
HandlerMapping:映射器对象, 用于管理url与对应controller的映射关系。
Interceptors:拦截器,实现请求响应的共性处理。
Controller:后端控制器-handler, 负责处理请求的控制逻辑。
ViewResolver:视图解析器,解析对应的视图关系(前缀+viewname+后缀)。
备注:假如希望了解Spring MVC的详细处理流程可以基于断点调试法进行跟踪。

2.初始配置

1. 添加Spring MVC依赖

编辑pom.xml文件,添加web依赖,Thymeleaf依赖,代码如下:
Web依赖(提供了Spring MVC核心API,同时会嵌入一个Tomcat服务器)

<dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-web</artifactId></dependency>

Thymeleaf依赖(提供了一个视图解析器对象以及数据绑定机制)

<dependency>       <groupId>org.springframework.boot</groupId>       <artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>

其中: Spring Web Starter 提供Spring MVC 依赖支持,并会自动添加一个tomcat依赖,作为嵌入式web服务器使用.thymeleaf是一个html模板引擎,提供了与Spring MVC进行整合的API,可作为MVC架构中Web应用的View层。

2. 配置Spring MVC 核心对象

在application.proper视ties文件中添加图解析器配置(假如没有配置也会默认配置,在默认配置中prefix默认值为classpath:/templates/,后缀默认为.html)。

spring.thymeleaf.prefix=classpath:/templates/pages/spring.thymeleaf.suffix=.html

说明:要基于配置在src/main/resources目录下创建templates/pages目录

3.Spring MVC 进行入门实践

第一步:编写GoodsController类并将其交给spring管理。这样的Controller在SpringMVC 规范中通常称之为Handler(处理器),我们在企业中有时也会将此对象理解为一个后端控制器。

package com.cy.pj.goods.controller;@Controller    @RequestMapping("/goods/")public class GoodsController {     @RequestMapping("doGoodsUI")public String doGoodsUI() {       return "goods";    }}

第二步:需要在/templates/pages/目录下创建goods.html
第三步:启动服务器(默认项目嵌入的是tomcat),打开浏览器进行访问测试。
http://localhost:8080/goods/doGoodsUI
API应用设计,如图所示:

课堂练习1:将数据库中的商品数据查询出来更新到页面上。

查询时序分析:

第一步:定义pojo对象(com.cy.pj.goods.pojo.Goods)

package com.cy.pj.goods.pojo;import java.util.Date;/** * pojo对象,基于此对象封装从数据库查询到的数据 * 思考:对象靠什么存储数据?属性 */public class Goods {    private Long id;//id bigint primary key auto_increment    private String name;//name varchar(100) not null    private String remark;//remark text    private Date createdTime;//createdTime datetime    public Long getId() {        return id;    }    public void setId(Long id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getRemark() {        return remark;    }    public void setRemark(String remark) {        this.remark = remark;    }    public Date getCreatedTime() {//        System.out.println("==getCreatedTime==");        return createdTime;    }    public void setCreatedTime(Date createdTime) {        this.createdTime = createdTime;    }    @Override    public String toString() {        return "Goods{" +                "id=" + id +                ", name='" + name + '\'' +                ", remark='" + remark + '\'' +                ", createdTime=" + createdTime +                '}';    }}

第二步:定义GoodsDao接口及方法

package com.cy.pj.goods.dao;import com.cy.pj.goods.pojo.Goods;import org.apache.ibatis.annotations.*;import java.util.List;/** * @Mapper是由Mybatis框架中定义的一个描述数据层接口对象的注解(所有的注解起到一个描述性的作用) * 系统底层启动mybatis框架会基于@Mapper注解的描述,创建其接口的实现类,并将其实现类对象交给spring管理 */@Mapperpublic interface GoodsDao {    /**     * 查找所有商品信息     */    @Select("SELECT id,name,remark,createdTime FROM tb_goods")    List<Goods> findObjects();}

第三步:定义GoodsService接口及其实现类

GoodsService

package com.cy.pj.goods.service;import com.cy.pj.goods.pojo.Goods;import java.util.List;public interface GoodsService {    List<Goods> findGoods();}

GoodsServiceImpl

package com.cy.pj.goods.service.impl;import com.cy.pj.goods.dao.GoodsDao;import com.cy.pj.goods.pojo.Goods;import com.cy.pj.goods.service.GoodsService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;/** * 商品业务层对象,负责业务逻辑处理 */@Servicepublic class GoodsServiceImpl implements GoodsService {    @Autowired    private GoodsDao goodsDao;    @Override    public List<Goods> findGoods() {        Long start=System.currentTimeMillis();        List<Goods> list=goodsDao.findObjects();        long end=System.currentTimeMillis();        System.out.println("query time:"+(end-start));        return list;    }}

第四步:定义GoodsController及其url映射

package com.cy.pj.goods.controller;import com.cy.pj.goods.pojo.Goods;import com.cy.pj.goods.service.GoodsService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import java.util.List;@Controller@RequestMapping("/goods/")public class GoodsController {    @Autowired    private GoodsService goodsService;        //http:localhost:8080/goods/doGoodsUI    //此访问路径会传递到DispatcherServlet对象    //DispatcherServlet对象会基于用户输入的url找到对应的controller及方法    //DispatcherServlet底层会根据反射技术调用对应的控制层方法    @RequestMapping("doGoodsUI")    public String doGoodsUI(Model model) {        //获取业务数据        List<Goods> list = goodsService.findGoods();        //将数据存储到作用域对象        model.addAttribute("list", list);        //将页面响应到客户端        return "goods";//view name        //将此view返回给前端控制器DispatcherServlet        //前端控制器会调用视图解析器对view进行解析,添加前缀和后缀        //templates/pages/goods.html        //最后由DispatcherServlet将页面响应给客户端    }}

第五步:定义goods.html,通过Thymeleaf模板将活动数据呈现在页面上

<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>    <table>        <thead>            <th>id</th>            <th>name</th>            <th>remark</th>            <th>createdTime</th>        </thead>        <tbody>            <tr th:each="g:${list}" >                <td th:text="${g.id}"></td>                <td th:text="${g.name}"></td>                <td th:text="${g.remark}"></td>                <td th:text="${#dates.format(g.createdTime,'yyyy/MM/dd HH:mm')}"></td>            </tr>        </tbody>    </table></body></html>

第六步:运行Application启动服务器,在网页中输入url地址

启动服务器:

在网页中输入url地址:http://localhost:8080/goods/doGoodsUI
查询结果如下:

课堂练习二:基于ID删除商品库中的商品信息

时序分析:

第一步:GoodsDao中定义基于id删除记录的方法 deleteById(Integer id);

package com.cy.pj.goods.dao;import com.cy.pj.goods.pojo.Goods;import org.apache.ibatis.annotations.*;import java.util.List;/** * @Mapper是由Mybatis框架中定义的一个描述数据层接口对象的注解(所有的注解起到一个描述性的作用) * 系统底层启动mybatis框架会基于@Mapper注解的描述,创建其接口的实现类,并将其实现类对象交给spring管理 */@Mapperpublic interface GoodsDao {    /**     * 基于id删除数据库中商品信息     * @param id     * @return     */    @Delete("delete from tb_goods where id=#{id}")    int deleteById(Integer id);        /**     * 查找所有商品信息     * @return     */    @Select("SELECT id,name,remark,createdTime FROM tb_goods")    List<Goods> findObjects();}

第二步:GoodsService及实现类中定义deleteById(Integer id)方法用于执行记录删除
GoodsService

package com.cy.pj.goods.service;import com.cy.pj.goods.pojo.Goods;import java.util.List;public interface GoodsService {    List<Goods> findGoods();    void deleteById(Integer id);}

GoodsServiceImpl

package com.cy.pj.goods.service.impl;import com.cy.pj.goods.dao.GoodsDao;import com.cy.pj.goods.pojo.Goods;import com.cy.pj.goods.service.GoodsService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;/** * 商品业务层对象,负责业务逻辑处理 */@Servicepublic class GoodsServiceImpl implements GoodsService {    @Autowired    private GoodsDao goodsDao;    @Override    public List<Goods> findGoods() {        Long start=System.currentTimeMillis();        List<Goods> list=goodsDao.findObjects();        long end=System.currentTimeMillis();        System.out.println("query time:"+(end-start));        return list;    }    @Override    public void deleteById(Integer id) {        int rows=goodsDao.deleteById(id);    }}

第三步:ActivityController中定义doDeleteById(Integer id)方法用于处理删除请求

package com.cy.pj.goods.controller;import com.cy.pj.goods.pojo.Goods;import com.cy.pj.goods.service.GoodsService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import java.util.List;@Controller@RequestMapping("/goods/")public class GoodsController {    @Autowired    private GoodsService goodsService;    //http://localhost:8080/goods/doDeleteById    @RequestMapping("doDeleteById")    public String doDeleteById(Integer id){        //调用业务层对象执行删除操作        goodsService.deleteById(id);        //思考:删除以后要做什么?        //在当前业务中我们可以重定向到查询页面        return "redirect:doGoodsUI";    }    //http:localhost:8080/goods/doGoodsUI    //此访问路径会传递到DispatcherServlet对象    //DispatcherServlet对象会基于用户输入的url找到对应的controller及方法    //DispatcherServlet底层会根据反射技术调用对应的控制层方法    @RequestMapping("doGoodsUI")    public String doGoodsUI(Model model) {        //获取业务数据        List<Goods> list = goodsService.findGoods();        //将数据存储到作用域对象        model.addAttribute("list", list);        //将页面响应到客户端        return "goods";//view name        //将此view返回给前端控制器DispatcherServlet        //前端控制器会调用视图解析器对view进行解析,添加前缀和后缀        //templates/pages/goods.html        //最后由DispatcherServlet将页面响应给客户端    }}

第四步:定义goods.html,通过Thymeleaf模板将活动数据呈现在页面上

<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>    <table>        <thead>            <th>id</th>            <th>name</th>            <th>remark</th>            <th>createdTime</th>        </thead>        <tbody>            <tr th:each="g:${list}" >                <td th:text="${g.id}"></td>                <td th:text="${g.name}"></td>                <td th:text="${g.remark}"></td>                <td th:text="${#dates.format(g.createdTime,'yyyy/MM/dd HH:mm')}"></td>                <td><a th:href="@{/goods/doDeleteById(id=${g.id})}">delete</a></td>            </tr>        </tbody>    </table></body></html>

第五步:运行Application启动服务器,在网页中输入url地址

启动服务器:

在网页中输入url地址:http://localhost:8080/goods/doGoodsUI

点击delete

课堂练习三:将页面用户输入的商品信息写入到数据库

时序分析

第一步:在GoodsDao中定义insert(Goods entity)方法以及SQL映射

package com.cy.pj.goods.dao;import com.cy.pj.goods.pojo.Goods;import org.apache.ibatis.annotations.*;import java.util.List;/** * @Mapper是由Mybatis框架中定义的一个描述数据层接口对象的注解(所有的注解起到一个描述性的作用) * 系统底层启动mybatis框架会基于@Mapper注解的描述,创建其接口的实现类,并将其实现类对象交给spring管理 */@Mapperpublic interface GoodsDao {    /**     * 基于id删除数据库中商品信息     * @param id     * @return     */    @Delete("delete from tb_goods where id=#{id}")    int deleteById(Integer id);    /**     * 基于id进行批量删除操作     * @param ids     * @return     */    //int deleteObjects(@Param("ids")Integer...ids);早期版本需要基于@Param注解    int deleteObjects(Integer...ids);//sql映射中可使用array,ids参数名来接收方法参数    /**     * 查找所有商品信息     * @return     */    @Select("SELECT id,name,remark,createdTime FROM tb_goods")    List<Goods> findObjects();    @Insert("insert into tb_goods (name,remark,createdTime) values(#{name},#{remark},now())")    int insert(Goods entity);}

第二步:在GoodsService接口及实现类中添加insert(Goods entity)

GoodsService

package com.cy.pj.goods.service;import com.cy.pj.goods.pojo.Goods;import java.util.List;public interface GoodsService {    List<Goods> findGoods();    void deleteById(Integer id);    int insert(Goods entity);}

GoodsServiceImpl

package com.cy.pj.goods.service.impl;import com.cy.pj.goods.dao.GoodsDao;import com.cy.pj.goods.pojo.Goods;import com.cy.pj.goods.service.GoodsService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;/** * 商品业务层对象,负责业务逻辑处理 */@Servicepublic class GoodsServiceImpl implements GoodsService {    @Autowired    private GoodsDao goodsDao;    @Override    public List<Goods> findGoods() {        Long start=System.currentTimeMillis();        List<Goods> list=goodsDao.findObjects();        long end=System.currentTimeMillis();        System.out.println("query time:"+(end-start));        return list;    }    @Override    public void deleteById(Integer id) {        int rows=goodsDao.deleteById(id);    }    @Override    public int insert(Goods entity) {        int rows=goodsDao.insert(entity);        return rows;    }}

第三步:在GoodsController对象中添加doSaveGoods方法并定义url映射

package com.cy.pj.goods.controller;import com.cy.pj.goods.pojo.Goods;import com.cy.pj.goods.service.GoodsService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import java.util.List;@Controller@RequestMapping("/goods/")public class GoodsController {    @Autowired    private GoodsService goodsService;    //http://localhost:8080/goods/doDeleteById    @RequestMapping("doDeleteById")    public String doDeleteById(Integer id){        //调用业务层对象执行删除操作        goodsService.deleteById(id);        //思考:删除以后要做什么?        //在当前业务中我们可以重定向到查询页面        return "redirect:doGoodsUI";    }    @RequestMapping("doSaveGoods")    public String doSaveGoods(Goods entity){        goodsService.insert(entity);        return "redirect:doGoodsUI";    }    //http:localhost:8080/goods/doGoodsUI    //此访问路径会传递到DispatcherServlet对象    //DispatcherServlet对象会基于用户输入的url找到对应的controller及方法    //DispatcherServlet底层会根据反射技术调用对应的控制层方法    @RequestMapping("doGoodsUI")    public String doGoodsUI(Model model) {        //获取业务数据        List<Goods> list = goodsService.findGoods();        //将数据存储到作用域对象        model.addAttribute("list", list);        //将页面响应到客户端        return "goods";//view name        //将此view返回给前端控制器DispatcherServlet        //前端控制器会调用视图解析器对view进行解析,添加前缀和后缀        //templates/pages/goods.html        //最后由DispatcherServlet将页面响应给客户端    }}

第四步:在页面中goods.html添加form表单(用户填写数据)并设置样式

<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>   <form action="/goods/doSaveGoods" method="post">       <ul>           <li>name:           <li><input type="text" name="name">           <li>remark:           <li><textarea rows="5" cols=""50 name="remark"></textarea>           <li><input type="submit" value="save"></li>       </ul>   </form>   <fieldset>       <legend>商品列表</legend>       <table width="50%">    <table>        <thead>            <th>id</th>            <th>name</th>            <th>remark</th>            <th>createdTime</th>        </thead>        <tbody>            <tr th:each="g:${list}" >                <td th:text="${g.id}"></td>                <td th:text="${g.name}"></td>                <td th:text="${g.remark}"></td>                <td th:text="${#dates.format(g.createdTime,'yyyy/MM/dd HH:mm')}"></td>                <td><a th:href="@{/goods/doDeleteById(id=${g.id})}">delete</a></td>            </tr>        </tbody>    </table></body></html>

第五步:在表单中输入数据,然后点击保存按钮,将数据传递到服务端



最后

有什么不懂的欢迎在下方留言讨论,也可以选择私信问我,私信我一般看到之后都会回的,当然特别忙的时候没看到的话也请见谅!