1.SpringMVC是什么:

​ Spring web mvc是表现层的框架,它是Spring框架的一部分

​ 执行流程:客户端发送请求,springMVC的前端控制器DispatcherServlet接收并分配请求到对应的Controller执行对应的

方法,方法会返回视图,DispatherServlet解析视图,返回客户端进行渲染

2.视图解析器:

​ 视图:简单理解为浏览器向用户展示的界面

​ 为什么使用?

​ 浏览器想要展示页面需要有一个请求的地址,拿到路径,但路径通常会在一个文件夹中,而文件夹可能会有多层,所

以SpringMVC中的视图解析器,可以帮我们减少一些重复的代码,把绝对路径可以写成我们的逻辑路径

​ 需要在配置类中添加:用户在返回视图时,会经过该解析器,帮我们拼接字符串

​ 配置类继承WebMvcConfigurerAdapter,注意spring5后一律推荐使用实现WebMvcConfigurer接口

@Bean
public InternalResourceViewResolver viewResolver(){
    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
    // 这是视图的前缀
    viewResolver.setPrefix("/");
    // 这是视图的后缀
    viewResolver.setSuffix(".jsp");
    return viewResolver;
}

// properties 方式配置
spring.mvc.view.prefix=
spring.mvc.view.suffix=

3.参数绑定:

3.1.注意事项(重要)

​ 其中前台的name必须和属性值名称一致,使用set方法赋值

​ 其中方法的参数类型如果是基本数据类型推荐使用包装类型,因为基本数据类型不能为null,如果请求中没有改参数,会抛异常

3.2.@RequestParam

​ 作用:当请求参数的名称与方法参数名称不一致时,可以使用该注解标记对应关系

​ 该注解中的参数:

name = "对应的在前台的name名称":与方法中的参数名对应

required:表示是否必须有该参数有两个值,,默认为false

defaultValue:表示如果前台没有传递该参数时的默认值

​ 引用数据类型的映射(POJO):

​ 在方法参数声明一个对象变量,请求时如果name和对象中的属性值一致,会自动注入到该对象中

​ 简单说就是在对象中又有其他对象:

​ 在前台传递参数时,参数名称为该对象的名称再点属性

​ 例子:

两个javaBean

@Data
public class CartItem {

    private Item item;
    private Integer number;
    private Double price;
}

@Data
public class Item {

    private String name;
    private Double price;
}

前台要提交的表单

1561021062698

Controller层处理,及控制台输出

1561024971927

1561021093442

3.3.数组绑定

​ 前台表单传递一个相同name的一组数据,在方法的参数中写一个数组类型进行赋值,其中数组的名称

也要和前台name的名称相同

​ 示例:

 // 数据:["1","2"]
 @PostMapping("/deleteMore")
 public ResponseEntity<BaseResult> deleteMore(@RequestBody String[] ids){}

  // 请求路径 http://localhost:8080/emp/demo?arr=1&arr=2
  @GetMapping("/demo")
  public void fun(String[] arr){System.out.println(Arrays.toString(arr));}

3.4.集合类型:

​ 如果在方法参数中直接写集合类型是赋值不了的,需要使用数组或者在Bean中添加一个集合属性进行赋

值,如果需要给指定索引赋值,在name中指定索引即可

​ 例子:前台传递表单方式

在上面的基础之上CartItem类中添加了一个集合属性

1561021515410

​ 前台数据传递的方式以及后台打印结果15610215763711561021539049

4.多路径映射/请求方法限定/窄化路径:

4.1多路径映射:

@RequestMapping:请求路径映射

​ 常用的参数:

value:"指定访问的路径"可以多个{"路径1","路径2"}

headers :指定请求头中的参数

            **params** :你可以让多个处理方法处理到同一个URL 的请求, 而这些请求的参数是不一样的。也就是

请求时的不同参数,调用的方法也会不同

    @RequestMapping(value = "/hello.action",params = {"id=10"})
    public String fun(String id){
        System.out.println(id);
        return "index";
    }

    @RequestMapping(value = "/hello.action",params = {"id=20"})
    public String fun2(String id){
        System.out.println(id);
        return "index";
    }

4.2请求方法限定(也是该注解的一个参数)

method:指定请求的类型,也可以是数组

​ method = {RequestMethod.GET,RequestMethod.POST}

4.3窄化路径:

​ 在类上添加相当于设置请求的前缀

​ 在方法上添加,设置方法对应的请求路径

5. @PathVaraible注解的使用:

