SpringMVC学习简要

学习资料:

SpringMVC-03-入门案例工作流程解析_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1ZF411G7eP/?p=3&spm_id_from=pageDriver&vd_source=4ac53f52a57eb96a3c8406b971b038ae

常用MYSQL命令:http://t.csdn.cn/zshCP
学习要求

什么是springmvc

  • springmvc是一种基于java实现MVC模型的轻量级web框架

  • 比servlet更便捷

  • MVC模式:后端服务器
    *

    |-----------------------------------------|--------------------------------------------------|
    | controller ||
    | view(页面) * HTML * CSS * VUE * ElementUI | model (最终生成的model对象是一个java对象,不能直接返回页面,要使用json格式) |
    | service ||
    | dao ||

springmvc基本使用步骤

  • 创建web工程(maven结构)
  • 设置tomcat服务器,加载web工程(tomcat插件)
  • 导入坐标(SpringMVC+Servlet)
  • 定义处理请求的功能类(UserController)
  • 设置请求映射 (配置映射关系)
  • 将SpringMVC设定加载到Tomcat容器中

启动服务器初始化过程

  • 服务器启动,执行ServletContainersInitConfig类,初始化web容器
  • 执行createServletApplicationContext方法,创建了WebApplicationContext对象
  • 加载SpringMvcConfig
  • 执行@ComponentScan,加载对应的bean
  • 加载UserController,每个@RequestMapping的名称对应一个具体的方法
  • 执行getServletMappings方法,定义所有的请求都通过SpringMVC
  • 简而言之:
    • 1、把springmvc配置加载到tomcat容器中
    • 2、把所有请求拦截给springmvc处理

单次请求过程

  • 发送请求localhost/save
  • web容器发现所有请求都经过SpringMVC,将请求交给SpringMVC处理
  • 解析请求路径/save
  • 由/save匹配执行对应的方法save()
  • 执行save()
  • 检测到有@ResponseBody直接将save()方法的返回值作为响应体返回给请求方

Springmvc的bean扫描范围

  • 因为功能不同,如何避免spring错误地加载到SpringMVC的bean?
  • springmvc加载的bean均在com.itheima.controller包内
  • 所以要修改spring的bean扫描范围:
    • 方式一:把加载bean的扫描范围设定为com.itheima,再排除掉controller包内的bean

      java 复制代码
      @Configuration
      @ComponentScan(
              value="com.study",//扫描该包
              excludeFilters=@ComponentScan.Filter(
                      type= FilterType.ANNOTATION, //按注解排除
                      classes= Controller.class//不扫描有@Controller注解的包
          )
      )
      public class SpringConfig {
      }
    • 方式二:直接设定为更具体的包,如com.itheima.service,com.itheima.dao。。。

    • 在springmvc项目中,以使用方式二为主

请求(解决传参的问题)

请求映射路径(@RequestMapping)

  • 该代码具有一般性
    *

    java 复制代码
    package com.study.config;
    
    import org.springframework.web.filter.CharacterEncodingFilter;
    import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
    
    import javax.servlet.Filter;
    
    public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    
        protected Class<?>[] getRootConfigClasses() {
            return new Class[0];
        }
    
        protected Class<?>[] getServletConfigClasses() {
            return new Class[]{SpringMvcConfig.class};
        }
    
        protected String[] getServletMappings() {
            return new String[]{"/"};
        }
    
        //乱码处理
        @Override
        protected Filter[] getServletFilters() {
            //为web容器添加过滤器并指定字符集
            CharacterEncodingFilter filter=new CharacterEncodingFilter();
            filter.setEncoding("UTF-8");
            return new Filter[]{};//数组的形式
        }
    }

1、五种数据类型的传参(@RequestParam)

```java
package com.study.controller;

import com.study.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Arrays;
import java.util.List;

@Controller
public class UserController {

    //普通参数,当请求参数名与形参名不同时,使用RequestParam注解
    @RequestMapping("/commonParam")
    @ResponseBody
    public String commonParam(@RequestParam("name")String userName){
        System.out.println("普通参数传递,userName:"+userName);
        return "{'module':'common Param'}";
    }

    //POJO参数
    @RequestMapping("/pojoParam")
    @ResponseBody
    public String pojoParam(User user){
        System.out.println("pojo参数传递,user:"+user);
        return "{'module':'pojo Param'}";
    }

    //嵌套POJO参数
    @RequestMapping("/pojoContainPojoParam")
    @ResponseBody
    public String pojoContainPojoParam(User user){
        System.out.println("pojo嵌套参数传递,user:"+user);
        return "{'module':'pojo contain Param'}";
    }

    //数组参数
    @RequestMapping("/arrayParam")
    @ResponseBody
    public String arrayParam(String[] likes){
        System.out.println("数组参数传递,likes:"+ Arrays.toString(likes));
        return "{'module':'array Param'}";
    }

    //集合参数
    @RequestMapping("/listParam")
    @ResponseBody
    public String listParam(@RequestParam List<String> likes){
        System.out.println("集合参数传递,likes:"+ likes);
        return "{'module':'list Param'}";
    }
}
```
  • 简而言之,url传递参数时,如果名称不对应,使用@RequestParam注解

