当前位置: 首页 > web >正文

【SpringMVC】SSM框架【二】——SpringMVC超详细

SpringMVC

学习目标:在这里插入图片描述

1.SpringMVC简介

1)web访问流程

在这里插入图片描述

  • 1.web服务器通过浏览器访问页面
  • 2.前端页面使用异步提交的方式发送请求到后端服务器
  • 3.后端服务器采用:表现层—业务层—数据层的架构进行开发
  • 4.页面请求由表现层进行接收,获取用户的请求后将参数传递到业务层,再由业务层访问数据层获取数据库中的数据,返回给表现层
  • 5.得到用户需要访问的数据之后,表现层通过JSON的格式发送数据到前端页面
  • 6.前端页面得到数据之后,解析数据并组织对应的页面渲染到浏览器展示给用户

2)SpringMVC概述

  • 是一种基于Java实现的MVC模型的轻量级web框架(表现层框架技术,主要用于表现层开发)
  • 优点:
    • 使用简单,开发便捷
    • 灵活性强

2.SpringMVC入门案例

1)案例实施

  • 1.导入SpringMVCServlet的坐标
    <dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.10.RELEASE</version></dependency></dependencies>

配置tomcat插件:

    <build><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><port>80</port><path>/</path></configuration></plugin></plugins></build>
  • 2.创建SpringMVC控制器类:
@Controller
public class controller {@RequestMapping("/print")@ResponseBodypublic String print() {System.out.println("user print ...");return "{user: name}";}
}
  • 3.初始化SpringMVC环境,设定SpringMVC加载对应的bean:
    SpringMVCConfig:
@Configuration
@ComponentScan("com.springmvclearn.controller")
public class SpringMvcConfig {
}
  • 4.初始化Servelet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求:
    SpringMvcContainersInitConfig:
public class ServeletContainersInitConfig extends AbstractDispatcherServletInitializer {//加载SpringMVC容器配置@Overrideprotected WebApplicationContext createServletApplicationContext() {AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();context.register(SpringMvcConfig.class);return context;}//设置哪些请求归属springMVC处理@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}@Overrideprotected WebApplicationContext createRootApplicationContext() {return null;}
}

在这里插入图片描述

涉及的注解介绍

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2)入门案例工作流程

在这里插入图片描述

3)不同层次结构Bean的加载控制

  • 在开发中,Spring一般加载业务层和数据层的bean,SpringMVC一般加载表现层的bean,而入门案例中配置时,Spring加载时会直接扫描整个包下的bean,包括表现层的bean
  • 为了避免Spring错误的加载到SpringMVC的bean:我们需要在Spring加载bean时,排除掉SpringMVC的bean
  • 1.方式一:Spring加载的bean设定扫描范围为com.itheima,排除掉controller包内的bean(SpringBoot中会使用这种方式进行bean的细粒度控制
@Configuration
@ComponentScan(value = "com.springmvclearn", excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)
)
public class SpringConfig {
}
  • 2.方式二:Spring加载的bean设定扫描范围为精确的包:比如直接对应service包,dao包等。
@Configuration
@ComponentScan({"com.springmvclearn.service", "com.springmvclearn.dao"})
public class SpringConfig {
}

在这里插入图片描述

4)简化开发的书写格式

5)PostMan

  • 网页调试与发送网页http请求的Chrome插件

  • 常用于进行接口测试

  • 在workspaces中可以云备份历史请求操作

  • 创建请求:
    在这里插入图片描述

  • 保持请求,并放入到一个集合中,方便分类复用:
    在这里插入图片描述

3.请求与响应

1.请求映射路径

  • 当相同层级下的controller有相同的路径时(/save),在访问时就会有路径冲突问题

  • 一般解决就是在不同controller的路径前加入不同模块的请求路径前缀: /user/save/book/save

  • 通过RequestMapping在控制类上统一设置当前控制类下的方法请求路径前缀,然后在每个控制器方法上再加每个控制方法对应的请求访问路径
    在这里插入图片描述

2.请求参数