@RequestMapping 注解可以同 @PathVaraible 注解一起使用,用来处理动态的 URI

​ 将 @PathVaraible注解写到方法的参数前,对应方法中的参数,可以将URL中的对应的位置的值赋值到变量中,还可以使用正则表达式

 @RequestMapping(value = "/fetch/{id}.action", method = RequestMethod.GET)
    public String getDynamicUriValue(HttpServletRequest request, @PathVariable("id") String id) {
        System.out.println("ID is " + id);
        return "index";
    }

​ 如果设置参数不是必须的,需要有对应的路径映射

// required 设置参数为非必须项
@GetMapping({"/path/{id}","/path"})
public void fun(@PathVariable(required = false) Integer id){
    System.out.println(id);
}

6.Controller方法返回值以及跳转方式:

​ 返回值为ModelAndView:创建ModelAndView对象,或者在方法形参中给出,可以在构造方法中直接给(返回的页面,存在域中的名称,存在域中的数据),或者分别使用addObject(name,value),setViewName(地址),会经过视图解析器

​ 返回值为String:在方法的形参上添加Model,使用addAttribute()存储数据,返回值写地址

​ 还可以使用 return "redirect:tao.jsp";

​ return "forward:tao.jsp";

​ 这两种方法存储的域都是request(想要存储到别的域中,可以使用原生)

​ 返回值为void使用方式和BaseServlet时一样,并且不会经过SpringMVC中的视图解析器

​ 想要重定向或请求转发,在字符串中分别拼接redirect:和forward:,MVC会帮我们解析返回值,并在底层调用不同的方法

7.异常处理器:

​ SpringMVC异常处理机制:

​ 系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由

异常处理器进行异常处理。springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。

具体代码实现:

​ 创建一个自己的异常类,继承Exception

​ 定义统一异常处理器类:实现HandlerExceptionResolver接口并交由spring管理,重写方法

@Component
public class CustomExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception ex) {

        //统一处理异常
        CustomException customException = null;
        // 如果是自定义异常直接类型转换赋值,并显示错误信息
        // 如果不是创建自定义异常,提示未知错误
        if(ex instanceof CustomException){
            customException = (CustomException) ex;
        } else {
            customException = new CustomException("系统错误,请与系统管理 员联系!");
        }

        //设置数据
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("message", customException.getMessage());
        modelAndView.setViewName("WEB-INF/error");

        return modelAndView;
    }
}

8.图片上传:

​ 在写具体代码时,先了解一下表单的一个属性

enctype:该属性有三个属性值

application/x-www-form-urlencoded:默认值,请求方式为get时,会将表单中的数据以键值对的方式加到url后面中间用?分隔,为post时,浏览器把form数据封装到http body中,然后发送到服务器

text/plain:表单以纯文本形式进行编码

multipart/form-data:当上传的含有非文本数据时,设置为该属性值,将表单数据变成二进制数据进行上传,这时使用request是获取不到表单响应的值的

​ 在了解这点后,看具体上传图片的代码:

​ 在配置类中添加文件上传解析器:

​ 需要导入commons-iocommons-fileupload依赖

 @Bean

    public CommonsMultipartResolver multipartResolver[1] (){

        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();

        // 设置所有的上传文件的总大小 10M

        multipartResolver.setMaxInMemorySize(10*1024*1024);

        // 设置单个文件上传的大小 4M

        multipartResolver.setMaxUploadSize(4*1024*1024);

        multipartResolver.setDefaultEncoding("utf-8");

        return multipartResolver;

    }

注解方式:

spring.servlet.multipart.max-file-size= 文件大小
spring.servlet.multipart.max-request-size= 请求大小

Controller中写方法接受表单数据,需要设置一个参数MultipartFile表示文件上传对象,其他参数可以正常获取

​ 该类常用方法:

            方法名                            描述
String getOriginalFilename()        获得原始上传文件名
transferTo(File file)                将上传文件转换到一个指定的文件中
String getContentType()                获取文件MIME类型,如image/pjpeg、text/plain等
String getName()                    获取表单中文件组件的名字

​ 直接写一个数组(没试过) ​ 如果是多文件上传,可以写一个VO类,里面添加一个成员变量List MultipartFiles

9.JSON数据交互:

​ 需要导入的依赖:

<dependency>

  <groupId>com.fasterxml.jackson.core</groupId>

  <artifactId>jackson-databind</artifactId>

  <version>2.9.7</version>

</dependency>

​ 前端发送json格式的数据,如果对应的Controller方法中的对象或者变量名相同可以直接封装赋值

