Java22-SpringMVC

95 阅读9分钟

Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。

一、流程

  • 用户发送请求到前端控制器DispatcherServlet(调度servlet,底层就是servlet)

  • DispatcherServlet收到请求调用HandlerMapping处理器映射器

  • 处理器映射器根据请求url找到具体的处理器(对应代码中的Controller),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet

  • DispatcherServlet通过HandlerAdapter(找到与之controller对应的类)处理器适配器调用处理器,执行处理器(Controller,也叫后端控制器)。

  • Controller执行完成返回ModelAndViewHandlerAdapter

  • HandlerAdapter将Controller执行结果ModelAndViewDispatcherServlet

  • DispatcherServlet将ModelAndView传给ViewReslover视图解析器

  • ViewReslover解析后返回具体给DispatcherServlet具体的View

  • DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)

  • DispatcherServlet响应用户

总结:
首先有请求来,经过tomcat服务器,进入里面的servlet进行处理。这里是DispatcherServlet,用来调度servlet
不同的请求具有不同的处理器来处理,DispatcherServlet接收到请求调用HandlerMapping处理器映射器
处理器根据请求的url找到具体的处理器,生成处理的对象,返回给DispatcherServlet
DispatcherServlet通过HandlerAdapter处理器适配器调用处理器,执行处理器,处理处理器对象
处理完之后,返回处理后的结果ModelAndView

可以看出来,只有DispatcherServlet有处理的功能
调用HandlerMapping处理器映射器找到处理器的对象
转交通过HandlerAdapter处理,执行对应的处理器的对象
从上面可以看出,DispatcherServlet有接收请求,响应结果,转发等作用。有了DispatcherServlet之后,可以减少组件之间的耦合度。

SpringMVC的优点:

  1. 可以支持各种视图技术,而不仅仅局限于JSP;

  2. 与Spring框架集成(如IoC容器、AOP等);

  3. 清晰的角色分配:前端控制器(dispatcherServlet) , 请求到处理器映射(handlerMapping), 处理器适配器(HandlerAdapter), 视图解析器(ViewResolver)。

SpringMVC的主要组件

1. 前端控制器 DispatcherServlet(不需要程序员开发)

作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。

2. 处理器映射器HandlerMapping(不需要程序员开发)

作用:根据请求的URL来查找Handler

3. 处理器适配器HandlerAdapter

注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。

4. 处理器Handler(需要程序员开发)

5. 视图解析器 ViewResolver(不需要程序员开发)

作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view)

6. 视图View(需要程序员开发jsp)

View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)

springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法地形参,可以设计为单例或多例(建议单例),

二、SpringMVC笔记

MVC框架要做的事情?

  • 将url映射到java类或java类的方法 (写的hello,映射到helloServlet)
  • 封装用户提交的数据 ()
  • 处理请求--调用相关的业务处理--封装响应数据
  • 将响应的数据进行渲染、jsp/html等表示层数据

2.1 复习servlet

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1、获取请求,得到前端参数
        String method=req.getParameter("method");
        if(method.equals("add")){
            req.getSession().setAttribute("msg","执行了add方法");
            //session就像map一样的进行保存数据
            //意思是获得session,设置属性级对应的key value
        }
        if(method.equals("delete")){
            req.getSession().setAttribute("msg","执行了delete方法");
        }
        //2、调用业务层
        //3、视图转发或重定向
        req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);
        resp.sendRedirect("/WEB-INF/jsp/hello.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //这样的作用实现复用
        doGet(req,resp);
    }
}

回顾
请求转发\ (正常使用的话请求转发使用的较多) 用户先通过浏览器访问 oneServlet,但是 oneServlet 不能解决用户的问题。于是 oneServlet 将 request 对象和 response 对象传递给 TwoServlet,然后 twoServlet 去处理用户的请求。
其实请求转发就相当于你去找刘备借钱,刘备一摸兜没钱,但是刘备这人挺仗义,他就带着你去找曹操借钱,最后你从曹操那里借到了钱。
不会放弃带着你,拿着你的对象\

格式为:
req.getRequestDispatcher("URL对应的文件的路径").forward(req.resp);

重定向
则是响应另一个界面,response.SendRedirect(“”),转达到另一个页面
你去找刘备借钱,刘备一摸兜没钱,然你去找小红借钱,重新响应到另外一个界面,不携带之前的对象

格式为:
resp.senfRedict("URL对应的文件的路径");

2、将servlet注册到web.xml中,让URL路径和资源进行映射

<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servler-mapping>

通过媒介servlet,将servlet的class和url进行映射,去执行servlet.class里面的代码,进行跳转.jsp文件
补充servlet的其他配置,配置欢迎页,和session的过期时间

