SpringMVC的一些恶补

最近实习,看组里别人写controller层的路径和参数绑定,几个人好多种不同的写法,才发现,这些东西背下来不太行,还是得全面的理解一下。

很多理解使个人理解,不一定对。这是跟着黑马的视频做的笔记,视频地址在最后贴出。先放在评论中。

MVC设计模型

  • M model模型 JavaBean 封装数据
  • V View 视图   JSP 显示最终页面
  • C Controller  控制器 Servlet 接受请求

在使用springMVC的项目中,会配置一个springmvx.xml的配置文件,这个文件里面一般会做这样一些工作

  • 扫描注解,我理解这里的扫描注解不是扫描springmvc的注解,而更像是spring的注解扫描,它负责扫描类级注解比如@Controller。扫描这些Controller之后创建出Bean对象,在之后要用到这些Bean的时候就可以用了。
  • 配置视图解析器<bean ...>注意这里是bean,那么也就是说其实是一个对象
  • <mvc:annotation-driven>开启springMVC框架注解的支持,比如@RequestMapping

几个月之前第一遍学的时候之前也不太理解这些东西,后来自己被分配任务从持久层写到表现层之后,大概才对这些有了理解。其实springMVC做这么多也只是为了在controller层能响应前端请求,找到对应的controller(handler)然后可以把返回的值解析成页面返回到客户端。这里面包含了参数的绑定,这个是一个重点。

下面说一下MVC的一些原理

MVC的核心是DispatcherServlet,是一个servlet,所以说MVC的核心是一个servlet,但是之前学servlet的时候觉得没什么用,所以也没好好学,大概就是知道它是处理请求,返回响应。所以后面还得好好去看看servlet。

  • MVC是将各个功能分成一个一个组件来执行,每个组件命名都是以器来结尾。个人觉得这里也可以和后面SpringBoot的组件理念对应,组件都是bean,都是对象,自动注入容器中,等要用到的时候取出来用。
  • 前端控制器DispathcerServlet是核心,从接受用户的请求开始就指导MVC做后面的每一步操作。
  • 处理器映射器HandlerMapping,注意Handler的概念,Handler翻译为处理器,其实就是Controller。HandlerMapping处理器映射器,负责通过请求的路径来找到对应的Controller类中的对应method。找到这个方法返回这个方法,它的功能就结束了,不是找到了就执行这个功能,执行这个功能是另外的东西负责。就是这么规定的,我是硬生生这么理解的。
  • 方法被返回给处理器适配器HandlerAdapter,我的理解是处理器适配器里面装了所有的controller的bean对象。然后在这里面就可以正真地执行这些不同的方法。
  • 返回字符串给视图解析器,视图解析器就是把这些字符串变成对应的页面,然后返回页面给客户端。前后端分离项目中,视图解析器不太重要,因为后端只会返回json字符串,不用管页面。
  • 处理器映射器和处理器适配器这两个名字很难记,但是我发现其实前缀都是处理器,也就是Handler,它其实就是指controller类,换种说法处理器映射器就是controller类映射查找,处理器适配器就是真正执行要执行method的组件。

使用SpringMVC的项目还要理解一点就是,适配器和映射器其实都没有配置,一个<mvc:annotation-driven>就会把这两个东西启动,而视图解析器是通过<bean ...>来配置出来的。<bean>就是往容器中装一个bean对象。

前端控制器是需要单独配置的,然后配置了处理器映射器,处理器适配器,视图解析器的springmvc.xml配置文件注入到前端控制器中。前端控制器就像个一个大容器,springmvc中的三个器(组件)就像里面的组件一样往前端控制器中注入。以此来看MVC的核心就是一个servlet控制器。

RequestMapping

@RequestMapping可以写在类上或者方法上。真实开发的时候一般都会在类上写一个,来分模块,这也就是一级目录,然后方法上的就是二级目录。在我现在做的SpringBoot中,大部分是写的GetMapping和PostMapping注解。

