springmvc最详细的开发流程(下)

前面一章节:springmvc最详细的开发流程(上) 

链接: springmvc最详细的开发流程(上)-CSDN博客

一、路径注解及参数设置

1.1. @RequestMapping细节介绍

默认情况:只要地址正确,不写请求方式都可以访问

不符合请求方式:报错405

1.2. param和json的区别

  • 格式:

param:key = value & key = value

json:(key:value,key:value)

  • 参数编码:

param是ASCII编码,所以中间有空格都会变为&,例如:node js,会被编码为node&js

josn是utf-8的编码格式

  • 顺序限制:

param没有顺序限制,json需要讲究顺序

  • 嵌套性:

param没有嵌套,而json是可以多层嵌套的

1.3. Json数据接收

        1.3.1.创建一个类,使用json格式接收数据

        1.3.2. 使用postman调用,发现报错信息415

        1.3.3. “415”是不支持数据类型错误,为啥?

原因:java原生的api只支持路径参数和param参数,也就是request.getParameter("key"),不支持json;json是前端的格式。

解决方法:1.导入json处理的依赖;2.handlerAdapt配置json转换器,依次完成以上两部,就可以解决json返回的问题。

  • 前置准备:导入jackson依赖,为的是下文的@EnableWebMvc注解可以使用
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.0</version>
</dependency>
  • 添加json数据转化器,使用@EnableWebMvc注解,同时,去掉SpringMvcConfig中原有的两个方法
@EnableWebMvc  //json数据处理,必须使用此注解,因为他会加入json处理器,同时它还会配置handlerMapping和handlerAdapt
@Configuration
@ComponentScan(basePackages = "com.samcode.controller") 
public class SpringMvcConfig implements WebMvcConfigurer {}

完成上面两个步骤,就可一解决415异常码的问题。

二、共享域的对象操作

  2.1.回顾共享域

在 JavaWeb 中,共享域指的是在 Servlet 中存储数据,以便在同一 Web 应用程序的多个组件中进行共享和访问。常见的共享域有四种:ServletContext、HttpSession、HttpServletRequest、PageContext。

简单来说,我想从servlet1跳转或重定向到servlet2,我们跳转和重定向是无法直接携带数据的,所以我们会存到一个共享空间。

在Java Servlet技术中,确实存在四种常见的共享域对象,括号中代码作用范围

 1. ServletContext(整个项目):

        - 是一个全局的、与整个Web应用程序(或Servlet容器)相关的共享区域。 - 存储在ServletContext中的数据在整个应用生命周期内对所有用户可见,并且可以跨多个请求和响应共享。 - 重定向和转发时,由于ServletContext是全局作用域,所以存储的数据仍然可以访问。

 2. HttpSession(一次会话的一个浏览器多次请求):

        - 提供了基于用户的会话级别的存储空间,每个用户都有独立的HttpSession对象。 - 在一次会话的多次请求和响应之间可以共享数据,但不是全局共享,只对该特定会话的用户有效。 - 转发时,由于请求仍属于同一会话,因此可以在转发前后访问HttpSession中的数据;重定向时,浏览器收到新的URL并发起新请求,但仍可以通过包含session ID的cookie来保持会话状态,从而访问到相同HttpSession中的数据。

 3. HttpServletRequest(一次请求/转发):

        - 表示单次HTTP请求,它提供了一个请求作用域的共享区域。 - 请求作用域内的数据只能在当前请求和响应过程中使用,一旦请求结束,这些数据就会失效。 - 在请求转发场景下,请求对象从一个Servlet传递到另一个Servlet时,其属性可以在转发链路上共享。但在重定向后,原请求对象会被丢弃,新请求会产生一个新的HttpServletRequest对象,所以原请求携带的数据不会自动传递给新的请求。

 4. PageContext:

        - 是JSP页面的上下文对象,它封装了与当前页面执行相关的所有四个作用域(page、request、session、application),并提供了在这些作用域之间存取数据的方法。 - PageContext的作用域局限于当前JSP页面及其嵌套的包含页,如果涉及到页面之间的转发或重定向,那么该作用域下的数据通常无法在目标页面直接获取。

        总结来说,对于转发操作,不同作用域的对象可以实现一定程度的数据共享;而对于重定向,由于创建了新的请求,只有HttpSession这种会话级作用域能够在重定向后继续保持数据的有效性。请求本身(即HttpServletRequest)不支持迭代数据,它的生命周期仅限于一次HTTP请求-响应过程。

  2.2.代码

三、springmvc的开发模式框架(重点)

  3.1.混合开发模式

  • 流程:

前端浏览器访问我们的程序—>依次经过三层架构获取到数据再return回到controller—>将数据存储在共享域中—>模板页面在共享域中取数据—>返回浏览器

  • 总结:三层架构+模板语言(jsp/Thymeleaf)
  • 优势:项目小,需要全栈,成本低
  • 劣势:只能访问html,也就是浏览器访问,其他端无法访问(app,ios,webchat小程序)

3.2. 前后端分离模式

  • 优势:后端可更加注重业务逻辑,后续可扩展性强,可做微服务,分布式
  • 劣势:项目大、成本高

四、配置视图解析器

 4.1. 配置类中实现接口

说明:在配置类中实现接口WebMvcConfigurer,重写configureViewResolvers方法,添加前后缀即可。

 4.2. 创建jsp文件

 4.3. 新建Controller,并启动项目访问改controller路径

注意:该controller不能有@RequestBody注解,否则回返回字符串给浏览器。没有这个注解的情况下是返回视图名称找到视图。

