目录
什么是MVC
SpringMVC概述
SpringMVC常见开发方式
SpringMVC执行流程
SpringMVC核心组件介绍
快速构建Spring MVC程序
SpringMVC参数绑定
SpringMVC跳转方式
SpringMVC处理json请求和响应
SpringMVC静态资源处理
SpringMVC拦截器
SpringMVC文件的上传
SpringMVC全局异常统一处理
SSM框架整合
1.引入pom依赖
2.设置配置文件
3.项目目录结构
MVC 设计模式一般指 MVC 框架,M(Model)指数据模型层,业务模型层,V(View)指视图层,C(Controller)指控制层。使用 MVC 的目的是将 M 和 V 的实现代码分离,使同一个程序可以有不同的表现形式。
MVC 属于架构模式的一种,所谓架构就是如何设计一个程序的结构。MVC 将程序结构划分为三层,每一层都对外提供了可供上层调用的接口,既能维系三层之间的联系,也能保持相对的独立性。
这种将业务逻辑、数据和界面分离的代码组织形式,降低了模块间的耦合度,有利于日后的维护与扩展。
springmvc是基于spring Framwork衍生出来的一个mvc框架,主要解决原有mvc架构中,控制器(Controller)的问题,常见的控制器有servlet,struts2等,控制器的核心功能是根据用户的请求调用对应业务功能,然后依据业务处理的结果,控制程序的运行流程。
servlet实现控制器存在的问题:
1.接收客户端请求参数时,存在代码的冗余
2.只能接收字符串类型的数据,其它数据类型需要手动的转换
3.无法接收对象类型的参数
4.调用业务对象存在耦合 (new)
5.流程跳转存在耦合(路径耦合,视图耦合)
1.传统的开发方式
通过作用域(request,session)实现数据的传递
通过视图技术进行视图的渲染(jsp thymleaf freeMarker)
2.前后端分离开发方式
多种新的访问方式(get 、post 、put、 delete)
Restful风格的访问
Spring MVC 框架是高度可配置的,包含多种视图技术,例如 JSP、FreeMarke和 POI。Spring MVC 框架并不关心使用的视图技术,也不会强迫开发者只使用 JSP。
Spring MVC 执行流程如图 所示:
SpringMVC 的执行流程如下:
用户点击某个请求路径,发起一个 HTTP request 请求,该请求会被提交到 DispatcherServlet(前端控制器);
由 DispatcherServlet 请求一个或多个 HandlerMapping(处理器映射器),并返回一个执行链(HandlerExecutionChain)。
DispatcherServlet 将执行链返回的 Handler 信息发送给 HandlerAdapter(处理器适配器);
HandlerAdapter 根据 Handler 信息找到并执行相应的 Handler(常称为 Controller);
Handler 执行完毕后会返回给 HandlerAdapter 一个 ModelAndView 对象(Spring MVC的底层对象,包括 Model 数据模型和 View 视图信息);
HandlerAdapter 接收到 ModelAndView 对象后,将其返回给 DispatcherServlet ;
DispatcherServlet 接收到 ModelAndView 对象后,会请求 ViewResolver(视图解析器)对视图进行解析;
ViewResolver 根据 View 信息匹配到相应的视图结果,并返回给 DispatcherServlet;
DispatcherServlet 接收到具体的 View 视图后,进行视图渲染,将 Model 中的模型数据填充到 View 视图中的 request 域,生成最终的 View(视图);
视图负责将结果显示到浏览器(客户端)
Spring MVC 涉及到的组件有 DispatcherServlet(前端控制器)、HandlerMapping(处理器映射器)、HandlerAdapter(处理器适配器)、Handler(处理器)、ViewResolver(视图解析器)和 View(视图)。下面对各个组件的功能说明如下。
1)DispatcherServlet
DispatcherServlet 是前端控制器,从图 1 可以看出,Spring MVC 的所有请求都要经过 DispatcherServlet 来统一分发。DispatcherServlet 相当于一个转发器或中央处理器,控制整个流程的执行,对各个组件进行统一调度,以降低组件之间的耦合性,有利于组件之间的拓展。
2)HandlerMapping
HandlerMapping 是处理器映射器,其作用是根据请求的 URL 路径,通过注解或者 XML 配置,寻找匹配的处理器(Handler)信息。
3)HandlerAdapter
HandlerAdapter 是处理器适配器,其作用是根据映射器找到的处理器(Handler)信息,按照特定规则执行相关的处理器(Handler)。
4)Handler
Handler 是处理器,和 Java Servlet 扮演的角色一致。其作用是执行相关的请求处理逻辑,并返回相应的数据和视图信息,将其封装至 ModelAndView 对象中。
5)View Resolver
View Resolver 是视图解析器,其作用是进行解析操作,通过 ModelAndView 对象中的 View 信息将逻辑视图名解析成真正的视图 View(如通过一个 JSP 路径返回一个真正的 JSP 页面)
6)View
View 是视图,其本身是一个接口,实现类支持不同的 View 类型(JSP、FreeMarker、Excel 等)。
以上组件中,需要开发人员进行开发的是处理器(Handler,常称Controller)和视图(View)。通俗的说,要开发处理该请求的具体代码逻辑,以及最终展示给用户的界面
搭建步骤如下:
创建 Web 应用并引入 JAR 包
spring-webmvc
Spring MVC 配置:在 web.xml 中配置 Servlet,创建 Spring MVC 的配置文件
springmvc配置文件
创建 Controller(处理请求的控制器)
创建 View(使用 JSP 作为视图)
部署运行
@RequestMapping详解
1.一个方法匹配多个路径
2.指定方法接收的请求方式
视图传参到控制器
1.基本数据类型绑定
形参的名字和传递参数的名字保持一致,参数需要全部传递否则报500错误,为了解决不传参报错,可以给基本类型的参数设置默认值
设置参数的别名
2.包装数据类型的传递
使用包装类型可以解决基本类型不传递值,出现500错误的问题但是还是要保持参数名字和形参保持一致,
3.字符串类型数据的绑定
参照包装类即可
4.数组类型
5.javaBean类型
参数名的字段和Javabean中的属性保持一致即可
返回数据到视图层
Spring MVC默认采用服务器内部转发的形式展示页面信息,同时也支持重定向页面
重定向(302状态码给浏览器)
响应json格式的数据
请求数据类型为JSON
/**
* 接收json格式的参数
* @param user
* @return
*/
@RequestMapping("/login4")
@ResponseBody
public Object login4(@RequestBody User user) {
System.out.println(user);
return user;
}
}
前台ajax请求
RestFul风格
一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制
URL定义
资源:互联网所有的事物都可以被抽象为资源 资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。 分别对应 添加、 删除、修改、查询
传统方式操作资源
http://127.0.0.1/item/queryUser.action?id=1 查询,GET http://127.0.0.1/item/saveUser.action 新增,POST http://127.0.0.1/item/updateUser.action 更新,POST http://127.0.0.1/item/deleteUser.action?id=1 删除,GET或POST
RestFul请求方式 可以通过 GET、 POST、 PUT、 PATCH、 DELETE 等方式对服务端的资源进行操作。其中:
1.实现Handlerlnterceptor接口
GET 用于查询资源,
POST 用于创建资源,
PUT 用于更新服务端的资源的全部信息,
DELETE 用于删除服务端的资源。
public class RestController {
@GetMapping("/rest")
public void test01(){
System.out.println("test01: ");
}
@PostMapping("/rest")
public void test02(){
System.out.println("test02: ");
}
@DeleteMapping("/rest")
public void test03(){
System.out.println("test03:");
}
@PutMapping("/rest")
public void test04(){
System.out.println("test04: ");
}
@PatchMapping("/rest")
public void test05(){
System.out.println("test05: ");
}
}
1.配置静态资源的路径
@Controller
@SessionAttributes({"model1","model2"})
public class SessionController {
@RequestMapping("/s1")
public void test01(HttpSession session){
session.setAttribute("msg", "session attribute");
}
@RequestMapping("/s2")
public void test02(HttpSession session){
System.out.println(session.getAttribute("msg"));
}
/**
* 将model放入session作用域
* @param model
*/
@RequestMapping("/s3")
public void test03(Model model){
model.addAttribute("model1", "model1 attribute");
}
/**
* 获取通过注解设置的session域中的值
* @param session
*/
@RequestMapping("/s5")
public void test05(HttpSession session){
System.out.println("msg: "+session.getAttribute("msg"));
System.out.println("model1 :"+session.getAttribute("model1"));
System.out.println("model2 :"+session.getAttribute("model2"));
}
/**
* 通过注解获取session域中的值
* @param
*/
@RequestMapping("/s6")
public void test05(@SessionAttribute(name = "msg") String session){
System.out.println(session);
}
操作cookie
public class CookieController {
@RequestMapping("/c1")
public void test01(HttpServletResponse response){
Cookie ck = new Cookie("cookie","cookieValue");
ck.setPath("/");
ck.setMaxAge(60*60*24*7);
response.addCookie(ck);
}
/**
* 获取cookie中值的方式1
* @param request
*/
@RequestMapping("/c2")
public void test02(HttpServletRequest request){
Cookie[] cookies = request.getCookies();
for (int i = 0; i < cookies.length; i++) {
System.out.println(cookies[i].getName()+":"+cookies[i].getValue());
}
}
/**
* 获取cookie中值的方式2 注解方式
* @param cookie
*/
@RequestMapping("/c3")
public void test03(@CookieValue("cookie") String cookie){
System.out.println(cookie);
}
}
SpringMVC中的Interceptor拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的 处理。比如通过它来进行权限验证,或者是来判断用户是否登录等操作。对于SpringMVC拦截器的定义方式有两 种
实现接口: org.springframework.web.servlet.Handlerlnterceptor
继承适配器: org.springframework.web.servethandler.HandlerInterceptorAdapter
1.实现Handlerlnterceptor接口
2.继承HandlerInterceptorAdapter(不建议使用)
使用拦截器拦截非法请求
/**
*用户操作模拟实现
* 用户的登录(无需登录)
* 用户的添加(登录)
* 用户修改(登录)
* 用户删除(登录)
*
* @author mosin
* date 2021/8/22
* @version 1.0
*/
@Controller
@RequestMapping("/user")
@SessionAttributes("action")
public class UserInfoController {
/**
* 用户登录
*/
@RequestMapping("/login")
public ModelAndView login(HttpSession session){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("success");
User user = User.builder().password("123456").username("lisi").build();
session.setAttribute("user", user);
modelAndView.addObject("user", user);
return modelAndView;
}
/**
* 用户添加
*/
@RequestMapping("/add")
public String add(Model model){
model.addAttribute("action", "用户添加成功");
System.out.println("用户的添加方法");
return "success";
}
/**
* 用户修改
*/
@RequestMapping("/update")
public String update(Model model){
System.out.println("用户的更新方法");
model.addAttribute("action", "用户更新成功");
return "success";
}
/**
* 用户修改
*/
@RequestMapping("/delete")
public String delete(Model model){
System.out.println("用户的删除方法");
model.addAttribute("action", "用户删除成功");
return "success";
}
}
添加坐标依赖
配置解析器
后台代码
@Controller
@RequestMapping("/upload")
public class UPloadController {
@RequestMapping("/file")
public String upload(@RequestParam("file") MultipartFile file, HttpServletRequest request){
//获取项目的真实路径
String realPath = request.getSession().getServletContext().getRealPath("/");
System.out.println(realPath);
//创建文件上传的目录
File dir = new File(realPath, "/upload");
System.out.println(dir);
//判定文件夹是否存在 不存在创建
if(!dir.exists()){
dir.mkdir();
}
if(!file.isEmpty()){
//获取文件的名字
String fileName = file.getOriginalFilename();
//截取文件的后缀 生成新的文件名 避免文件名字重复
String suffix= fileName.substring(fileName.lastIndexOf("."));
//获取当前系统时间
String fileLastName = System.currentTimeMillis()+suffix;
System.out.println(fileLastName);
//将文件写入目标文件夹
try {
file.transferTo(new File(dir,fileLastName));
request.setAttribute("msg", "文件上传成功");
} catch (IOException e) {
e.printStackTrace();
request.setAttribute("msg", "文件上传失败");
}
}else{
request.setAttribute("msg", "未选择文件");
}
return "success";
}
@RequestMapping("/files")
public String uploads(@RequestParam("files") List files, HttpServletRequest request){
//遍历集合
files.forEach(multipartFile -> {
FileUploadUtil.upload(multipartFile, request);
});
return "success";
}
}
1.处理的方式1 使用 @ExceptionHandler(Exception.class) 在类中定义一个异常的方法,处理本类中的指定异常
@RestController
@RequestMapping("/exception")
public class ExceptionController01 {
@ExceptionHandler(Exception.class)
public Object handlerException(Exception e){
return JsonResult.builder().msg("出现"+"异常").code(1).data(e.getMessage()).build();
}
@RequestMapping("/e1")
public Object ex1(){
int a = 1/0;
return null;
}
@RequestMapping("/e2")
public Object ex2() throws FileNotFoundException {
new FileInputStream("ab");
return null;
}
}
2.处理的方式2 全局处理模式 定义ExceptionAdvice类
1.引入mybatis依赖
org.mybatis
mybatis
3.5.7
com.github.pagehelper
pagehelper
5.2.1
org.mybatis
mybatis-spring
2.0.5
2.引入spring依赖
org.springframework
spring-context
5.3.9
org.springframework
spring-aspects
5.3.9
org.springframework
spring-jdbc
5.3.9
3.springmvc依赖
org.springframework
spring-webmvc
5.3.9
com.fasterxml.jackson.core
jackson-core
2.11.3
com.fasterxml.jackson.core
jackson-databind
2.11.3
com.fasterxml.jackson.core
jackson-annotations
2.11.3
commons-fileupload
commons-fileupload
1.4
4.log4j依赖
log4j
log4j
1.2.17
org.apache.logging.log4j
log4j-api
2.13.3
org.apache.logging.log4j
log4j-core
2.13.1
5.数据库驱动和连接池
mysql
mysql-connector-java
5.1.44
com.alibaba
druid
1.1.10
6.servlet+jsp依赖
javax.servlet
javax.servlet-api
4.0.1
javax.servlet.jsp
jsp-api
2.2
7.jstl依赖
javax.servlet
jstl
1.2
taglibs
standard
1.1.2
8.其它依赖
org.projectlombok
lombok
1.18.16
junit
junit
4.11
test
3.spring核心配置文件
4.spring-mvc配置文件
104857600
4096
utf-8
5.mybatis配置文件
6.web.xml
ssm
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:config/spring-*.xml
1
ssm
*.do
encoding
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
encoding
/