有几个重要属性

  1. value和path是一个东西,就是写路径
  2. method指定请求方法,post get,如果写成GetMapping和PostMapping也就不太需要这个属性了
  3. header指定请求头,没遇到过。
  4. params就是指定要有什么参数传过来。在现在做的项目里很多路径传参,其实是在方法的形参里面加入@PathVariable("")来替换params的,个人理解。比如会这么写:
@PostMapping(value="delete/{id}")
Public String deleteByPrimaryKey(@PathVariable("id") Long id){
    //...
}

其实我一般会用GetMapping,不知道为什么别人在这里写的是PostMapping,有知道的同学麻烦解释一下。反正这么用貌似也可以用。

参数绑定**(封装数据)

参数绑定首先理解键值对的概念,K V,Key就是名称Value就是这个名称对应的值。MVC通过变量的名字来自动绑定。不过这种情况只是传递几个值的简单情况,记住通过该名字绑定就行了。

大部分时候都是把数据封装成javabean,用对象来接收。

  • 前端input之类的name和对象字段名对应即可
  • 引用类型的封装:如果javaBean中还有一个JavaBean对象,前端命名为javabean1.javebean2field
  • 集合:主要是前端命名要改,List[0].field  Map['key'].field
    • 有的时候对象里面还会有对象,比如accout是一个类,里面还包含了很多User对象。一般装这些User对象,使用List,比如List<User> list,使用Map<String,User> map。

post请求中文会乱码。// request.serCharacter

  • 但是springmvc提供了过滤器可以解决这个问题,在web.xml中配置一个CharacterEncodingFilter来拦截请求处理乱码。

自定义类型转换

和我另外一篇写日期的处理的博客相关。自定义类型转换主要是除了一些基本数据类型,别的数据类型接受时容易出问题,要规定它们接受的方式所以诞生出自定义类型转换。

  • 其实SpringMVC使用自定义类型转换器还挺麻烦的,首先要写自定义转换类,实现一个接口,复写方法。然后去springmvc中配置自定义转换器,配置自定义转换器,只是配置了这个组件和自己写的转换类没关系,所以还要在其中把自己写的转换类注册进去。
  • 再在开启springmvc的annotation-driven中把转换器加进去 conversion-service="conversionService"
  • springboot中就会简单很多,@DateTimeFormat和@JsonFormat就可以解决日期格式的问题

@RequestParam

这个注解是写在形参前面的。里面有name和value属性,作用一样。required表示是否一定需要这个参数。它主要的功能是让前端传来的值和后端名字不同的属性进行封装。(@RequestParam(value="name") String userName)这样name和userName字段就能封装了。不然后端接会因为前后端名称不同而接收不到。

@RequestBody

这是一个超级重要的注解。获取请求体中的参数。

真实开发中,很多数据都是封装成对象来使用的,封装成java对象也就需要这个注解来将请求体中的键值对和对象字段绑定起来。

表单传来一个个属性,然后形参用对象用对应的属性接收,对象前面就写@RequestBody。

@PathVariable就是获得/xx/{xx}路径中的变量

@RequestMapping("/xx/{id}")
public String xx(@PathVariable(value="uid") Integer id){
    //...
}

HiddenHttpMethodFilter

可以让表单中某一个字段变成另外一种请求方式。在现在做的项目里,也有看到PostMapping注解下却传递了id,用路径传递,所以猜测是不是使用这个技术。后面再做详细了解。

@CookieValue注解

@CookieValue(value="JSESSIONID") String cookieValue

@ModelAttribute

请求发出,先执行有这个注解的方法再执行请求方法

这种情况一般是修改数据,其实可以前端把所有的数据先填充进去,然后用户选择要修改的字段修改即可,这样一些不做修改的字段不会有变化。

  • 写法一:方法有返回值,返回对象

  • 方法二:不写返回值,在map中装对象,然后在需要这个对象的方法中形参上加上@ModelAttribute("key")来获取对象

@SessionAttributes

  • 这个注解用在类上面,意味着将一个值存入session域中(这里之前说了一堆和request域相关的,没怎么理解)

  • 一个方法添加了另外一个方法可以取到(存值和取值)

  • 清除session中的参数(设置完成方法)