1)普通参数请求
//请求参数
@Controller
public class UserController {//普通参数:请求参数与形参名称对应即可完成参数传递@RequestMapping("/commonParam")@ResponseBodypublic String commonParam(String name ,int age){System.out.println("普通参数传递 name ==> "+name);System.out.println("普通参数传递 age ==> "+age);return "{'module':'common param'}";}//普通参数:请求参数名与形参名不同时,使用@RequestParam注解关联请求参数名称与形参名称之间的关系@RequestMapping("/commonParamDifferentName")@ResponseBodypublic String commonParamDifferentName(@RequestParam("name") String userName , int age){System.out.println("普通参数传递 userName ==> "+userName);System.out.println("普通参数传递 age ==> "+age);return "{'module':'common param different name'}";}
}
  • 1.GET 请求:
    在这里插入图片描述
  • 2.POST请求:
    在这里插入图片描述
  • 3.POST中文参数乱码问题
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {protected Class<?>[] getRootConfigClasses() {return new Class[0];}protected Class<?>[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};}protected String[] getServletMappings() {return new String[]{"/"};}//乱码处理@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter filter = new CharacterEncodingFilter();filter.setEncoding("UTF-8");return new Filter[]{filter};}
}

在这里插入图片描述

2)POJO参数传递
  • 当大量参数需要传递时,一般将参数封装成一个实体类,在参数传递时,直接将参数赋值给实体类对象,然后从实体类对象中拿取对应参数值

User:

package com.itheima.domain;public class User {private String name;private int age;@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

在controller中:

//请求参数
@Controller
public class UserController {//POJO参数:请求参数与形参对象中的属性对应即可完成参数传递@RequestMapping("/pojoParam")@ResponseBodypublic String pojoParam(User user){System.out.println("pojo参数传递 user ==> "+user);System.out.println("userName ==> "+user.getName());System.out.println("userAge ==> "+user.getAge());return "{'module':'pojo param'}";}
}

在这里插入图片描述
在这里插入图片描述

3)嵌套POJO参数传递
  • 当POJO中还有引用的POJO时,如何传递参数
  • 也就是在POJO中将该POJO注入,并给出setter和getter方法:

user:

package com.itheima.domain;public class User {private String name;private int age;private Address address;@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +", address=" + address +'}';}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

然后在controller中同样接收POJO对象即可:

//请求参数
@Controller
public class UserController {//嵌套POJO参数:嵌套属性按照层次结构设定名称即可完成参数传递@RequestMapping("/pojoContainPojoParam")@ResponseBodypublic String pojoContainPojoParam(User user){System.out.println("pojo嵌套pojo参数传递 user ==> "+user);System.out.println("userName ==> "+user.getName());System.out.println("userAge ==> "+user.getAge());System.out.println("userAddress ==> "+user.getAddress());return "{'module':'pojo contain pojo param'}";}
}

在这里插入图片描述

在这里插入图片描述

4)数组参数传递
  • 需要传入一个数组类型的参数时:
//请求参数
@Controller
public class UserController {//数组参数:同名请求参数可以直接映射到对应名称的形参数组对象中@RequestMapping("/arrayParam")@ResponseBodypublic String arrayParam(String[] hobby){System.out.println("数组参数传递 hobby ==> "+ Arrays.toString(hobby));return "{'module':'array param'}";}
}

在这里插入图片描述

在这里插入图片描述

5)集合类型参数
  • 需要集合类型参数时:我们需要设置该集合参数为RequestParam,否则无法识别需要传递的是集合
//请求参数
@Controller
public class UserController {//集合参数:同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据@RequestMapping("/listParam")@ResponseBodypublic String listParam(@RequestParam List<String> likes){System.out.println("集合参数传递 likes ==> "+ likes);return "{'module':'list param'}";}
}

请求则同上,结果也是一样的。

在这里插入图片描述

3.JSON格式参数传递

  • 首先要加入解析JSON的坐标:
    <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.0</version></dependency>
1)JSON格式的集合参数
  • 1.开启支持集合JSON格式的数据类型自动转换:
@Configuration
@ComponentScan("com.itheima.controller")
//开启json数据类型自动转换
@EnableWebMvc
public class SpringMvcConfig {
}
  • 2.加上在参数前面加入@RequestBody,表示传入的参数是在JSON的body中
