SpringMVC那些事儿

写在前面:

之前已经介绍过了Mybatis《梳理Mybatis(一)》《梳理 Mybatis(二)》《Mybatis面试题准备+源码分析》Mybatis作为和数据库打交道的一层,给我们操作数据库带来了极大的方便,不用像JDBC那般写那么多繁琐重复毫无意义的代码了而是给我们如德芙一般纵享丝滑,没看过的朋友们建议先去看看哈!作为SSM框架(Spring、SpringMVC、Mybatis)三剑客之一的SpringMVC同样给我们开发带来了很大方便,理解起来也比较通俗易懂M(Model模型)V(View视图)C(Controller控制器)

Ps:M(Model模型)我学习的时候一开始也不好理解什么是模型。对初学者有点抽象。特此解释一下。可以这样理解model是用来从后台封装数据到页面的,比如页面上展示一个“欢迎你,{userName}",你就可以用model封装一个userName进去,model.addAttribute("useNamer”,张三"" );页面就会显示”欢迎你,张三”。言外之意就是后台定义封装的实体类。

目录结构:

|SpringMVC简介

|SpringMVC运行流程

|    |代码说话

|    |    |配置前端控制器

|    |    |配置处理器映射器

|    |    |配置处理器适配器

|    |    |*Handler(处理程序)

|    |    |配置视图解析器

|RESTful风格

|    |简介

|    |特点

|    |参考网址推荐附带单元测试

|Swagger2

|    |介绍

|    |添加Swagger2依赖

|    |创建Swagger2配置类

|    |SwaggerAPI注解详解,以及注解常用参数配置

|    |访问

|    |API文档访问与调试

|Spring Boot对MVC的支持

|    |@RestController

|    |@RequestMapping

|    |@PathVariable

|    |@RequestParam

|    |@RequestBody

SpringMVC简介

强调:MVC的全名Model View Controller不是框架而是一种设计模式。MVC它强制的使用应用程序的输入、处理、和输出分开,这三个核心组件分别处理各自的任务,最典型的MVC模式就是:jsp+servlet+javabean的模式。

分离了控制器(Controller)、模型(Model)、分配器(Adapter)、视图(View)和处理程序对象(Handler,实际上调用的是 Controller 中定义的逻辑)。

springmvc是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合。

Ps:SpringMVC其实还挺简单的,只要清楚了它整个框架的运行流程就知道它是怎么一回事了。这种设计模式工作中普遍会采用。优点如下:

降低各模块之间的耦合性(如果视图层需要改变其代码,修改页面样式,就不涉及到controller和model层代码;如果需要修改业务逻辑,这个时候不需要修改与其相关的view视图代码等)

重用性高:多个视图可以共享一个数据模型,比如pc端下单和移动端下单,虽然订购的方式不一样,但是处理该数据的方式都是一样的。

SpringMVC运行流程

网上找的一张图,已经很详细了。介绍了整个运行的流程。

理解 前端控制器DispatcherServlet、处理器映射器、处理器适配器、视图解析器互相之间调用关系就OK了!!!!

第一步:发起请求到前端控制器(DispatcherServlet)。

第二步:前端控制器请求HandlerMapping查找 Handler,可以根据xml配置、注解进行查找。

第三步:处理器映射器HandlerMapping向前端控制器返回Handler。

第四步:前端控制器调用处理器适配器去执行Handler。

第五步:处理器适配器去执行Handler。

第六步:Handler执行完成给适配器返回ModelAndView。

第七步:处理器适配器向前端控制器返回ModelAndView,ModelAndView是springmvc框架的一个底层对象,包括 Model和view。

第八步:前端控制器请求视图解析器去进行视图解析,根据逻辑视图名解析成真正的视图(jsp)。

第九步:视图解析器向前端控制器返回View。

第十步:前端控制器进行视图渲染,视图渲染将模型数据(在ModelAndView对象中)填充到request域。

第十一步:前端控制器最终向用户响应结果 。

代码说话:

1.配置前端控制器