@Controller
@RequestMapping("/view")
public class ViewController {

    @RequestMapping(value = "/jsp")
    public String viewJsp() {
        System.out.println("jsp");        
        return "index";    
        }
}

五、转发和重定向写法:

 5.1. 使用spring mvc的写法如下:

下面这两个方法最后都是去访问

localhost:端口/项目上下文路径/view/jsp这个路径

//转发
@RequestMapping(value = "/forward")
public String forward() {
    return "forward:/view/jsp";
    }
//重定向,可以为内部资源,也可以为外部资源,如果是外部资源就写全路径
@RequestMapping(value = "/redirect")
public String redirect() {
    return "redirect:/view/jsp";
    }

5.2. 不使用springmvc写法,也就是用request和response对象api

  • 转发:可以省略全路径的写法,直接写 /jsp/index
  • 重定向:不可省略,必须写全路径。

5.3. @ResponseBody

只要使用了该注解,快速查找视图,转发和重定向都不生效了。

六、静态资源的访问(路径直接访问)

 6.1. 新建静态资源文件直接路径访问

6.2. 启动项目,访问资源

http://localhost:7774/springmvc/images/sun.png

发现该路径访问后404,找不到资源

6.3. 原因及解决办法

  • 原因:

springmvc处理路径的时候,都是先交给dispatcherservlet,然后再将请求交给handlerMapping,找类中的方法又没有这个路径的,没有就是404。所以路径找的是Handler,而不是一个资源。

  • 解决:

实现的WebMvcConfigurer接口中,重写另外一个方法configureDefaultServletHandling,并调用enable()。说明:请求先找dispatcherservlet,接着找handlerMapping,没有匹配到就继续找静态资源。

七、Restful风格开发

内容较少,较为基础,本片暂不介绍

八、异常处理及拦截器

  8.1. 异常类型

  • 编程式异常处理:是指在代码中显式地编写处理异常的逻辑。它通常涉及到对异常类型的检测及其处理,例如使用 try-catch 块来捕获异常,然后在 catch 块中编写特定的处理代码,或者在 finally 块中执行一些清理操作。在编程式异常处理中,开发人员需要显式地进行异常处理,异常处理代码混杂在业务代码中,导致代码可读性较差。
  • 声明式异常处理:则是将异常处理的逻辑从具体的业务逻辑中分离出来,通过配置等方式进行统一的管理和处理。在声明式异常处理中,开发人员只需要为方法或类标注相应的注解(如 @Throws 或@ExceptionHandler),就可以处理特定类型的异常。相较于编程式异常处理,声明式异常处理可以使代码更加简洁、易于维护和扩展。

8.2. 声名式异常的开发

        8.2.1. 新建全局异常处理类

/** * 全局异常类,发生异常会走该类 
* @author SamY 
* @date 2024/01/25 
*/
//@ControllerAdvice 可以返回逻辑视图
@RestControllerAdvice  // 可以返回json,该注解就是 @ResponseBody + @ControllerAdvice
public class GlobalExceptionHandler {
    /**     
    * 当发生空指针异常会触发此方法!     
    */    
    @ExceptionHandler(NullPointerException.class)
    public Object handlerNullException(NullPointerException e){
        return e.getMessage();    
        }

    /**     
    * 所有异常都会触发此方法!但是如果有具体的异常处理Handler!     
    * 具体异常处理Handler优先级更高!     
    */    
    @ExceptionHandler(Exception.class)
    public Object handlerException(Exception e){
        return e.getMessage();    
        }
}

8.2.2. @ComponentScan注解扫描需要加上异常类所在的包

九、拦截器

9.1. 过滤器和拦截器的区别:

  • 作用范围:

如上图所示,过滤器的拦截范围是请求还在springmvc外部时,而拦截器HandlerInterceptor是在springmvc内部作用,具体是在调用Handler之前和之后,还有在总体处理完毕最后。也就是过滤器能够拦截到的是整个项目,拦截器拦截是springmvc负责的请求。

  • 适用项目:

过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web程序中使用。而拦截器(Interceptor) 它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。

  • 拦截请求类型:

过滤器几乎可以对所有进入容器的请求起作用,而拦截器只会对Controller中请求或访问static目录下的资源请求起作用。例如:直接请求直接访问静态资源拦截器就不拦截了。

  • 注入情况Bean不同:

拦截器加载的时间点在springcontext之前,而Bean又是由spring进行管理。所以,在实现了过滤器接口的类中去使用依赖注入是无效的,会有空指针异常。

9.2. 代码案例:

        9.2.1. 新建拦截器类

public class MyInterceptor implements HandlerInterceptor {
    //到达目标方法前    
    @Override    
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("request = " + request + ", response = " + response + ", handler = " + handler);        
        System.out.println("Process01Interceptor.preHandle");        
        // 返回true:放行        
        // 返回false:不放行        
        return true;    
        }
    //到达目标方法后    
    @Override    
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("request = " + request + ", response = " + response + ", handler = " + handler + ", modelAndView = " + modelAndView);        
        System.out.println("Process01Interceptor.postHandle");    }
    // 渲染视图之后执行(最后),一定执行!    
    @Override    
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("request = " + request + ", response = " + response + ", handler = " + handler + ", ex = " + ex);        
        System.out.println("Process01Interceptor.afterCompletion");    }
}

        9.2.2. MvcConfig类中实现接口WebMvcConfigurer(之前已经做过)

重写方法

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new MyInterceptor());}

本章结束,下章转至ssm框架介绍

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值