//请求参数
@Controller
public class UserController {//集合参数:json格式//1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc//2.使用@RequestBody注解将外部传递的json数组数据映射到形参的集合对象中作为数据@RequestMapping("/listParamForJson")@ResponseBodypublic String listParamForJson(@RequestBody List<String> likes){System.out.println("list common(json)参数传递 list ==> "+likes);return "{'module':'list common for json param'}";}
}

在这里插入图片描述
在这里插入图片描述

2)JSON格式的POJO参数传递(以及嵌套POJO)
  • 接收参数格式:
//请求参数
@Controller
public class UserController {//POJO参数:json格式//1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc//2.使用@RequestBody注解将外部传递的json数据映射到形参的实体类对象中,要求属性名称一一对应@RequestMapping("/pojoParamForJson")@ResponseBodypublic String pojoParamForJson(@RequestBody User user){System.out.println("pojo(json)参数传递 user ==> "+user);return "{'module':'pojo for json param'}";}
}
  • 参数请求格式:
    在这里插入图片描述

  • 结果:
    在这里插入图片描述

3)JSON格式对象集合参数传递
  • 接收参数格式:
//请求参数
@Controller
public class UserController {//集合参数:json格式//1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc//2.使用@RequestBody注解将外部传递的json数组数据映射到形参的保存实体类对象的集合对象中,要求属性名称一一对应@RequestMapping("/listPojoParamForJson")@ResponseBodypublic String listPojoParamForJson(@RequestBody List<User> list){System.out.println("list pojo(json)参数传递 list ==> "+list);return "{'module':'list pojo for json param'}";}
}
  • 参数请求格式:

在这里插入图片描述

  • 结果:
    在这里插入图片描述

4.对比

在这里插入图片描述

5.日期型参数传递

在这里插入图片描述
在这里插入图片描述

  • 接收参数格式:
//请求参数
@Controller
public class UserController {//日期参数//使用@DateTimeFormat注解设置日期类型数据格式,默认格式yyyy/MM/dd@RequestMapping("/dataParam")@ResponseBodypublic String dataParam(Date date,@DateTimeFormat(pattern="yyyy-MM-dd") Date date1,@DateTimeFormat(pattern="yyyy/MM/dd HH:mm:ss") Date date2){System.out.println("参数传递 date ==> "+date);System.out.println("参数传递 date1(yyyy-MM-dd) ==> "+date1);System.out.println("参数传递 date2(yyyy/MM/dd HH:mm:ss) ==> "+date2);return "{'module':'data param'}";}
}
  • 参数请求格式:

在这里插入图片描述

  • 结果:
    在这里插入图片描述

6.响应

  • 1.响应页面
  • 2.响应文本
  • 3.响应POJO
  • 4.响应POJO集合

使用@ResponseBody

  • 将其注解在SpringMVC控制器方法定义的上方
  • 作用:设置当前控制器返回值为响应体(POJO转JSON,POJO集合转JSON)
//请求参数
@Controller
public class UserController {//返回页面@RequestMapping("/pageParam")public String pageParam() {System.out.println("返回页面");return "index.jsp";}//返回文本数据@RequestMapping("/textParam")@ResponseBodypublic String totext() {System.out.println("返回文本数据");return "context text";}//返回POJO@RequestMapping("/userParam")@ResponseBodypublic User userParam(User user) {System.out.println("返回POJO");User new_user = new User();new_user.setName(user.getName());new_user.setAge(user.getAge());new_user.setAddress(user.getAddress());return new_user;}//返回POJO集合@RequestMapping("/usersParam")@ResponseBodypublic List<User> usersParam(List<User> user) {System.out.println("返回POJO集合");List<User> new_users = new ArrayList<>();new_users.addAll(user);return new_users;}
}

4.REST风格

  • 是一种定义资源描述的形式
    在这里插入图片描述

  • REST风格访问资源时,使用行为动作区分对资源进行了何种操作:路径+请求方式
    在这里插入图片描述
    在这里插入图片描述

