SpringMVC学习笔记

本文详细介绍了SpringMVC中如何获取请求参数,包括通过ServletAPI、形参、注解如@RequestParam、@RequestHeader和@CookieValue。同时讨论了RESTful风格的请求映射、HttpMessageConverter的作用以及文件上传和下载的实现。还涵盖了SpringMVC的视图、拦截器和RESTful设计原则。
### 4、SpringMVC的执行流程

1) 用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获。

2) DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI),判断请求URI对应的映射:

a) 不存在

i. 再判断是否配置了mvc:default-servlet-handler

ii. 如果没配置,则控制台报映射查找不到,客户端展示404错误

![image-20210709214911404](img/img006.png)

![image-20210709214947432](img/img007.png)

iii. 如果有配置,则访问目标资源(一般为静态资源,如:JS,CSS,HTML),找不到客户端也会展示404错误

![image-20210709215255693](img/img008.png)

![image-20210709215336097](img/img009.png)

b) 存在则执行下面的流程

3) 根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain执行链对象的形式返回。

4) DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。

5) 如果成功获得HandlerAdapter,此时将开始执行拦截器的preHandler(…)方法【正向】

6) 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:

a) HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息

b) 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等

c) 数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等

d) 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中

7) Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象。

8) 此时将开始执行拦截器的postHandle(...)方法【逆向】。

9) 根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据Model和View,来渲染视图。

10) 渲染视图完毕执行拦截器的afterCompletion(…)方法【逆向】。

11) 将渲染结果返回给客户端。
浏览器发送请求,若请求地址符合前端控制器的url-pattern,该请求就会被前端控制器DispatcherServlet处理。
前端控制器会读取SpringMVC的核心配置文件,通过扫描组件找到控制器,将请求地址和控制器中@RequestMapping
注解的value属性值进行匹配,若匹配成功该注解所标识的控制器方法就是处理请求的方法。处理请求的方法需要返回
一个字符串类型的视图名称,该视图名称会被视图解析器解析,加上前缀和后缀组成视图的路径,通过thymeleaf对视
图进行渲染,最终转发到视图所对应页面

@RequestMapping
(1)value属性



(2)method属性,设置方法属性后,不符合方法属性的请求会出现405错误,
get:<a th:href="@{/test}> //get可以链接访问,post不可以,不可以传文件
/post: <form th:action="@{/test}" method="post"> //post

提供了派生注解getMapping
get,post,put,delete等,form表单不支持put请求,默认按get处理

(3)param属性通过请求参数匹配请求映射

param:要求请求映射所匹配的请求必须携带param请求参数

!param:要求必须不携带请求参数

param=value要求请求所匹配的请求必须携带param请求参数且param=value

param!=value同上但param!=value,参数不匹配报错400

(4)headers(k-v)

同param四种,可用于网站页面内超链接访问,而不是直接访问,当初爬微博热搜还要讲headers里面的cookie加进去才可用requests访问,selenium无关,

若满足value和method但无headers会报404错误

springmvc支持ant风格的路径  *通配符、?占位符(?,/,\不能匹配需要转义:可能需要,暂未测试),**表示一层或多层目录a**a表示只能是两个通配符,必须要在/**/使用

SpringMVC支持路径中的占位符(restful)

原始:/deleteUser?id=1

rest方式:/deleteUser/1

@RequestMapping("testRest/{id}/{username}")

--------————————————————————————————

SpringMVC获取请求参数(

问题1:SpringMVC在请求controller方法结束后如果不进行显示别的页面就会报错的问题

2.是用RequestMapping来操控各种html页面)

1.通过servletAPI获取

将HttpServletRequest参数作为形参

2.通过形参获取

@RuquestParam设置方法形参接受RequestParam设置的请求参数名

@RequestHeader k-v类型将请求头信息和形参创建映射关系,赋值给方法形参,

形参=请求头某个参数的值

@CookieValue 将请求cookie信息和形参形成映射关系 cookie->形参;形参=cookie;

此上三个用法相同

value属性设置请求携带时的名字,required默认为true如果请求不带参数且没有设置defalutvalue则报错400,false则带不带无所谓,defalutvalue表示请求没有参数时默认值

 sessio依赖于cookie,每次getsession都会创建键为gsession的cookie,第一次执行getsession Cookie 存在于响应报文中,以后存在于请求报文中

传递pojo参数(pojo就是简单的bean),在bean中的属性名和请求页面中的input的name属性要一致

乱码问题:get不会出现乱码tomcat解决了get请求的乱码问题,但没解决post请求,通过characterEncodingFilter,servletContext加载时间最早,然后是过滤器->servlet

