String MVC

一、Front设计模式

(1)概念:

Front(前端)设计模式就是有一个前端(不是前端专业那个前端,是最前面的意思)统一入口,在统一入口根据请求url调用自己的编写的普通方法。其中这个入口称为DispatcherServlet(Servlet分发器)。

(2)优点

  • 只需要在一个Servlet中编写获取容器Bean的代码,减少了代码冗余。

  • 不需要为每个控制器都创建一个类,而是可以在一个普通Java类中提供普通实例方法代表以前servlet中的services方法。

  • 因为可以自己编写普通Java类,这类可以放入到Spring容器中,注入Service更方便

  • 同时因为是自己编写的Java,所以可以进行一些封装,对其他操作进行简化。(代码中没有体现)

二、SpringMVC 环境搭建

(1)引入Spring-webmvc依赖


  org.springframework
  spring-webmvc
  5.3.23

(2)创建Spring MVC配置文件



    
    
    
    
    
    

(3)编写web.xml,让DispatcherServlet生效



    
        springmvc
        org.springframework.web.servlet.DispatcherServlet
        
            
            contextConfigLocation
			
            classpath:springmvc.xml
        
        
        
        1
    
    
        springmvc
        
        /
    


    
    
        code
      org.springframework.web.filter.CharacterEncodingFilter
        
            encoding
            utf-8
        
    
    
        code
        /*
    

(4)创建一个类放入到Spring MVC容器中

package com.bjsxt.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller// 放入到Spring MVC容器中
public class FirstController {
    /*
     * 官方标准写法:
     *      返回值是ModelAndView,对象中存储跳转资源路径及作用域值
     */
    // 当前方法的映射路径
    @RequestMapping("/first")
    public ModelAndView test1(){
        ModelAndView modelAndView = new ModelAndView("first.jsp");
        return modelAndView;
    }
    /*
     * 简化写法(平时使用的方式)
     *      返回值是String,表示跳转的资源路径
     */
    @RequestMapping("/first2")
    public String test2(){
        return "first.jsp";
    }
}

三、@RequestMapping

(1)value"" 默认属性,配置映射路径,可以配置多个

(2)path="" 配置映射路径,可以配置多个

(3)name="" 备注

(4)method={RequestMethod.} 控制只能某种请求方法访问这个方法(控制单元),不配置默认什么请求方法都可以,如果不支持该请求方式报405状态码

(5)params="" 请求时必须包含某个参数,如果没有报400状态码

(6)consumes 设置请求体Content-Type类型,只能结合@RequestBody使用

(7)produces 设置响应体Content-Type类型,只能结合@ResponseBody使用

四、转发和重定向

(1)转发

在返回值字符串之前拼接 forward: 

(2)重定向

在返回值字符串之前拼接 redirect:

五、作用域传值

(1)和原生servlet的api多了一个Model传值,实际还是request作用域传值。

(2)还有一种方式可以直接使用Map传值,实际上还是request作用域。

六、获取请求参数

(1)可以直接在参数列表中通过name名直接获取

(2)@RequestParam 设置请求参数的注解

        1.name和value要接收请求参数的哪个参数

        2.defaultValue:默认值。表示当请求参数中没有这个参数时给与的默认值

        3.required:boolean类型,表示请求中是否必须包含参数

(3)接收一个自定义类型的参数,类中的属性名和请求参数名对应,默认通过set方法设置

(4)@DateTimeFormat接收日期类型参数,该注解也可以放在属性上

        pattern属性设置格式:@DateTimeFormat(pattern="yyyy-MM-dd")

(5)当请求参数为多个同名参数时,可以通过数组接收。如果向使用集合接收,必须有@RequestParam("参数名")

(6)使用路径传参(restful)

        请求路径写成

                /bjsxt/test/chen/123/23

        映射写为

                /test/{name}/{password}/{age}

        参数列表一定要加@PathVariable("name"),如果名字相同可以不写参数

                (@PathVariable("name") String name,@PathVariable("name") String password,@PathVariable("name") int age)

七、视图解析器

解决资源路径过于复杂的问题。

实际方式:做字符串拼接,为每个资源路径都加前缀和后缀。


   
   
   
   

八、文件上传

(1)在Html的form中enctype属性控制请求体数据类型

        application/x-www-form-urlencoded :默认值,表示普通表单数据,传递的都是字符串参数

        multipart/form-data:如果表单中除了普通字符串参数以外,还包含文件流数据,必须设置成这个

        text/plain:大文本数据。传递的内容是比较大的字符串。常用在邮箱。

(2)导入commons-fileupload依赖


    commons-fileupload
    commons-fileupload
    1.4

(3)在springmvc容器中配置



   
   

(4)使用及方法