1)RESTful
  • 在请求时通过不同的请求方式
    在这里插入图片描述

  • @PathVariable接收路径参数或者路径变量(路径中的参数获取:http://localhost/users/3 -> 3的获取)
    在这里插入图片描述

package com.itheima.controller;import com.itheima.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;@Controller
public class UserController {//设置当前请求方法为POST,表示REST风格中的添加操作@RequestMapping(value = "/users",method = RequestMethod.POST)@ResponseBodypublic String save(){System.out.println("user save...");return "{'module':'user save'}";}//设置当前请求方法为DELETE,表示REST风格中的删除操作//@PathVariable注解用于设置路径变量(路径参数),要求路径上设置对应的占位符,并且占位符名称与方法形参名称相同@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)@ResponseBodypublic String delete(@PathVariable Integer id){System.out.println("user delete..." + id);return "{'module':'user delete'}";}//设置当前请求方法为PUT,表示REST风格中的修改操作@RequestMapping(value = "/users",method = RequestMethod.PUT)@ResponseBodypublic String update(@RequestBody User user){System.out.println("user update..."+user);return "{'module':'user update'}";}//设置当前请求方法为GET,表示REST风格中的查询操作//@PathVariable注解用于设置路径变量(路径参数),要求路径上设置对应的占位符,并且占位符名称与方法形参名称相同@RequestMapping(value = "/users/{id}" ,method = RequestMethod.GET)@ResponseBodypublic String getById(@PathVariable Integer id){System.out.println("user getById..."+id);return "{'module':'user getById'}";}//设置当前请求方法为GET,表示REST风格中的查询操作@RequestMapping(value = "/users",method = RequestMethod.GET)@ResponseBodypublic String getAll(){System.out.println("user getAll...");return "{'module':'user getAll'}";}
}
2)@RequestBody@RequestParam@PathVariable

在这里插入图片描述

3)RESTful快速开发
  • 在1)RESTful的编写中,同一个路径前缀等在每个控制器方法上都有,为了简化书写,以下注解和简化写法是标准的RESTful开发:
    在这里插入图片描述
    在这里插入图片描述

  • 标准RESTful开发:

package com.itheima.controller;import com.itheima.domain.Book;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;//@Controller
//@ResponseBody配置在类上可以简化配置,表示设置当前每个方法的返回值都作为响应体
//@ResponseBody
@RestController     //使用@RestController注解替换@Controller与@ResponseBody注解,简化书写
@RequestMapping("/books")
public class BookController {//    @RequestMapping( method = RequestMethod.POST)@PostMapping        //使用@PostMapping简化Post请求方法对应的映射配置public String save(@RequestBody Book book){System.out.println("book save..." + book);return "{'module':'book save'}";}//    @RequestMapping(value = "/{id}" ,method = RequestMethod.DELETE)@DeleteMapping("/{id}")     //使用@DeleteMapping简化DELETE请求方法对应的映射配置public String delete(@PathVariable Integer id){System.out.println("book delete..." + id);return "{'module':'book delete'}";}//    @RequestMapping(method = RequestMethod.PUT)@PutMapping         //使用@PutMapping简化Put请求方法对应的映射配置public String update(@RequestBody Book book){System.out.println("book update..."+book);return "{'module':'book update'}";}//    @RequestMapping(value = "/{id}" ,method = RequestMethod.GET)@GetMapping("/{id}")    //使用@GetMapping简化GET请求方法对应的映射配置public String getById(@PathVariable Integer id){System.out.println("book getById..."+id);return "{'module':'book getById'}";}//    @RequestMapping(method = RequestMethod.GET)@GetMapping             //使用@GetMapping简化GET请求方法对应的映射配置public String getAll(){System.out.println("book getAll...");return "{'module':'book getAll'}";}
}
4)案例:基于RESRful页面数据交互
  • 1.制作控制器,通过PostMan测试接口:
    在这里插入图片描述

  • 2.放行静态资源访问:
    由于SpringMVC设置了访问路径拦截,当访问前端静态页面时,会被拦截,导致无法访问到,于是我们需要制作放行器,将对应的静态数据进行放行:

SpringMVCSupport:

package com.itheima.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;@Configuration
public class SpringSupport extends WebMvcConfigurationSupport {//当访问/pages/????的时候,走/pages目录下的内容@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");registry.addResourceHandler("/css/**").addResourceLocations("/css/");registry.addResourceHandler("/js/**").addResourceLocations("/js/");registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");}
}
  • 3.异步提交访问后端控制器获取数据:
    在这里插入图片描述

5.拦截器

  • 动态拦截方法调用的机制,在SpringMVC中动态拦截控制器的执行
  • 作用:
    • 在指定的方法调用前后执行预先设定的代码
    • 阻止原始方法的执行(权限控制)
      在这里插入图片描述