在web.xml中配置前端控制器。

<servlet>
    <servlet-name>mymvc</servlet-name>
                          <!-- DispatcherServlet前端控制器 -->
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <!--加载 contextConfigLocation配置SpringMVC加载的配置文件 & Spring配置文件-->
      <param-name>contextConfigLocation</param-name>
                      <!-- HandlerMapping 处理器映射 -->      <!-- spring配置文件 -->
      <param-value>classpath:Spring/handlerContext.xml,classpath:Spring/applicationContext.xml</param-value>
    </init-param>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>mymvc</servlet-name>
    <!--第一种 *.action 访问以.action结尾的 由DispatcherServlet进行解析-->
    <!--第二种 / 所有访问的地址都由DispatcherServlet进行解析。
          对于静态文件的解析需要配置不让DispatcherServlet进行解析。
          使用这种方法可以实现RESTful风格的url  -->
    <!--第三种 /* 这样配置不对 使用这种配置 最终要转发到一个jsp页面时
            仍然需要由DispatcherServlet进行解析jsp地址 但是不能根据jsp页面找到Handler 会报错。-->
    <url-pattern>*.action</url-pattern>
  </servlet-mapping>

2.配置处理器映射器

在classpath下的handlerContext.xml中配置处理器映射器。

  • BeanNameUrl处理器映射

<!-- 处理器映射器 handler 之 BeanNameUrl处理器映射 默认处理方式-->
 <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>       
 <bean name="/orders.action" class="controller.Orders_list"></bean>

Ps: id和name都是spring 容器中bean 的唯一标识符。

id:一个bean的唯一标识 , 命名格式必须符合XML ID属性的命名规范

name:可以用特殊字符,并且一个bean可以用多个名称:name=“bean1,bean2,bean3”,用逗号或者分号或者空格隔开。

参考链接:https://blog.csdn.net/q309572960/article/details/90473772

  • 简单url处理器映射

<!-- 处理器映射器 handler 之 SimpleUrl处理器映射-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
  <property name="mappings">
     <props>
        <prop key="/orders.action">homeController</prop>
     </props>
  </property>
</bean>
<bean id="homeController" class="controller.Orders_list"/>

3.配置处理器适配器

在classpath下的handlerContext.xml中配置处理器适配器。

常用的处理器适配器有HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter以及AnnotationMethodHandlerAdapter。

这里配置的处理器是SimpleControllerHandlerAdapter

主要配置如下:

<!-- 处理器适配器Adapter 当前的处理器适配器要求处理器必须实现Controller接口-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>   

通过查看原代码:

SimpleControllerHandlerAdapter适配器支持所有实现了Controller接口的Handler控制器,开发者如果编写了实现Controller接口的控制器,那么SimpleControllerHandlerAdapter适配器会执行Controller的具体方法。

当处理器适配器HandlerAdapter处理了相关的Handler的具体方法之后,Handler会返回一个视图对象ModelAndView。

4.*Handler(处理程序)

需要实现controller接口,才能由org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter适配器执行。

 

处理器~适配器 handlerAdapter ==前端控制器调用处理器适配器去执行Handler==当前的处理器适配器要求处理器必须实现Controller接口==执行完成给适配器返回ModelAndView,再向前端控制器返回ModelAndView。

  • 非注解开发

还是需要在handlerContext.xml配置映射器、适配器、视图解析器

public class Orders_List implements Controller{
  @Override
  public ModelAndView handleRequest(HttpServletRequest arg0,
      HttpServletResponse arg1) throws Exception {
    ……
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.addObject("orders_list",list);
    
    modelAndView.setViewName("jsp/orders_list.jsp");
    return modelAndView;
  }
}
  • 注解开发

不需要在handlerContext.xml中配置映射器、适配器只需要视图解析器帮忙解析页面

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
         <!--  
        modelAndView.setViewName("orders_list");
        modelAndView.setViewName("jsp/orders_list,jsp");
        前缀
        <property name="prefix" value="jsp/"/>
        后缀
        <property name="suffix" value=".jsp"/>
      -->
</bean>

在spring配置文件(applicationContext.xml)中进行添加:

<mvc:annotation-driven/>默认加载很多的参数绑定方法,比如json转换解析器就默认加载了。

<context:component-scanbase-package="controller"/>对于有注解(@Controller。。。)的Handler可以单个配置。实际开发中 建议使用组件扫描。相当于@ComponentScan(basePackages={“”,””})

Ps:使用mvc:annotation-driven代替上边注解映射器和注解适配器配置。就不用配置上边的映射器和适配器。

而在handler里面可以基于注解,对返回值类型自定义,比较灵活。

@Controller
public class Find_Q1 {
  private ApplicationContext ctx;
  @RequestMapping("/f1.do")
  public void f1(HttpServletRequest req, HttpServletResponse res) throws Exception{
    ctx=new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
    
    Q1 dao = ctx.getBean(Q1.class);
    List<Orders> list = dao.q1();
    
    req.setAttribute("find_orders", list);
    req.getRequestDispatcher("jsp/find_orders.jsp").forward(req, res);
  }
  
  @RequestMapping("/f1_2.do")
  public ModelAndView f1_2(HttpServletRequest req) throws Exception{
    ctx=new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
    
    int id = Integer.parseInt(req.getParameter("id"));
    Q1 dao = ctx.getBean(Q1.class);
    List<OrderDetail> list = dao.q1_2(id);
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.addObject("find_detail", list);
    modelAndView.setViewName("find_detail");
    return modelAndView;
  }


  @RequestMapping("/getItems.action")
  public String getItems(Model m,int id) throws Exception{
  ctx = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
  Buy dao = ctx.getBean(Buy.class);


  List<Items> list = dao.find_items(id);
  m.addAttribute("items_list", list);
  return "jsp/items_list.jsp";
}
}

三种返回值 各自入参、保存、跳转总结。。。。

返回值void,ModelAndViewString
入参HttpServletRequest req, HttpServletResponse resHttpServletRequest  reqModel m
保存req.setAttribute("find_orders", list);modelAndView.addObject("find_detail", list);m.addAttribute("items_list", list);
跳转req.getRequestDispatcher("jsp/find_orders.jsp").forward(req, res);modelAndView.setViewName("find_detail");return "jsp/items_list.jsp";

5.配置视图解析器

在classpath下的handlerContext.xml中配置视图解析器。

上一节Handler(处理程序)中也说了。可以分为注解开发和非注解开发。

不管注解不注解,视图解析器是一定存在的

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    前缀<property name="prefix" value="jsp/"></property>
    后缀<property name="suffix" value=".jsp"></property>
</bean>

如果这里进行前缀后缀的添加,则handler中返回视图时不需要再额外进行指定了。

RESTful风格

简介

REST是REpresentational StateTransfer的缩写(一般中文翻译为表述性状态转移)

简单来说,在 REST 中,资源通过 URL 进行识别和定位,然后通过行为(即 HTTP 方法)来定义 REST 来完成怎样的功能。

CRUD 动作  HTTP 方法
Create    Post
ReadGet
UpdatePut或Patch
Delete
Delete

HTTP 方法会映射为 CRUD 动作,但这并不是严格的限制,有时候 PUT 也可以用来创建新的资源,POST 也可以用来更新资源。

特点

在使用 RESTful 风格之前, 增加一条商品数据通常是这样的:

/addCategory?name=xxx

但是使用了 RESTful 风格之后就会变成:

/category(类别)

这就变成了使用同一个 URL ,通过约定不同的 HTTP 方法来实施不同的业务,这就是 RESTful 风格所做的事情了。

参考网址推荐附带单元测试

http://tengj.top/2017/12/28/springboot12/#Controller

http://blog.didispace.com/springbootrestfulapi/

两个都有介绍了!!!重点是第一个。写的很好,为了省点篇幅,这里先不展开介绍了。等后面介绍SpringBoot的时候再来讲。学会看网上文档对照会用就行。这其实也是一种能力。人不可能把所有学过的知识都记得倒背如流,我为啥要写公众号呢。其实很大一方面,是把学过的知识再从头过一遍,有的可能初次接触用着不熟练,但你用过学过有记录过,等下次需要使用的时候再回过头来看,看一会马上就能想起接着使用,这就已经很足够了!把不会的没用过的一点一滴把它们都消灭!!!!

Swagger2

介绍

http://blog.didispace.com/springbootswagger2/

由于Spring Boot能够快速开发、便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API。而我们构建RESTful API的目的通常都是由于多终端的原因,这些终端会共用很多底层业务逻辑,因此我们会抽象出这样一层来同时服务于多个移动端或者Web前端。

它可以轻松的整合到Spring Boot中,并与Spring MVC程序配合组织出强大RESTful API文档。它既可以减少我们创建文档的工作量,同时说明内容又整合入实现代码中,让维护文档和修改代码整合为一体,可以让我们在修改代码逻辑的同时方便的修改文档说明。另外Swagger2也提供了强大的页面测试功能来调试每个RESTful API。

又见面啦。之前上一个项目中第一次接触到Swagge,趁现在赶快在学习一遍。

添加Swagger2依赖

创建Swagger2配置类

SwaggerAPI注解详解,以及注解常用参数配置

https://blog.csdn.net/java_yes/article/details/79183804

http://blog.didispace.com/springbootswagger2/

@Api:作用在类上,用来标注该类具体实现内容。表示标识这个类是swagger的资源。

@ApiOperation:用于方法注解,表示一个http请求的操作。

@ApiImplicitParams、@ApiImplicitParam注解来给参数增加说明。

@ApiModel:用于类,表示对类进行说明,用于参数用实体类接收。

@ApiModelProperty:用于方法,字段 ,表示对model属性的说明或者数据操作更改。

访问

启动Spring Boot程序,访问:http://localhost:8080/swagger-ui.html

。就能看到前文所展示的RESTful API的页面。我们可以再点开具体的API请求,以POST类型的/users请求为例,可找到上述代码中我们配置的Notes信息以及参数user的描述信息,如下图所示。

API文档访问与调试

Spring Boot对MVC的支持

@RestController

@ResponseBody 注解是将返回的数据结构转换为 JSON 格式

@ResponseBody+@Controller=@RestController

Ps: 如果是前后端分离,不用模板渲染的话,比如 Thymeleaf,可以直接使用 @RestController 将数据以 JSON 格式传给前端,前端拿到之后解析;但如果不是前后端分离,需要使用模板渲染的话,一般 Controller 中都会返回到具体的页面,此时就不能使用 @RestController 了

@RequestMapping

用来处理请求地址映射的注解。

比较常用的有 3 个属性:valuemethodproduces

value 属性:指定请求的实际地址,value 可以省略不写。

method 属性:指定请求的类型,主要有 GET、PUT、POST、DELETE,默认为 GET。

produces 属性:指定返回内容类型,produces = "application/json; charset=UTF-8"

@PathVariable

主要用来获取 URL 参数。Spring Boot 支持 Restfull 风格的 URL。

  • URL 中的参数和方法接收参数一致

  • URL 中的参数和方法接收参数不一致

@RequestParam

也是获取请求参数的。

@RequestParam 和@PathVariable 有什么不同呢?

 

主要区别在于:@PathValiable 是从 URL 模板中获取参数值, 即这种风格的URL:http://localhost:8080/user/{id};而 @RequestParam 是从 Request 里获取参数值,即这种风格的 URL:http://localhost:8080/user?id=1。我们使用该 URL 带上参数 id 来测试下如下代码:

  • 参数一致

  • 参数不一致

  • 传递的参数和后台封装的实体类一致的话则不需要@RequestParam注解

@RequestBody

用于接收前端传来的实体。

在后端封装一个实体来接收。

10.1回家了,不早了,要休息了!

多看几遍哈!!

加油!

没伞的孩子,必需努力奔跑!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值