响应之返回值是void

在这里面介绍了一个概念,请求转发一次请求,不用编写项目的名称。我理解的是点击执行一个方法,这是一个请求,然后return返回一个字符串,这是转发一次请求。它们都经过视图解析器,所以不用写项目的名称之类的。

但是自己(写转发)调用前端控制器是不会被视图解析器解析的,所以需要加上项目名称

总结就是,其实都是要写项目名称的。但是谁经过视图解析器谁就不用写视图解析器的前缀和后缀,视图解析器负责了,关键看视图解析器负不负责这个请求。

  • 重定向请求,重定向是再发一次请求(重定向没办法直接进入WEB-INF)

  • 直接进行响应

响应之返回ModelAndView(用ModelAndView做跳转)

这和return一个字符串,然后视图解析器去解析这个字符串然后返回页面是一样的,甚至modelAndView都是经过视图解析器的,所以路径不用写项目名。

这其实就是return字符串的底层实现。ModelAndView是SpringMVC提供的一个对象。

关键字进行转发

forward关键字不经过视图解析器,所以路径要写全路径

  • forward关键字(请求转发)

  • redirect(重定向):redirect重定向关键字底层加上了项目名称(前面也讲到了重定向不是过response重定向,那种重定向是原始的所以就要加项目前缀,这种关键字是封装好然后拿来用的所以就不需要),不需要再加项目名称,重定向无法直接进入WEB-INF目录。

解决静态资源被拦截

@ResponseBody的一些新理解

之前只知道ResponseBody这个注解可以绕过视图解析器,向前端返回字符串。这才知道原来,它是封装后端传到前端的数据,使其变成json字符串。我之前一般写在类上面。

这个注解有组合注解,@RestController就是@ResponseBody和@Controller组合的注解。前后端分离项目中经常使用这个注解,放在类上面。然后类中的方法都是返回对象,通过@ResponseBody封装成json字符串返回给前端。

我的大概理解@RequestBody是将前端传来的键值对封装成对象,@ResponseBody将后端返回的对象封装成json字符串给前端。

 

以上就是所有响应的内容了,前面主要说的是请求进来和返回什么回去的问题。

 

文件上传

原始的文件上传方法(JavaWeb的方式)

解释这个multipart/form-data属性。原来表单内部都是xxx=xxx&xx=xx这样的键值对。但是用这个属性之后表单被划分成很多部分(分成很多部分,这也就直接导致需要解析到底哪部分是文件)

如果使用Get方法,必须加到路径上,而URL是有限的,所以用post。

  • 文件上传组件(这个无论原始方法还是springmvc都需要这个组件,具体功能还不太理解,只知道是规定了写入文件的路径)

原始方法的实现代码

  • 首先这是负责上传路径,springmvc方法也需要这部分

  • 这块就是有一个解析,因为前端传来的所有数据都是在request请求中,所以要解析request请求中的上传文件项。springmvc也就是简化了这一步,不需要解析,直接可以获得上传文件项目,然后对上传文件想进行操作即可。

  • 名字增加uuid

SpringMVC文件上传功能

配置文件解析器

 

这个视频之前说了原始的文件上传的方法,大概理解如下

  • 表单提交,一般表单提交都是键值对。
  • 有文件的话,其要解析文件上传。把这个解析出来,原始的方式需要手动,但是springmvc就提供了解析的方法,就是这个文件解析器。

文件解析器是解析request,在原始的方法要自己去便利request请求,然后找到上传文件项目。文件解析器是解析request然后直接提供文件上传项目。

 

MultipartFile是SpringMVC提供的对象,就是用来装文件上传项的。

 

 

 

springmvc文件上传的实现代码 

 

上面一部分是判断路径是否存在,如果不存在就创建这个文件夹。下面才是获得上传文件名字,给名字加UID避免同名文件覆盖,然后保存文件。比起传统的上传,也不需要删除临时文件。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值