1)拦截器与过滤器区别

  • 归属不同:Filter属于Serverlet技术,Interceptor属于SpringMVC技术
  • 拦截内容不同:Filter针对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强

2)拦截器入门案例

  • 1.声明拦截器的bean,并实现HandlerInterceptor接口:
@Component
public class MyProjectInterceptor implements HandlerInterceptor {@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("MyProjectInterceptor posHandle");}@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("MyProjectInterceptor preHandle");return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("MyProjectInterceptor afterCompletion");}
}
  • 2.定义配置类,继承WebMvcConfigurationSupport,实现addInterceptor方法:
@Configuration
public class MySpringMvcSupport extends WebMvcConfigurerAdapter {@Overridepublic void addInterceptors(InterceptorRegistry registry) {}
}
  • 3.添加拦截器并设定拦截的访问路径,路径可以通过可变参数设置多个:
@Configuration
public class MySpringMvcSupport extends WebMvcConfigurerAdapter {@Autowiredprivate MyProjectInterceptor projectInterceptor;@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/page/**").addResourceLocations("classpath:/pages/");}@Overridepublic void addInterceptors(InterceptorRegistry registry) {//拦截器配置,当遇到哪些路径时,会将其拦截下来执行对应的postHandle和preHandle方法registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*");}
}
  • 4.发送请求:
    在这里插入图片描述
  • 5.拦截器拦截对应的路径下方法的调用,并在方法调用前后执行预先定义的方法:
    在这里插入图片描述
拦截器执行流程:

在这里插入图片描述

3)拦截器参数(了解即可,主要用到的可能是前置处理)

  • 前置处理,拿到handler(原始方法对象的封装)可以对原始方法进行一些处理
  • 主要用处为在方法执行前作校验
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

4)拦截器链(了解即可)

  • 当配置多个拦截器是,形参拦截器链
  • 拦截器链的运行顺序参照拦截器添加的顺序为准
    在这里插入图片描述
    *注:上述内容均来自黑马程序员SSM框架的课程学习,仅用作学习交流,不作为商业用途,如有侵权,联系删除。
http://www.xdnf.cn/news/19372.html

相关文章:

  • ModuleNotFoundError: No module named ‘cairosvg‘
  • 浔川社团阅读量破历史记录
  • 得物25年春招-安卓部分编程题
  • GD32入门到实战21--输入捕获
  • 【C++】日期类实现详解:代码解析与复用优化
  • C#正则表达式与用法
  • 【基础-单选】关于Tabs组件页签的位置设置,下面描述错误的是
  • 免费在线图片合成视频工具 ,完全免费
  • uni.onBLECharacteristicValueChange接收到数据,返回的value为{}的原因及其获取方法
  • 佳易王钟表维修养护管理系统:开启钟表维修高效管理新篇章​就#软件操作教程
  • Mysql 学习day 2 深入理解Mysql索引底层数据结构
  • React前端开发_Day6-Day9_极客园项目
  • C语言 - 输出参数详解:从简单示例到 alloc_chrdev_region
  • Spring AI 的应用和开发
  • 如何简单建设一个网站,让用户快速找到你。
  • 在PowerPoint和WPS演示让蝴蝶一直跳8字舞
  • Python生成免安装exe
  • SAP PP模块的MPS
  • Vue加载速度优化,verder.js和element.js加载速度慢解决方法
  • 防火墙技术(二):安全区域
  • C#调用c++ dll读取2进制文件时而正常,时而异常
  • 语义分割目前还是研究热点吗?
  • 如何快速了解项目管理基础
  • 【具身智能】【机械臂】机械臂轨迹规划项目以及资料汇总【持续更新】
  • 【物联网】MQTT / Broker / Topic 是什么?
  • windows 谷歌浏览器把英文改成中文
  • 【路由器】TP Link 路由器为何无法进入管理后台
  • 关于铭飞平台企业官网模板使用中常到的问题、企业官网的百度认证以及IDEA编辑启动器的快捷方法/Apipost本地和云端没法同步的问题解决
  • 【软考架构】SOA与微服务解疑
  • React Hooks深度解析与最佳实践:提升函数组件能力的终极指南