@Controller
public class PeopleController {
    /**
     * 文件上传控制单元方法实现
     *
     * @param name    也可以使用JavaBean接收name的值
     * @param address 也可以使用JavaBean接收address的值
     * @param photo   名字必须和表单中文件域的name属性值相同
     * @return
     * @throws IOException transferTo抛出的异常,可以使用try...catch处理异常。示例中为了让代码看起来简洁直接抛出了。
     */
    @RequestMapping("/upload")
    public String upload(String name, String address, MultipartFile photo) throws IOException {
        photo.transferTo(new File("D:/images", photo.getOriginalFilename()));
        return "/upload.jsp";
    }
}

String MVC_第1张图片

 (5)生成唯一文件名的方式

        时间戳+随机数

        UUID(jdk自带)

    /**
     * 文件上传控制单元方法实现
     * @param name 也可以使用JavaBean接收name的值
     * @param address 也可以使用JavaBean接收address的值
     * @param photo 名字必须和表单中文件域的name属性值相同
     * @return
     * @throws IOException transferTo抛出的异常,可以使用try...catch处理异常。示例中为了让代码看起来简洁直接抛出了。
     */
    @RequestMapping("/upload")
    public String upload(String name, String address, MultipartFile photo) throws IOException {
        // 判断上传文件流是否为空。如果不为空继续执行
        if(!photo.isEmpty()) {
            // 获取项目部署后的文件绝对路径
            // String realPath = req.getServletContext().getRealPath("/page");

            // 使用UUID生成文件名称
            // String fileName = UUID.randomUUID().toString();
            // 使用时间戳+随机数生成文件名
            long timeMillis = System.currentTimeMillis();
            Random random = new Random();
            String fileName = timeMillis + "" + random.nextInt(1000);
            // 获取上传时文件名
            String oldName = photo.getOriginalFilename();
            // 获取上传时文件的扩展名
            String suffix = oldName.substring(oldName.lastIndexOf("."));
            // 保存文件到D:/images中。必须保存D盘下已经存在images文件夹
            photo.transferTo(new File("D:/images",fileName + suffix));
        }
        return "/upload.jsp";
    }

 (6)字节输出流

    // 方法返回值为void
	@RequestMapping("/uploadfile/{filepath}")
    public void showImage(@PathVariable String filepath, HttpServletResponse resp) throws IOException {
        FileInputStream is = new FileInputStream("D:/images/" + filepath);
        // Resonse对象getOutputStream()获取响应流。
        ServletOutputStream os = resp.getOutputStream();
        // Commons-io.jar中的工具类。
        // copy(InputStream,OutputStream)表示表InputStream中内容拷贝到OutputStream中
        IOUtils.copy(is, os);
    }