2、json数据传递参数(@RequestBody和@RequestParam)

  • (1)导入坐标

    XML 复制代码
    <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>2.8.10</version>
    </dependency>
  • (2)在核心注解类中加注解,开启自动转换json数据的支持
    *

    java 复制代码
    @EnableWebMvc
    public class SpringMvcConfig {
    }
  • (3)注意postman里的4处

  • (4)添加@RequestBody注解

    java 复制代码
        //集合参数:json格式
        @RequestMapping("/listParamForJson")
        @ResponseBody
        public String listParamForJson(@RequestBody List<String> likes){
            System.out.println("list common(json)参数传递,list:"+ likes);
            return "{'module':'list Param for json param'}";
        }
    
        //POJO参数:json格式
        @RequestMapping("/pojoParamForJson")
        @ResponseBody
        public String pojoParamForJson(@RequestBody User user){
            System.out.println("pojo(json)参数传递,user:"+ user);
            return "{'module':'pojo for json param'}";
        }
    
        //集合参数:json格式
        @RequestMapping("/listPojoParamForJson")
        @ResponseBody
        public String listPojoParamForJson(@RequestBody List<User> list){
            System.out.println("list pojo(json)参数传递,list:"+ list);
            return "{'module':'list pojo for json param'}";
        }
    • 发送json数据,用注解@RequestBody
    • 发送非json数据,用注解@RequestParam接收参数

3、日期型参数传递(@DateTimeFormat)

  • 根据不同的日期格式设置不同的接收格式

    java 复制代码
        //日期参数
        @RequestMapping("/dataParam")
        @ResponseBody
        public String dataParam(Date date,
                                @DateTimeFormat(pattern="yyyy-MM-dd") Date date1,
                                @DateTimeFormat(pattern="yyyy/MM/dd HH:mm:ss") Date date2){
            System.out.println("参数传递,date:"+ date);//2088/08/08
            System.out.println("参数传递,date1(yyyy-MM-dd):"+ date1);//2088-08-08
            System.out.println("参数传递,date1(yyyy/MM/dd HH:mm:ss):"+ date2);//2088/08/08 8:08:08
            return "{'module':'date param'}";
        }
  • 注解@DateTimeFormat用于设定接收的日期格式

响应(@ResponseBody)

1、响应页面

```java
@RequestMapping("/toPage")
public String toPage(){
    return "page.jsp";
}
```

2、响应json数据(对象转json)

```java
@RequestMapping("/toJsonPOJO")
@ResponseBody //把user对象转成json数据返回
public User toJsonPOJO(){
        User user=new User();
        user.setName("itcast");
        user.setAge(15);
        return user;
}
```

3、响应json数据(对象集合转json数组)

```java
@RequestMapping("/toJsonList")
@ResponseBody
public List<User> toJsonList(){
        System.out.println("返回json集合数据");
        User user1=new User();
        user1.setName("itcast");
        user1.setAge(15);

        User user2=new User();
        user2.setName("黑马");
        user2.setAge(12);

        List<User> userList=new ArrayList<>();
        userList.add(user1);
        userList.add(user2);
        return userList;
}
```
  • 类型转换器(HttpMessageConverter)

REST风格

  • Representational State Transfer,表现层资源状态转移

  • 简而言之,REST风格就是访问网络资源的格式

  • 约定可以打破,所以叫REST风格,而不是REST规范

  • 模块名称通常用复数

  • 使用

    • 1、设定http请求动作
    • 2、设定请求参数路径变量
  • 三个接收参数的注解区别:

    • (1)@RequestParam用于接收url地址传参或表单传参
    • (2)@RequestBody用于接收json数据
    • (3)@PathVariable用于接收路径参数,使用{参数名称}描述路径参数

REST风格简化开发