<session>
    <session-timeout>15</session-timeout>
</session>
<welcome-file-list>
    <welcome-file>index.jsp<welcome-file>
</welcome-file-list>

2.2 SpringMVC初学

Spring:可以将SpringMVC的bean注入到容器中\

  • Spring的核心
  • DispathweServlet
  • 处理器的映射器
  • 处理器的适配器
  • 视图解析器 (Thymeleaf) controller返回的modeleAndView

补英语:prefix 前缀 suffix后缀

2.3 使用注解进行开发

@Controller
@RequestMapping("/hello")
public class HelloController {

    //真实访问地址 : 项目名/hello/h1
    @RequestMapping("/h1")
    
    public String hello(Model model) {
        //封装数据
        //向模型中添加属性msg与值,可以在JSP页面中取出并渲
        model.addAttribute("msg","HelloSpringMVCAnnotation");
        //返回视图
        //web-inf/jsp/hello.jsp
        return "hello";   //会被视图解析器处理
    }
}

@Controller是为了让Spring IOC容器初始化时自动扫描到;

@RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该 是/HelloController/h1;

方法中声明Model类型的参数是为了把Action中的数据带到视图中;

方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.js

后面在前端页面,使用${msg}进行获取相关加入视图中的信息

  • 重要:之前是Controller执行完之后需要需要返回视图,这里使用Model model,进行封装数据,返回给ModelAndView

2.4 RestFul和控制器

控制器Controller

  • 控制器复杂提供访问应用程序的行为,通常通过接口定义注解定义两种方法实现。
  • 控制器负责解析用户的请求并将其转换为一个模型。
  • 在Spring MVC中一个控制器类可以包含多个方法
  • 在Spring MVC中,对于Controller的配置方式有很多种

注解的使用
@Controller

@ResquestMapping (一般放在类上,方法与专门的注解)

  • @RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

方法级别的注解变体有如下几个:组合注解

@GetMapping  一般GetMapping使用的较多一点
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping

路径的变量
@PathVariable //@PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中

//这里URL上的占位符和形参相同,相同时可以将@PathVariable("name")的name去掉
@RequestMapping("/getUserById/{name}")
    public User getUser(@PathVariable("name") String name){
        return userService.selectUser(name);
    }


@RequestMapping("/getUserById/{name}")
    public User getUser(@PathVariable("name") String userName){
        return userService.selectUser(userName);
    }
    

@Controller
public class RestFulController {
​
   //映射访问路径
   @RequestMapping("/commit/{p1}/{p2}")
   public String index(@PathVariable int p1, @PathVariable int p2, Model model){
       
       int result = p1+p2;
       //Spring MVC会自动实例化一个Model对象用于向视图中传值
       model.addAttribute("msg", "结果:"+result);
       //返回视图位置
       return "test";
       
  }  
}

http://localhost:8080/commit/1/2

//则跳转到页面返回的是3

RestFul风格
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。 传统方式操作资源 :通过不同的参数来实现不同的效果!方法单一,post 和 get

http://127.0.0.1/item/queryItem.action?id=1 查询,GET

http://127.0.0.1/item/saveItem.action 新增,POST

http://127.0.0.1/item/updateItem.action 更新,POST

http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST

使用RESTful操作资源 :可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!

http://127.0.0.1/item/1 查询,GET

http://127.0.0.1/item 新增,POST

http://127.0.0.1/item 更新,PUT

http://127.0.0.1/item/1 删除,DELETE

2.5 JSON

前后端分离的时代:

  • 后端部署后端,提供接口

数据交换的格式JSON - 采用完全独立于编程语言的文本格式来存储和表示数据。

  • 前端独立部署,负责渲染后端的数据

在 JavaScript 语言中,一切都是对象。因此,任何JavaScript 支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。看看他的要求和语法格式:

  • 对象表示为键值对,数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组

2.6 Ajax

AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。

AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。

2.7拦截器

SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。

过滤器与拦截器的区别:拦截器是AOP思想的具体应用。

过滤器

servlet规范中的一部分,任何java web工程都可以使用

在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截

拦截器

拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用

拦截器只会拦截访问的控制器方法, 如果访问的是jsp/html/css/image/js是不会进行拦截的

public class LoginInterceptor implements HandlerInterceptor {
​
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果是登陆页面则放行
        System.out.println("uri: " + request.getRequestURI());
        if (request.getRequestURI().contains("login")) {
            return true;
        }
​
        HttpSession session = request.getSession();
​
        // 如果用户已登陆也放行
        if(session.getAttribute("userLoginInfo") != null) {
            return true;
        }
​
        // 用户没有登陆跳转到登陆页面
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
        return false;
    }
}
  • 实现了HandlerInterceptor接口,里面有preHandle方法