九、文件下载

 (1)在Http协议中,响应头参数Content-Disposition参数可取值有两个:

        inline:默认值。表示浏览器能解析就显示,不能解析就下载。

        attachment。以附件形式下载(恒下载)

    @RequestMapping("/download")
    public void download(HttpServletRequest req, HttpServletResponse response, String filename) {
        try {
            // filename=的值就是客户端看到的下载文件名称
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            File file = new File(req.getServletContext().getRealPath("/images"), filename);
            FileInputStream fis = new FileInputStream(file);
            ServletOutputStream os = response.getOutputStream();
            IOUtils.copy(fis, os);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

十、@ResponseBody

(1)放在方法上,可以把方法的返回值转换为json字符串,并设置到响应体中。

注意:会使得方法没有跳转功能。

(2)想要改变@ResonseBody注解的响应内容类型(Content-Type)只能通过@RequestMapping的produces属性进行设置。如果返回值是String类型并且返回值中有中文必须这样设置。

    @RequestMapping(value="/demo1",produces = "text/html;charset=utf-8")
    @ResponseBody
    public String demo1() {
        return "幽默涵养";
    }

(3)@RestController写在类上,表示该类上所有方法都加了@ResponseBody

十一、@RequestBody

服务端接收请求体中包含JSON字符串的请求时,需要在参数前面添加@RequestBody。表示使用Jackson把请求体中JSON/XML格式的数据转换为JavaBean或Map

    @RequestMapping("/testContentType")
    @ResponseBody
    public People testContentType(@RequestBody People peo) {
        System.out.println(peo);
        return peo;
    }

十二、拦截器

(1)定义:Spring MVC中提供的一个类似filter(过滤器)的功能。

String MVC_第2张图片

 (2)使用

        1.创建java类实现HandlerInterceptor接口,重写三个方法

        参数:

                Object handler:HandlerMethod类型,存储了拦截的单元方法的method对象。

                ModelAndView: 存储了model和view信息的对象。

                Exception:存储异常信息的对象,如果没有异常信息则默认为null。

package com.bjsxt.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

        2.在springmvc.xml中配置拦截器拦截哪些控制单元


   
   
   
       
       
       
       
       
   

(3)拦截器栈

拦截器栈指多个拦截器。当一个控制单元被多个拦截器拦截时,就形成了拦截器栈。拦截器栈中拦截器有着严格的执行顺序。执行顺序按照配置顺序执行。先配置的优先级更高,执行完控制单元,是先配置的后执行。

十三、Spring MVC异常处理

(1)局部配置

每个控制器类中可以有多个处理异常的方法。每个方法上面只需要有@ExceptionHandler,千万别添加了@RequestMapping注解。参数:value设置出现什么异常类型。

注意:只在当前类生效。

@Controller
public class DemoController {
    @RequestMapping("/demo")
    @ResponseBody
    public String demo2(){
        Object obj = null;
        obj.toString();
        return "demo2";
    }

    @ExceptionHandler(value = ArithmeticException.class)
    public String myexception(){
        System.out.println("Demo-1");
        return "forward:/exception.jsp";
    }

    @ExceptionHandler(value = Exception.class)
    public String myexception2(){
        System.out.println("Demo-2");
        return "forward:/exception2.jsp";
    }
}

(2)全局配置

创建一个类在类上加@ControllerAdvice注解,在该类中的异常处理方法就会在所有控制类中生效。

@ControllerAdvice
public class MyExceptionController {
    @ExceptionHandler(value = ArithmeticException.class)
    public String myexception(){
        System.out.println("MyException-1");
        return "forward:/exception.jsp";
    }
    @ExceptionHandler(value = Exception.class)
    public String myexception2(){
        System.out.println("MyException-2");
        return "forward:/exception2.jsp";
    }
}

(3)使用配置文件配置

   
       
                
                /error1.jsp
                /error2.jsp
           

       

   

(4)在web.xml中配置

上面的方式只有在Spring MVC中出现异常时才会触发,也可以使用Java EE中的配置方式。在web.xml中配置error-page即可。

这种在web.xml配置的方式是针对整个项目出现的异常。而在springmvc.xml配置文件的配置方式只是针对Spring MVC框架出现的异常。

   

       
        java.lang.NullPointerException

       

        500
        /error3.jsp
   

十四、数据校验

注解 含义
@AssertFalse 类型必须是布尔,取值必须为false
@AssertTrue 类型必须是布尔,取值必须为true
@DecimalMax("3") 最大值为3,value属性是String类型。
@DecimalMin("1") 最小值为1,value属性是String类型。
@Digits(integer = 10,fraction = 3) integer:整数位最大长度,fraction小数位最大长度
@Email 必须是邮箱地址。只要中间包含@,且@前后都具有超过1位的字符就能通过校验。字符可以是数字字母下划线
@Future 类型必须是时间类型,允许为null,如果设置值必须是一个将来的时间
@FutureOrPresent 类型必须是时间类型,允许为null,如果设置值必须是一个一个将来或现在的时间(精确到秒)
@Max(5) 最大值为5,value属性是long类型
@Min(1) 最小值为1,value属性是long类型。
@Negative 必须是负数,对数据类型没有要求。
@NegativeOrZero 必须是负数或零,对数据类型没有要求。
@NotBlank 用在String类型。不能是空白(null和"")
@NotEmpty 用在String类型。不能是空白(null和"")
@NotNull 不能为null,可以是""。可以用在所有类型中。对于八大基本数据类型来说,永远不为null。
@Null 必须为Null。可以用在所有类型中。对于八大基本数据类型来说,永远不可能为null。
@Past 类型必须是时间类型,必须是一个过去的时间。精确到秒。
@PastOrPresent 类型必须是时间类型,必须是一个过去的时间或现在的时间。精确到秒。·
@Pattern(regexp = "\w{1,6}") 必须满足正则表达式。regexp是必有属性。
@Positive 必须是正数,对数据类型没有要求。
@PositiveOrZero 必须是正数或零,对数据类型没有要求。
@Size(min = 1,max = 10) 用在String类型。个数必须在1和10之间
注解 含义
@Length(min = 1,max = 10) 用在String类型。长度需要在1和10之间
@Range(min = 1,max = 10) 数据类型没有要求。取值范围需要在1和10之间
@URL(port = 8080,host = "127.0.0.1",protocol = "https") 需要是一个合法的URL。默认情况下只要是以http:开头即可。可以通过port限制端口、host限制主机名、protocol限制协议

(1)导入hibernate-validator依赖

       
            org.hibernate.validator
            hibernate-validator
            6.1.7.Final
       

(2)在实体类属性上添加注解

public class People {
    @NotNull(message = "姓名不能是null")
    @Length(min = 2,max = 6,message = "长度应该是2-6位")
    private String name;
    private String age;
    // 省略Getter和Setter
}

(3)控制单元中添加@Valid注解,否则校验不生效

    @RequestMapping("/test1")
    @ResponseBody
    public People test1(@Valid People people,BindingResult result) {
        // 如果有异常信息
        if (result.hasErrors()) {
            // 获取异常信息对象
            List errors = result.getAllErrors();
            // 将异常信息输出
            for (ObjectError error : errors) {
                System.out.println(error.getDefaultMessage());
            }
        }
        return people;
    }

十五、跨域

(1)跨域介绍

跨域:当前项目的协议、ip、端口和访问的URL的协议、IP、端口中有一个不同,这种访问就叫跨域。

跨域只发生在Ajax请求中。

Ajax研发之初为了保证安全性,设置默认情况下不允许跨域访问。

 (2)实现跨域原理

只要在控制单元方法上添加了@CrossOrigin注解后,会在响应头中添加Access-Control-Allow-Origin:*

Access-Control-Allow-Origin是HTTP协议中允许哪些IP的项目跨域访问,*表示所有IP

十六、国际化

(1)新建配置文件:属性文件语法:任意名_语言_国家.properties。例如:中文是zh、英文是en。如果为了更加精确是哪国使用的这个语言,可以在后面添加国家,因为美式英语和英式英语是不一样的。中国:CN、美国是US,国家缩写都是大写的。

新建suiyi_zh_CN.properties

bjsxt.username=用户名
bjsxt.password=密码
bjsxt.submit=登录

新建suiyi_en_US.properties

bjsxt.username=username
bjsxt.password=password
bjsxt.submit=login

(2)在springmvc.xml中添加额外配置。

   
   
       
   

   
   

(3)新建控制单元

    @RequestMapping("/showForm")
    public String showForm(){
        return "/form.jsp";
    }

(4)新建页面:

        在上面使用taglib执行引入标签库

  根据语言环境负责加载属性文件中key的值。中文环境就加载suiyi_zh_CN.properties文件内容,英文环境就加载suiyi_en_US.properties文件内容

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>


    Title


    
       
       
        "/>    

十七、SpringMVC常见组件

DispatcherServlet:前端控制器。Spring MVC的入口,也是整个流程控制中心。其他组件由DispatcherServlet统一调度,降低了组件和组件之间的耦合度。

MultipartResovler:多部分处理器。文件上传时需要使用。

LocaleResolver:解决客户端的区域和时区问题。

ThemeResolver:主题解析器。刻提供自定义布局。

HandlerMapping: 映射处理器。主要负责处理URL,并找到对应的HandlerMethod。简单说就是找@RequestMapping注解中映射路径是否有和URL匹配的。

HandlerAdapter:适配器。负责调用具体的HandlerMethod。

HandlerExceptionResovler:异常处理器。异常处理,根据不同异常返回视图。

RequestToViewNameTranslator:从请求中获取到视图名称。

ViewResovler:视图解析器,负责解析字符串视图名和物理视图文件的。

FlashMapManager:主要用于存储属性的,本质是一个Map。多用在重定向时。FlashMap在重定向之前存储,重定向之后删除。

ModelAndView:模型和视图。Spring MVC中提供的模型和视图接口。

HandlerInterceptor:拦截器。拦截控制器资源的。

十八、SpringMVC运行原理 

1.客户端向服务端发起请求,Spring MVC总体入口DispatcherServlet进行请求分发。

2.DispatcherServlet把URL交给映射处理器HandlerMapping进行解析URL。并寻找是否具有对应的控制单元。

3.如果存在控制单元,执行拦截器Interceptor的预处理方法preHandle进行处理。如果不存在对应控制单元,拦截器不执行。

4.如果拦截器允许放行,返回给Servlet分发器DispatcherServlet,调用后续组件。

5.Servlet分发器DispatcherServlet使用适配处理器HandlerAdapter,调用具体的控制单元方法。

6.执行单元方法HandlerMethod。

7.控制单元HandlerMethod执行完成后产生模型和视图组件ModelAndView。

8.返回模型和视图组件给Servlet分发器DispatcherServlet。如果有拦截器Interceptor,执行postHandle

9.Servlet分发器DispatcherServlet调用视图解析器ViewResolver解析视图

10.产生视图View对象,执行了视图对应的资源。

11.把结果返回给Servlet分发器DispatcherServlet。如果有拦截器Interceptor,执行拦截器的afterCompletion

12.Servlet分发器把最终视图执行结果响应给客户端浏览器。

你可能感兴趣的:(mvc,前端)