​ 后台想要把数据返回到前台页面显示,需要在配置类上添加@EnableWebMvc开启配置

​ 有两种方式:

​ 1.在类上添加@Controller在方法返回值前加@ResponseBody

​ 2.直接在类上添加@RestController,因为该注解包含上面两个注解

10.拦截器:

​ 自定义拦截器需要实现HandlerInterceptor接口重写其方法

  1. preHandle方法是controller方法执行前拦截的方法

    可以使用request或者response跳转到指定的页面

    return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。

    return false不放行,不会执行controller中的方法。

  1. postHandle是controller方法执行后执行的方法,在JSP视图执行前。

    可以使用request或者response跳转到指定的页面

    如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。

  1. afterCompletion方法是在JSP执行后执行

    request或者response不能再跳转页面了

使用配置类配置拦截器:

​ 配置类继承WebMvcConfigurerAdapter

​ 重写方法:

@Override
public void addInterceptors(InterceptorRegistry registry) {
    // 添加拦截器
    InterceptorRegistration interceptorRegistration1 = registry.addInterceptor(myInterceptor1);
    InterceptorRegistration interceptorRegistration2 = registry.addInterceptor(myInterceptor2);
    interceptorRegistration1.addPathPatterns("/**");
    interceptorRegistration2.addPathPatterns("/**");
}

​ 多个拦截器执行流程:

​ 会先按顺序执行preHandle方法,在Controller方法执行完成并且在jsp视图执行前反顺序执行postHandle方法,然后

在返回视图,在返回视图完成后在反顺序执行afterCompletion方法

11.序列化

@JsonInclude注解的使用

有时前台获取数据时,数据中有为null或者""空字符串的字段,为了解决不必要的麻烦,可以在实体类的字段上添加该注解

@JsonInclude(JsonInclude.Include.NON_NULL) // 字段的值为空时跳过序列化
@JsonInclude(JsonInclude.Include.NON_EMPTY)// 包含上面注解,同时字段值为空字符时跳过序列化

12.@RequestBody

配合post请求使用

该注解主要作用用于解析请求体中的数据

如果不添加该注解,那么获取形参的数据为null

     // 不添加注解
     @PostMapping
    public void fun(String student){
        System.out.println(student);
    }

    // 请求体中的数据
    {"sname":"taoqz"}
    // 控制台输出
    console : null



    // 添加注解    
    @PostMapping
    public void fun(@RequestBody String student){
        System.out.println(student);
    }

     // 请求体中的数据
    {"sname":"taoqz"}
    // 控制台输出 会将数据当做字符串解析赋值
    console : {"sname":"taoqz"}

​ 传递对象

​ 只需将参数设置为需要的对象,mvc会将请求中的数据自动封装到对象中,前提是请求体中的字段与实体类中的属性名称一致

@PostMapping
public void fun(@RequestBody Student student){
    System.out.println(student);
}

// 请求体中数据
{
   "sname":"taoqz",
   "address":"北京"
}
// 控制台输出
Student(sid=null, sname=taoqz, address=北京, teachers=null)

​ 结合@RequestParam使用

​ @RequestBody注解只能使用一次,如果有特殊需要可以结合@RequestParam使用

    @PostMapping("/test")
    public void add(@RequestBody Student student, @RequestParam("arr") String[] arr){
        System.out.println(student);
        System.out.println(Arrays.toString(arr));
    }
    // 请求路径  mvc会将路径中相同名称的参数封装到数组中
    http://localhost:8080/test/zz?arr=1&arr=2
    // 请求体 自动封装到对象中
    {
          "sname": "zs",
          "address": "江苏省南京市"
    }
    // 控制台输出
    student: Student(sid=null, sname=zs, address=江苏省南京市, teachers=null)
    arr : [1, 2]

注意事项

​ 请求: http://localhost:8090/user?ids=1&ids=2

​ 接收数组参数

@DeleteMapping
    public void fun(Integer[] ids){
    System.out.println(Arrays.toString(ids));
}

​ 将参数转为集合

// 也可以使用请求: http://localhost:8090/user?ids=1,2
@DeleteMapping
public void fun(@RequestParam List<Integer> ids){
    ids.forEach(System.out::println);
}
Copyright © TaoQZ 2019 all right reserved,powered by Gitbook作者联系方式:taoqingzhou@gmail.com 修订时间: 2024-11-19 17:25:44

results matching ""

    No results matching ""

    results matching ""

      No results matching ""