```java
//简化前
@Controller
public class UserController {

    @RequestMapping(value="/users",method=RequestMethod.POST)
    @ResponseBody
    public String save(){
        System.out.println("user save...");
        return "{'module':'user save'}";
    }

    @RequestMapping(value="/users/{id}",method=RequestMethod.DELETE)
    @ResponseBody
    public String delete(@PathVariable Integer id){//从路径处传过来的变量
        System.out.println("user delete..."+id);
        return "{'module':'user delete'}";
    }

    @RequestMapping(value="/users",method=RequestMethod.PUT)
    @ResponseBody
    public String update(@RequestBody User user){
        System.out.println("user update..."+user);
        return "{'module':'user update'}";
    }

    @RequestMapping(value="/users/{id}",method=RequestMethod.GET)
    @ResponseBody
    public String getById(@PathVariable Integer id){
        System.out.println("user getById..."+id);
        return "{'module':'user getById'}";
    }

    @RequestMapping(value = "/users",method = RequestMethod.GET)
    @ResponseBody
    public String getAll(){
        System.out.println("user getAll...");
        return "{'module':'user getAll'}";
    }
}




//简化后
@RestController
@RequestMapping("/users")
public class UserController {

    @PostMapping
    public String save(){
        System.out.println("user save...");
        return "{'module':'user save'}";
    }

    @DeleteMapping("/{id}")
    public String delete(@PathVariable Integer id){
        System.out.println("user delete..."+id);
        return "{'module':'user delete'}";
    }

    @PutMapping
    public String update(@RequestBody User user){
        System.out.println("user update..."+user);
        return "{'module':'user update'}";
    }

    @GetMapping("/{id}")
    public String getById(@PathVariable Integer id){
        System.out.println("user getById..."+id);
        return "{'module':'user getById'}";
    }

    @GetMapping
    public String getAll(){
        System.out.println("user getAll...");
        return "{'module':'user getAll'}";
    }
}
```

基于RESTful页面数据交互

  • 1、做后台功能,开发接口并调通接口
  • 2、做页面异步调用,确认功能正常可以访问
  • 3、完成页面数据展示
  • 4、放行静态资源的访问

SSM整合(Spring,MyBatis,SpringMVC)

  • 详见具体项目代码
  • Spring整合MyBatis的结构

|------------------------------------------------------------------------|
| 配置(config) * SpringConfig * JDBCConfig、jdbc.properties * MyBatisConfig |
| 表现层(controller) * BookController * Result * Code |
| 模型(domain) * Book |
| 数据层标准开发(dao) * BookDao |
| 业务层标准开发(service) * BookService * BookServiceImpl |
| 测试接口(test/service) * BookServiceTest |

  • 异常处理
    • 项目异常:
      • 1、业务异常(BusinessException)
        • 发送对应消息传递给用户,提醒规范操作
      • 2、系统异常(SystemException)
        • 发送固定消息传递给用户,安抚用户
      • 3、其他异常(Exception)
        • 发送固定消息传递给用户,安抚用户
    • 项目异常处理
      • 1、自定义项目系统级异常、业务级异常......
        *

        html 复制代码
        //自定义项目系统级异常
        axios.get("/books").then((res)=>{});//查询
        axios.post("/books",this.formData).then((res)=>{});//添加
        axios.delete("/books"+row.id).then((res)=>{});//删除
        axios.put("/books",this.formData).then((res)=>{});//修改
        axios.get("/books"+row.id).then((res)=>{});//查询
      • 2、自定义异常编码(类似404,500的存在)

      • 3、触发自定义异常

拦截器(Interceptor)

  • 是一种动态拦截方法调用的机制
  • 拦截器和过滤器的区别:
    • 1、Filter属于Servlet技术,Interceptor属于SpringMVC技术
    • 2、Filter对所有访问进行增强,Interceptor仅对SpringMVC的访问进行增强

使用步骤:

  • 1、声明拦截器的bean,并实现HandlerInterceptor接口
  • 2、定义配置类,继承WebMvcConfigurationSupport,实现addInterceptor方法
  • 3、添加拦截器并设定拦截的访问路径,路径可以通过可变参数设置多个

拦截器参数:

  • 1、前置处理

    java 复制代码
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            String contentType=request.getHeader("Content-Type");
            System.out.println("preHandle..."+contentType);
            return true;
    }
    • 参数:
      • request:请求对象
      • response:响应对象
      • handler:被调用的处理器对象
    • 返回值: false,被拦截的处理器将不执行
  • 2、后置处理

    java 复制代码
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle...");
    
    }
    • modelAndView: 读取并调整返回结果对应的数据和页面信息
  • 3、完成后处理

    java 复制代码
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("afterCompletion...");
    
    }
    • ex:处理处理器执行过程中出现的异常情况

多拦截器执行顺序(了解即可,通常一个拦截器就够用了)

  • 配置的多个拦截器形成拦截器链
  • 拦截器链的运行顺序以拦截器添加顺序为准
相关推荐
Wx-bishekaifayuan6 分钟前
django电商易购系统-计算机设计毕业源码61059
java·spring boot·spring·spring cloud·django·sqlite·guava
可峰科技8 分钟前
斗破QT编程入门系列之二:认识Qt:编写一个HelloWorld程序(四星斗师)
开发语言·qt
customer0811 分钟前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
全栈开发圈13 分钟前
新书速览|Java网络爬虫精解与实践
java·开发语言·爬虫
WaaTong15 分钟前
《重学Java设计模式》之 单例模式
java·单例模式·设计模式
面试鸭17 分钟前
离谱!买个人信息买到网安公司头上???
java·开发语言·职场和发展
小白学大数据18 分钟前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
Python大数据分析@21 分钟前
python操作CSV和excel,如何来做?
开发语言·python·excel
@小博的博客25 分钟前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习