【深度分析】:阿里,腾讯面试题 SpringBoot整合Spring MVC
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管理
*/
@Mapper
public 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;
/**
* 商品业务层对象,负责业务逻辑处理
*/
@Service
public 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管理
*/
@Mapper
public 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;
/**
* 商品业务层对象,负责业务逻辑处理
*/
@Service
public 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管理
*/
@Mapper
public 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;
/**
* 商品业务层对象,负责业务逻辑处理
*/
@Service
public 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>
第五步:在表单中输入数据,然后点击保存按钮,将数据传递到服务端




最后
有什么不懂的欢迎在下方留言讨论,也可以选择私信问我,私信我一般看到之后都会回的,当然特别忙的时候没看到的话也请见谅!
【深度分析】:阿里,腾讯面试题 SpringBoot整合Spring MVC的更多相关文章
- springBoot整合spring security实现权限管理(单体应用版)--筑基初期
写在前面 在前面的学习当中,我们对spring security有了一个小小的认识,接下来我们整合目前的主流框架springBoot,实现权限的管理. 在这之前,假定你已经了解了基于资源的权限管理模型 ...
- springBoot整合spring security+JWT实现单点登录与权限管理--筑基中期
写在前面 在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与 ...
- springboot整合spring Data JPA
今天敲代码,一连串的错误,我也是服气~果然,我们不是在出bug,就是在找bug的路上…… 今天完成的是springboot整合spring data JPA ,出了一连串的错,真是头大 java.sq ...
- SpringBoot整合Spring Security
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 前言 Spring Securi ...
- Springboot整合Spring Cloud Kubernetes读取ConfigMap,支持自动刷新配置
1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! Docker & Kubernetes相关文章:容器技术 之前介绍了Spring Cloud Config的用法,但 ...
- 2分钟在eclipse下使用SpringBoot搭建Spring MVC的WEB项目
1. 首先用eclipse创建一个maven工程, 普通maven工程即可 2. 修改pom如下: <?xml version="1.0" encoding="UT ...
- SpringBoot集成Spring MVC视图
SpringBoot在springmvc的视图解析器方面就默认集成了ContentNegotiatingViewResolver和BeanNameViewResolver,在视图引擎上就已经集成自动配 ...
- Linux fork函数具体图解-同一时候分析一道腾讯笔试题
原创blog.转载请注明出处 头文件: #include<unistd.h> #include<sys/types.h> 函数原型: pid_t fork( void); (p ...
- SpringBoot整合Spring Security使用Demo
https://start.spring.io/ 生成SpringBoot项目 pom文件应该是我这样的: <?xml version="1.0" encoding=&quo ...
随机推荐
- Linux运维学习第三周记
日落狐狸眠冢上 夜归儿女笑灯前 人生有酒须当醉 一滴何曾到九泉 愿醉卧沙场可未有匹夫之勇. 第三周学记 第三周主要学习正则表达式和Shell编程 1.正则表达式基本字符 2.扩展正则表达式 3.gre ...
- C++ Win 32 使用原始套接字获取所有ip数据包并分析(包括ping包)
/*页面编码:GBK 开发环境 VS2019 */ #define _WINSOCK_DEPRECATED_NO_WARNINGS#include <iostream>#include&l ...
- 阿里技术专家十五问,真题面试刀刀见肉,快来和阿里面试官battle
引言 2020阿里巴巴专家组出题,等你来答: 题目:如何判断两个链表是否相交 出题人:阿里巴巴新零售技术质量部 参考答案: $O(n^2)$: 两层遍历,总能发现是否相交 $O(n)$: 一层遍历,遍 ...
- Spring Boot与多数据源那点事儿~
持续原创输出,点击上方蓝字关注我 目录 前言 写这篇文章的目的 什么是多数据源? 何时用到多数据源? 整合单一的数据源 整合Mybatis 多数据源如何整合? 什么是动态数据源? 数据源切换如何保证线 ...
- 用node.js给C#写一个数据表的实体类生成工具
虽然微软提供了T4模板,但是我感觉非常难用.哪儿比得上直接用脚本来写模板来的爽. 因为要给一个老项目做周边的工具,需要连接到数据库. 我习惯性用EntityFrameworkCore来做,因为毕竟从出 ...
- VB 错误日志:MSForms.CommandButton 不是一个已加载的控件类等解决方法
是由于缺少了fm20.dll这个必要组件 网上找到 然后在工程中引用 找到路径 完美解决
- D. Palindromic characteristics 解析(DP)
Codeforce 835 D. Palindromic characteristics 解析(DP) 今天我們來看看CF835D 題目連結 題目 略,請看原題 前言 想不到這種狀態... @copy ...
- Memcached 的惹祸,.NET 5.0 的背锅
抱歉,拖到现在才写这篇为 .NET 5.0 洗白的博文(之前的博文),不好意思,又错了,不是洗白,是还 .NET 5.0 的清白. 抱歉,就在今天上午写这篇博客的过程中,由于一个bug被迫在访问高峰发 ...
- Docker学习笔记之--安装mssql(Sql Server)并使用Navicat连接测试(环境:centos7)
前一节演示如何使用Nginx反向代理 .net Core项目容器,地址:Docker学习笔记之-部署.Net Core 3.1项目到Docker容器,并使用Nginx反向代理(CentOS7)(二) ...
- Djano之数据库--ORM
一.建立数据库模型类 1.在model里创建模型类.(继承models.Model) 1 class Order(models.Model): 2 TYPE_CHOICE = ( 3 (0, u&qu ...