域对象共享数据

context request session pagecontext

(1)原生HTTPServletRequest可以共享request数据(request域)

四种方式

<a th:href="@{/testRequestByServlet}">通过servletAPI向requestScope传递共享数据//原生方式</a><br> <a th:href="@{/testModelAndView}">通过ModelAndView向requestScope传递共享数据//ModelAndView方式</a><br> <a th:href="@{/testModel}">通过Model向requestScope传递共享数据//Model方式</a><br> <a th:href="@{/testMap}">通过Map向requestScope传递共享数据//Map方式</a><br> <a th:href="@{/testModelMap}">通过ModelMap向requestScope传递共享数据//ModelMap方式</a><br>

SpringMVC的视图

1.thymeleafView

当孔子起方法中所设置的视图名称没有任何前缀时,此时的视图名称会被SpringMVC配置文件中的视图解析器解析,视图名称拼接视图前缀和视图后缀所得到的最终路径,会通过转发的方式实现跳转

2.转发视图

SpringMVC中默认的转发视图时internalResourceView

forward:/newurl

3.重定向视图

redirect:/newurl

4.视图控制器:当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理器方法使用view-controller标签进行表示

转发和重定向区别

1、请求次数

重定向是浏览器向服务器发送一个请求并收到响应后再次向一个新地址发出请求,转发是服务器收到请求后为了完成响应跳转到一个新的地址;重定向至少请求两次,转发请求一次;

2、地址栏不同

重定向地址栏会发生变化,转发地址栏不会发生变化;

3、是否共享数据

重定向两次请求不共享数据,转发一次请求共享数据(在request级别使用信息共享,使用重定向必然出错);

4、跳转限制

重定向可以跳转到任意URL,转发只能跳转本站点资源;

5、发生行为不同

重定向是客户端行为,转发是服务器端行为;

RestFul(一种开发风格)

Rest:表现层,Representational state Transfer,表现层资源状态转移。

a->资源

资源是一种看待服务器的方式,即,将服务器看作是由很多离散的自愿组成,每个资源是服务器上一个可命名的抽象概念。因为资源是一个抽象的概念,所以他不仅仅能代表服务器文件系统中的一个文件,数据库中的一张表等等具体的东西,可以将资源设计的要多抽象有多抽象,只要想象力允许客户端应用开发者能够理解。与面向对象设计类似,资源是以名词为核心来组织的,首选关注的是名词,一个资源可以由一个或多个URl来标识,URI既是资源的名称,也是资源在web上的地址,对某个资源感兴趣的客户端应用,可以通过资源的URI与其进行交互

b->资源的表述

资源的表述是一段对于资源在某个特定时刻的状态的描述,可以在客户端-服务端之间转移(交换)。资源的表述可以有多种格式,例如html,XML/json/纯文本/图片/视频/音频等等。资源的表述格式可以通过协商机制来确定。请求->相应方向的表述通常使用不同的格式。

c->状态转移

在服务端和客户端之间转移transfer代表资源状态的表述,通过转移和操作资源的表述,来简洁实现操作资源的目的。

2.restFul的实现

通过各种类型请求来实现各种请求对应的操作

get:获取资源

post:新建资源

put:更新资源

​​​​​​​delete:删除资源

首先交由DispatcherServlet处理,处理不了则交给DefalutServlet处理

HttpMessageConverter

报文信息转换器,将请求报文转换为java对象,或将java对象转换为响应豹纹HttpMessageConverter提供了两个注解和两个类型,@RequestBody3(请求体),@ResponseBody(响应体),RequestEntity,ResponseEntity

(1)RequestBody(在方法形参标注赋值给一个形参)

@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String requestBody,String username) {
    System.out.println(username);
    System.out.println(requestBody);
    return "success";
}

:username=%E5%BC%A0%E4%B8%89&password=11
 

(2)RequestEntity:

@RequestMapping("/testRequestEntity")
public String testRequestEntity(RequestEntity<String> requestEntity) {
    System.out.println("requestBody:" + requestEntity.getBody());
    System.out.println("requestHeaders:" + requestEntity.getHeaders());
    System.out.println("method:" + requestEntity.getMethod());
    System.out.println("url:" + requestEntity.getUrl());
    System.out.println("enetity:" + requestEntity);
    return "success";
}

enetity:<GET http://localhost:8080/MVCDemo4/testRequestEntity,[host:"localhost:8080", accept:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", upgrade-insecure-requests:"1", cookie:"Pycharm-be7acd86=7f85a34d-541b-4f65-88dd-2c2f0a8d488f; Idea-a54192fa=1baafb09-86ba-4caa-8af0-e551e91c0921", user-agent:"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Safari/605.1.15", accept-language:"zh-CN,zh-Hans;q=0.9", accept-encoding:"gzip, deflate", connection:"keep-alive"]>

(3)@ResponseBody(响应体)在方法上标注

@RequestMapping("/testResponseBody") @ResponseBody//标记方法返回的是数据,而不是视图名称 public String testResponseBody() { return "success";//返回的相当于print输出的数据,而不是视图名称 }

jackson依赖,开启mvc注解,此时在HandlerAdaptor中会自动装配一个小时转换器:MappingJackson2HttpMessageConverter,可以使将浏览器对象返回值转换为json


微服务中每个方法都要加@ResponseBody,json是一种数据交互格式,浏览器和服务器以后都普遍使用http+json,每一个控制器都使用

@RestController

相当于类加上@Controller,类中方法都加上了@ResponseBody

7.ResponseEntity

ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值i就是响应到浏览器的响应报文

文件上传和下载

1.文件下载

@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
    //获取ServletContext对象
    ServletContext servletContext = session.getServletContext();
    //获取服务器中文件的真实路径
    String realPath = servletContext.getRealPath("/static/img/1.jpg");
    //创建输入流
    InputStream is = new FileInputStream(realPath);
    //创建字节数组
    byte[] bytes = new byte[is.available()];
    //将流读到字节数组中
    is.read(bytes);
    //创建HttpHeaders对象设置响应头信息
    MultiValueMap<String, String> headers = new HttpHeaders();
    //设置要下载方式以及下载文件的名字
    headers.add("Content-Disposition", "attachment;filename=1.jpg");
    //设置响应状态码
    HttpStatus statusCode = HttpStatus.OK;
    //创建ResponseEntity对象
    ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
    //关闭输入流
    is.close();
    return responseEntity;
}

2、文件上传

文件上传要求form表单的请求方式必须为post,并且添加属性enctype="multipart/form-data"

SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息

上传步骤:

上传步骤:

a>添加依赖:

```xml
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
```

b>在SpringMVC的配置文件中添加配置:

```xml
<!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
```

c>控制器方法:

```java
@RequestMapping("/testUp")
public String testUp(MultipartFile photo, HttpSession session) throws IOException {
    //获取上传的文件的文件名
    String fileName = photo.getOriginalFilename();
    //处理文件重名问题
    String hzName = fileName.substring(fileName.lastIndexOf("."));
    fileName = UUID.randomUUID().toString() + hzName;
    //获取服务器中photo目录的路径
    ServletContext servletContext = session.getServletContext();
    String photoPath = servletContext.getRealPath("photo");
    File file = new File(photoPath);
    if(!file.exists()){
        file.mkdir();
    }
    String finalPath = photoPath + File.separator + fileName;
    //实现上传功能
    photo.transferTo(new File(finalPath));
    return "success";
}
```

# 

十、拦截器

拦截器的配置

SPringMVC中的拦截器用于拦截控制器方法的执行

SpringMVC中的拦截器需要实现HandlerInterceptor或者继承HandlerInterceptorAdapte类

SpringMVC的拦截器必须在SpringMVC的配置文件中进行配置

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    System.out.println("firstInterceptor->preHandle");
    return HandlerInterceptor.super.preHandle(request, response, handler);
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
        throws Exception {
    System.out.println("firstInterceptorPostHandler");
    HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
        throws Exception {
    System.out.println("firstInterceptorAfterCompletion");
    HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}

123个方法分别在控制器方法前、后、及视图渲染完毕后执行

ModelAndView 处理模型数据,渲染视图

# 十一、异常处理器

### 1、基于配置的异常处理

SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口:HandlerExceptionResolver

HandlerExceptionResolver接口的实现类有:DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver

SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver,使用方式:

```xml
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
        	<!--
        		properties的键表示处理器方法执行过程中出现的异常
        		properties的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面
        	-->
            <prop key="java.lang.ArithmeticException">error</prop>
        </props>
    </property>
    <!--
    	exceptionAttribute属性设置一个属性名,将出现的异常信息在请求域中进行共享
    -->
    <property name="exceptionAttribute" value="ex"></property>
</bean>
```

### 2、基于注解的异常处理

```java
//@ControllerAdvice将当前类标识为异常处理的组件
@ControllerAdvice
public class ExceptionController {

    //@ExceptionHandler用于设置所标识方法处理的异常
    @ExceptionHandler(ArithmeticException.class)
    //ex表示当前请求处理中出现的异常对象
    public String handleArithmeticException(Exception ex, Model model){
        model.addAttribute("ex", ex);
        return "error";
    }

}
```

# 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值