springmvc基本使用

文章目录

    • 1.springmvc介绍
    • 2.简单入门
      • 2.1导入jar
      • 2.2.配置xml
      • 2.3配置web.xml
      • 2.4入门程序
    • 3.入门案列解析
      • 3.1流程(非常重要)
      • 3.2注解
    • 4.json参数返回
      • 4.1说明与基本配置
      • 4.2map类型
      • 4.3对象类型
      • 4.4数组类型
      • 4.5集合类型
      • 4.6基本数据类型+日期类型(看源码再说)
    • 5.请求参数
      • 中文请求乱码
      • 1.基本类型:注意使用包装类型 避免出转换异常
      • 2.接收数组 requestparam注解
      • 3.对象接收
      • 4.@requestBody:接收前台的json对象
      • 5.集合接收
      • 6.日期转换
    • 6.总结
      • 6.1后端传递到前台
      • 6.2前端传递到后端
      • 6.3HTTP的常见code编号
      • 6.4注解
    • 7.文件上传
    • 8.拦截器
    • 9.参数校验
    • 10.统一异常拦截
    • 11.swagger集成

配套视频地址:
https://www.bilibili.com/video/BV1ra411F7Er/
https://www.bilibili.com/video/BV18Z4y1g7Si/

Mvc:软件设计架构,解除v层的耦合,希望只写一套后台代码,就可以满足各种v端

1.springmvc介绍

1.接受前台或者其它服务的数据,并校验 json

2.返回数据给前端或者其它服务 json,流

3.指定跳转的页面或者其它服务 重定向或者跳转

数据接口

2.简单入门

2.1导入jar

spring-context
spring-context-support
spring-web
spring-webmvc
servlet-api
jsp-api

 <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.11.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context-support -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>5.2.11.RELEASE</version>
    </dependency>


    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.2.11.RELEASE</version>
    </dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.11.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.1</version>
      <scope>provided</scope>
    </dependency>
    
 <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.6.0</version>
            <configuration>
                <source>1.8</source> <!-- 源代码使用jdk1.8支持的特性 -->
                <target>1.8</target> <!-- 使用jvm1.8编译目标代码 -->
                <compilerArgs> <!-- 传递参数 -->
                    <arg>-parameters</arg>
                    <arg>-Xlint:unchecked</arg>
                    <arg>-Xlint:deprecation </arg>
                </compilerArgs>
            </configuration>
        </plugin>
    </plugins>
</build>

2.2.配置xml


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    
    <context:component-scan base-package="cn.cdqf.web">context:component-scan>

    
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/">property>
        <property name="suffix" value=".html">property>
    bean>
    
    <mvc:annotation-driven>mvc:annotation-driven>
beans>


2.3配置web.xml


<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    
    <servlet>
        <servlet-name>dispatcherServletservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        
    <init-param>
        <param-name>contextConfigLocationparam-name>
        <param-value>classpath:springmvc.xmlparam-value>
    init-param>
        
        <load-on-startup>1load-on-startup>
    servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServletservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>
    
    <servlet-mapping>
        <servlet-name>defaultservlet-name>
        <url-pattern>*.htmlurl-pattern>
    servlet-mapping>

web-app>


2.4入门程序

package cn.cdqf.web;

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

//标记这个类 要交给spring管理
@Controller//指定当前类要交给springmvc管理
@RequestMapping("test")//指定路径
public class TestController {
     

    //指定路径的注解  RequestMapping+RequestMapping
    @RequestMapping("test01")
    public String test01(){
     
        System.out.println("hello springmvc");
        return "abc";
    }
}

测试:访问http://localhost:xxxx/test/test01

使用modelAndview视图:

package cn.cdqf.web;

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

//标记这个类 要交给spring管理
@Controller//指定当前类要交给springmvc管理
@RequestMapping("test")//指定路径
public class TestController {
     

    //指定路径的注解  RequestMapping+RequestMapping
    @RequestMapping(value = "test01",method = RequestMethod.POST
    ,consumes="text/html")
    public ModelAndView test01(){
     
        //数据+试图
        ModelAndView modelAndView = new ModelAndView();
        //request.setAttribute();
        modelAndView.addObject("name","zhangsan");
        modelAndView.setViewName("abc");
        System.out.println("hello springmvc");
        return modelAndView;
    }
}


测试:访问http://localhost:xxxx/test/test01 会默认跳转到http://localhost:xxxx/test/abc路径

abc没有写前面的下划线就是相对路径,相对于当前controller而言,如果写了**/abc**就是绝对路径,访问了就是http://localhost:xxx/abc了

3.入门案列解析

后面的springmvc源码学习还会详细的学习这块

3.1流程(非常重要)

初始化容器的时候,tomcat会读取xml文件------->dispatchServlet(初始化这个类)------>contextConfigLocation

------->springmvc.xml-------->base-package=“cn.cdqf.web”(扫描这个包)------>递归读取下面所有java文件---->

cn.cdqf.web.TestController(反射class.forName(""))------>获得class对象------>反射获得注解(@Controller有这个标记的类就是要交给springmvc管理的类)------>类上面requestMapping(namespace)------->再读取方法上面的

requestMapping两个requestMapping组成该方法对应的唯一路径

/test/test01----->public String test01()(Method对象) .invoke(某个对象,参数)

handlerMapping类 属性:url Method Object(conrtroller对象)

List<HandlerMapping> handlerMappings; 描述了url与handler,method的对应关系
HandlerAdapter:调用方法,适配参数
List<HandlerAdapter> handlerAdapters;

ModelAndView:数据视图
ViewResolver:视图解析器

abc.html--->io流读取到里面所有内容(字符串)----${
     name}(正则表达式)---->去除${
     }---->name---->request.getAttribute("name");



springmvc基本使用_第1张图片

url---->dispatchservlet----->handlerMapping(根据前端url,找对应handler(几个重要属性url,method,Object)以及Method)---->找不到就404,找到了就返回method,object(controller对象,框架帮我们通过反射创建)---->

交给handleradpater(适配参数,调用方法method.invoke(对象,参数))------>modelAndview(数据与视图)----->

viewResolver(视图解析)------>前端

3.2注解

@Controller

@RequestMapping
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

6种属性:

value: 指定请求的实际地址,指定的地址可以是URI Template 模式;url
method: 指定请求的method类型, GETPOSTPUTDELETE等;默认用get请求
consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
params: 指定request中必须包含某些参数值是,才让该方法处理。
headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求

从定向与跳转

package cn.cdqf.web;

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

//标记这个类 要交给spring管理
@Controller//指定当前类要交给springmvc管理
@RequestMapping("test")//指定路径
public class TestController {
     

    //指定路径的注解  RequestMapping+RequestMapping
    @RequestMapping(value = "test01",method = RequestMethod.POST
    ,consumes="text/html")
    public ModelAndView test01(){
     
        //数据+试图
        ModelAndView modelAndView = new ModelAndView();
        //request.setAttribute();
        modelAndView.addObject("name","zhangsan");
        modelAndView.setViewName("abc");
        System.out.println("hello springmvc");
        return modelAndView;
    }
    //test/index
    @RequestMapping("index")
    public String index(){
     
        //默认是跳转
        //return "abc";
        return  "abc";
    }

    @RequestMapping("indexA")
    public String indexA(){
     
        //默认是跳转
        //return "abc";
        //重定向 上面的方法
        return  "redirect:/test/index";
    }

    @RequestMapping("indexC")
    public String indexC(){
     
        //默认是跳转
        //return "abc";
        //重定向
        return  "redirect:https://www.baidu.com/";
    }

}

4.json参数返回

4.1说明与基本配置

注:jsp已经过时,前后端分离开发现在是主流,该课程只讲解前后端分离的ajax请求,全部使用json传递数据

导入json jar

Jackson fastJson GSON

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.73</version>
    </dependency>

<mvc:annotation-driven>mvc:annotation-driven>

<mvc:annotation-driven>
    
    <mvc:message-converters register-defaults="false">
        
        <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
        <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>

        
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <constructor-arg value="UTF-8"/>
        bean>
        
        <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
            <property name="defaultCharset" value="UTF-8"/>
            <property name="supportedMediaTypes">
                <list>
                    
                    <value>text/html;charset=UTF-8value>
                    <value>application/jsonvalue>
                list>
            property>
            <property name="fastJsonConfig" ref="fastJsonConfig"/>
        bean>
    mvc:message-converters>
mvc:annotation-driven>


<bean id="fastJsonConfig" class="com.alibaba.fastjson.support.config.FastJsonConfig">
    
    <property name="charset" value="UTF-8"/>

    <property name="serializerFeatures">
        <list>
            
            
            <value>WriteNullListAsEmptyvalue>
            
            <value>WriteDateUseDateFormatvalue>
            
            <value>PrettyFormatvalue>
            <value>WriteMapNullValuevalue>
            <value>WriteNullStringAsEmptyvalue>
            
            <value>DisableCircularReferenceDetectvalue>
        list>
    property>


导入jquery,bootsrap静态资源需要的包(见resouces目录),配置放过js文件

因为在springmvc中配置的路径拦截是/表示拦截所有,那么请求静态资源也会被拦截,所以得放过静态资源,百度搜索:springmvc放过静态资源

<!-- 对指定目录下的静态资源放行 -->
<mvc:resources location="/fonts/" mapping="/fonts/**"/>
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/js/" mapping="/js/**"/>

前端代码

<link href="/css/bootstrap.min.css">
    <script src="/js/jquery-3.3.1.min.js">script>
    <script src="/js/bootstrap.min.js">script>
head>
<body>
    <button id="ajax">点击button>
body>
<script>
    $(function () {
      
        $("#ajax").click(function () {
      
            $.ajax({
      
               url:"/ajax/ajax1",
                type:"GET",
                dataType:"json",//返回数据类型
                success:function (data) {
      
                    console.log(data);
                }
            })
        })
    })
script>

4.2map类型

4.3对象类型

4.4数组类型

4.5集合类型

4.6基本数据类型+日期类型(看源码再说)

返回json代码:
springmvc基本使用_第2张图片

package cn.cdqf.web;

import cn.cdqf.pojo.Student;
import cn.cdqf.pojo.Teacher;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.*;

@Controller
@RequestMapping("/json")
public class JsonController {
     


    /**
     * 经过配置 已经告诉了springmvc如果用户需要把返回值转换成json 就用fastJson,并且使用那些自定义配置
     *
     *
     */
    @RequestMapping(value = "jsonObject",method = RequestMethod.GET,produces = "application/json;charset=utf8")
    @ResponseBody//告诉springmvc  把我的返回值转成json给用户
    public Student getStudent(){
     
        Student student = new Student();
        student.setPassword("123456");
        student.setBirthday(new Date());

        Teacher teacher = new Teacher();
        teacher.setName("张瑞瑞");
        teacher.setStudents(Arrays.asList(student));
        //循环引用
        student.setTeacher(teacher);
        return student;
    }

    @RequestMapping(value = "jsonMap",method = RequestMethod.GET,produces = "application/json;charset=utf8")
    @ResponseBody//告诉springmvc  把我的返回值转成json给用户
    public Map<String,String> jsonMap(){
     
        Map<String,String> objectObjectHashMap = new HashMap<>();
        objectObjectHashMap.put("name","张三");
        objectObjectHashMap.put("password","123456");
        return objectObjectHashMap;
    }
    @RequestMapping(value = "jsonList",method = RequestMethod.GET,produces = "application/json;charset=utf8")
    @ResponseBody//告诉springmvc  把我的返回值转成json给用户
    public List<Student> jsonList(){
     
        Student student = new Student();
        student.setPassword("123456");
        student.setBirthday(new Date());
        student.setName("张三");
        Student student2 = new Student();
        student2.setPassword("123456");
        student2.setBirthday(new Date());
        student2.setName("李四");
        Student student3 = new Student();
        student3.setPassword("123456");
        student3.setBirthday(new Date());
        student3.setName("王五");
        return Arrays.asList(student,student2,student3);
    }


    @RequestMapping(value = "jsonArr",method = RequestMethod.GET,produces = "application/json;charset=utf8")
    @ResponseBody//告诉springmvc  把我的返回值转成json给用户
    public Student[] jsonArr(){
     
        Student student = new Student();
        student.setPassword("123456");
        student.setBirthday(new Date());
        student.setName("张三");
        Student student2 = new Student();
        student2.setPassword("123456");
        student2.setBirthday(new Date());
        student2.setName("李四");
        Student student3 = new Student();
        student3.setPassword("123456");
        student3.setBirthday(new Date());
        student3.setName("王五");
        return new Student[]{
     student,student2,student3};
    }

    @RequestMapping(value = "jsonDate",method = RequestMethod.GET,produces = "application/json;charset=utf8")
    @ResponseBody//告诉springmvc  把我的返回值转成json给用户
    public Date getDate(){
     
        return new Date();
    }


    @RequestMapping(value = "jsonStr",method = RequestMethod.GET,produces = "application/json;charset=utf8")
    @ResponseBody//告诉springmvc  把我的返回值转成json给用户
    public String jsonStr(){
     
        return "天青色等烟雨";
    }
}

5.请求参数

中文请求乱码


<filter>
    <filter-name>characterEncodingFilterfilter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
    
    <init-param>
        <param-name>encodingparam-name>
        <param-value>UTF-8param-value>
    init-param>
filter>
<filter-mapping>
    <filter-name>characterEncodingFilterfilter-name>
    <url-pattern>/*url-pattern>
filter-mapping>

1.基本类型:注意使用包装类型 避免出转换异常

//@Controller//标记这个类要被springmvc管理
//@ResponseBody//作用在类上 相当于所有的方法都加了这个
@RestController//@ResponseBody+@Controller
public class ParamController {
     

    //@RequestMapping(value = "",method = RequestMethod.GET)
    @GetMapping("/param/param01")//RequestMapping的get请求方式
    //自动拆箱---->有可能出现空指针异常
    public Student param01(String name,Integer age){
     //name对应前端name age对应前端的age
        System.out.println("接收到调用方传递的参数:"+name+","+age);
        Student student = new Student();
        student.setName("张三");
        return student;
    }
}
$(function () {
     
        $("#ajax").click(function () {
     

            $.ajax({
     
                url:"/param/param01?name=李四",
                type:"GET",
                data:{
     age:10},
                dataType:"json",//返回数据类型
                success:function (data) {
     
                    console.log(data);
                    //for(var student in data){
     
                     //   console.log(data[student].name);
                    //}

                }
            })
        })
    })

2.接收数组 requestparam注解

HTTP Status 400 – Bad Request:必须的参数没有写,或者是参数类型不对
    //@RequestMapping(value = "",method = RequestMethod.GET)
    @GetMapping("/param/param01")//RequestMapping的get请求方式
    //自动拆箱---->有可能出现空指针异常
    //不写RequestParam的时候 如果前端没有传递name 最多name接收到为null
    //写了以后 如果没有name参数 直接报错
    //前端传递参数的名称 与RequestParam的value对应 后面的参数名字都不重要了
    public Student param01(@RequestParam(required = false,value = "name") String aaa,
                           Integer age){
     
        System.out.println("接收到调用方传递的参数:"+aaa+","+age);
        Student student = new Student();
        student.setName("张三");
        return student;
    }

3.对象接收

 //@RequestMapping(method = RequestMethod.POST)
    @PostMapping("/param/param02")
    //student对象里面包含了name、password属性 所以可以
    //直接把前台传递的这个key的参数 放入student对象
    public Student param02(Student student,String name){
     
        System.out.println("获得前台的参数:"+student);
        return student;
    }
$("#ajax2").click(function () {
     

            $.ajax({
     
                url:"/param/param02?name=李四",
                type:"POST",
                data:{
     password:"123456"},
                dataType:"json",//返回数据类型
                success:function (data) {
     
                    console.log(data);
                    //for(var student in data){
     
                    //   console.log(data[student].name);
                    //}

                }
            })
        })

4.@requestBody:接收前台的json对象

415:后端希望接收到一个json对象,但是前端传递不是

 $("#ajax3").click(function () {
     
            var student ={
     
                "name":"张三",
                password:"123456"
            }
            console.log(JSON.stringify(student))
            $.ajax({
     
                url:"/param/param03",
                type:"POST",//必须是post
                data:JSON.stringify(student),//json字符串
                dataType:"json",//返回数据类型
                contentType:"application/json",//前端传递到后端的类型
                success:function (data) {
     
                    console.log(data);
                    //for(var student in data){
     
                    //   console.log(data[student].name);
                    //}

                }
            })
        })

 @PostMapping("/param/param03")
    //RequestBody:告诉springmvc我要的json对象
    public Student param03(@RequestBody Student student){
     
        System.out.println("获得前台的参数:"+student);
        return student;
    }

5.集合接收

 @PostMapping("/param/param04")
    public List<Student> getList(@RequestBody ArrayList<Student> students){
     
        System.out.println(students);
        return students;
    }

 $("#ajax4").click(function () {
     
            var student =[
                {
     
                    "name":"张三",
                    password:"123456"
                },
                {
     
                    "name":"李四",
                    password:"123456"
                }
            ]
            $.ajax({
     
                url:"/param/param04",
                type:"POST",
                data:JSON.stringify(student),//json字符串
                dataType:"json",//返回数据类型
                contentType:"application/json",//前端传递到后端的类型
                success:function (data) {
     
                    console.log(data);
                    //for(var student in data){
     
                    //   console.log(data[student].name);
                    //}

                }
            })
        })

6.日期转换

当前版本未出现日期转换问题,如有问题配置一个日期转换器即可(下面的代码未测试,应该没问题)

<!-- 配置注解驱动,使用自定义日期转换器 -->
	<mvc:annotation-driven conversion-service="myConvert"/>
	
	<!-- 日期转换器 -->
		<!-- 定义转换器 -->
	<bean id="myConvert" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
		<property name="converters">
			<set>
				<!-- 自己的写的转换器全路径名 -->
				<bean class="com.xue.utils.MyConvert"></bean>
			</set>
		</property>
	</bean>

package com.xue.utils;
 
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
 
import org.springframework.core.convert.converter.Converter;
 
/**
 * 定义时间转换器springmvc
 * Converter
 * S:source要转换的源类型 
 * T:target 要转换成的数据类型
 * @author 
 *
 */
public class MyConvert implements Converter<String, Date> {
     
 
	@Override
	public Date convert(String source) {
     
		Date result = null;
		try {
     
			//指定日期的格式
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			//将源数据转为指定日期格式
			result = sdf.parse(source);
		} catch (ParseException e) {
     
			e.printStackTrace();
		}
		//返回转换后的时间格式日期
		return result;
	}
 
}

6.总结

6.1后端传递到前台

1.跳转页面
A:return ”index” 如果在springmvc.xml配置了前后缀就会默认拼接 如果没有配置 就需要自己写全路径
B: return “redirect:index.html” redirect不会去拼接
无论是重定向或者跳转都可以调用后台的方法

C:modelAndView addObject()添加数据 添加的数据 放在request作用域 viewName:视图名称

2.返回json
1.@ResponseBody
2.@RestController = @ResponseBody+@Controller

6.2前端传递到后端

1.如果是普通get请求 只需要 请求参数 与方法接收参数的名称相同即可,对象的属性跟请求参数相同也会自动匹配
2.传递数组/集合 :
A:前端 通过key—value 比如{id:ids} @RequestParam(“id[]”) POST请求
B:前端传递json字符串 json.stringfy() 需要配置contentType:”application/json”
后端方法:@RequestBody 名字不重要,但是都写成相同

6.3HTTP的常见code编号

404:请求路径错误

400:参数错误

405:请求方式 错误 比如后端 method=RequestMethod.POST 前端采用get请求

302:重定向

304:走浏览器缓存

500:后台代码抛异常

415:json转换问题,后台用了requestbody

6.4注解

GetMapping、postMapping、requestParam、requestBody、responseBody、restController

7.文件上传

导入jar

  <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
    </dependency>

配置:


    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="#{1024*1024*80}"/>
        <property name="defaultEncoding" value="utf-8"/>
    bean>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>springmvc uploadtitle>
    <link href="/css/bootstrap.min.css">
    <script src="/js/jquery-3.3.1.min.js">script>
    <script src="/js/bootstrap.min.js">script>
head>
<body>   
        <form id="uploadForm" enctype="multipart/form-data">
            <input id="file" type="file" name="file" /><br>
            <input id="file22" type="file" name="file" /><br>

            <input type="text" name="username"/><br>
            <button id="upload" type="button">uploadbutton>
        form>
body>
<script>
    $(function () {
      
        $("#upload").click(function () {
      
            $.ajax({
      
                url: '/upload',
                type: 'POST',
                cache: false,
                data: new FormData($('#uploadForm')[0]),
                processData: false,
                contentType: false,
                success: function (res) {
      
                    console.log(res);
                }
            })

        })
    })

script>
html>
 

这里要注意几点:

processData设置为false。因为data值是FormData对象,不需要对数据做处理。
<form>标签添加enctype="multipart/form-data"属性。
cache设置为false,上传文件不需要缓存。
contentType设置为false,不设置contentType值,因为是由<form>表单构造的FormData对象,且已经声明了属性enctype="multipart/form-data",所以这里设置为false。
上传后,服务器端代码需要使用从查询参数名为file获取文件输入流对象,因为<input>中声明的是name="file"。

如果不是用<form>表单构造FormData对象又该怎么做呢?

 
 
2.使用FormData对象添加字段方式上传文件
 

HTML代码

<div id="uploadForm">
    <input id="file" type="file"/>
    <button id="upload" type="button">uploadbutton>
div>
这里没有<form>标签,也没有enctype="multipart/form-data"属性。

 

javascript代码

var formData = new FormData();
formData.append('file', $('#file')[0].files[0]);
$.ajax({
    url: '/upload',
    type: 'POST',
    cache: false,
    data: formData,
    processData: false,
    contentType: false
}).done(function(res) {
}).fail(function(res) {});
 

这里有几处不一样:

append()的第二个参数应是文件对象,即$('#file')[0].files[0]。
contentType也要设置为‘false’。
 

从代码$('#file')[0].files[0]中可以看到一个<input type="file">标签能够上传多个文件,
只需要在<input type="file">里添加multiple或multiple="multiple"属性。

 

package cn.cdqf.web;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@RestController
public class UploadController {
     

    @PostMapping("upload")
    public Map upload(String username, String password,
                      @RequestParam("file") MultipartFile[] files) throws IOException {
     
        for(MultipartFile file:files){
     
            //获得名称
            String originalFilename = file.getOriginalFilename();
            String name = file.getName();
            //暂时知道如何存储,在项目中会有单独服务器 到时候在处理
            File file1 = new File("D://"+originalFilename);
            System.out.println(file1);
            file.transferTo(file1);
        }

        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
        return objectObjectHashMap;
    }
}

8.拦截器

过滤器,优于框架执行
过滤器不依赖框架,移植性比较好
request,response,filterChain
针对于现在用springmvc的情况下
可以获得request里面所有参数,但是无法获得要执行的controller与方法

拦截器有三个参数HttpServletRequest request, HttpServletResponse response, Object handler
handler:就可以拿到目标方法

拦截器1:

package cn.cdqf.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 {
     
    //http://localhost:8888/param/param01 ----->abc()
    //会在目标方法abc()执行之前执行,如果return true那么就继续执行目标方法,如果是false就在这里就结束
    //handler:参数就可以获得controller以及执行的目标方法,这个过滤器是拿不到的
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
     
        System.out.println("拦截器1执行了...");
        return true;
    }
    //目标方法正常执行结束后执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
     
        System.out.println("拦截器1:目标方法正常执行结束后执行");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
     
        System.out.println("拦截器1:不管有没有异常都会执行....");
    }
}

拦截器2:

package cn.cdqf.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 MyInterceptor2 implements HandlerInterceptor {
     
    //http://localhost:8888/param/param01 ----->abc()
    //会在目标方法abc()执行之前执行,如果return true那么就继续执行目标方法,如果是false就在这里就结束
    //handler:参数就可以获得controller以及执行的目标方法,这个过滤器是拿不到的
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
     
        System.out.println("拦截器2执行了...");
        return true;
    }
    //目标方法正常执行结束后执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
     
        System.out.println("拦截器2:目标方法正常执行结束后执行");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
     
        System.out.println("拦截器2:不管有没有异常都会执行....");
    }
}


配置:

<mvc:interceptors>
        <mvc:interceptor>
            
            <mvc:mapping path="/**"/>
            <bean class="cn.cdqf.interceptor.MyInterceptor">bean>
        mvc:interceptor>
        <mvc:interceptor>
            
            <mvc:mapping path="/**"/>
            <bean class="cn.cdqf.interceptor.MyInterceptor2">bean>
        mvc:interceptor>
    mvc:interceptors>

结果:

拦截器1执行了...
拦截器2执行了...
接收到调用方传递的参数:李四,10
拦截器2:目标方法正常执行结束后执行
拦截器1:目标方法正常执行结束后执行
拦截器2:不管有没有异常都会执行....
拦截器1:不管有没有异常都会执行....

9.参数校验

前端校验:可以减少服务器压力,因为前端校验了就不需要走服务器,不安全,别人有很多种方式可以跳过你的检验

后端校验:安全,服务器压力大

开发的时候应该前端+后端

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.7.Final</version>
</dependency>


springmvc基本使用_第3张图片

package cn.cdqf.param;

import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;

public class User implements Serializable {
     

    @NotBlank(message = "用户名不能为null")
    private String username;

    @Min(value = 18,message = "未成年人禁止入内")
    @Max(value = 35,message = "年龄太大也别来了")
    private int age;
    @Length(message = "长度必须在5-10之间",min = 5,max = 10)
    @NotBlank(message = "地址不能为null")
    private String address;

    public String getUsername() {
     
        return username;
    }

    public void setUsername(String username) {
     
        this.username = username;
    }

    public int getAge() {
     
        return age;
    }

    public void setAge(int age) {
     
        this.age = age;
    }

    public String getAddress() {
     
        return address;
    }

    public void setAddress(String address) {
     
        this.address = address;
    }
}


package cn.cdqf.param;

import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class Param2Controller {
     

    @GetMapping("param/check01")
    public Map<Object,Object> check01(@Validated User user, BindingResult bindingResult){
     

        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
        if(bindingResult.hasErrors()){
     //参数校验没有过
            //取出错误
            List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            for(FieldError fieldError:fieldErrors){
     
                String field = fieldError.getField();//username属性名
                String defaultMessage = fieldError.getDefaultMessage();//错误信息
                objectObjectHashMap.put(field,defaultMessage);
            }
        }
        return objectObjectHashMap;
    }
}


校验组

public interface GroupA {

}

public interface GroupB {

}

 @NotNull(message="id不能为空!",groups = {GroupA.class})
    private Integer id;
    
    @NotBlank(message="用户名不能为空!",groups = {GroupB.class})
    @Size(min=4,max=12,message="用户名的长度在4~12之间!")
    private String username;
    
    @Validated(value= {GroupB.class})//只能校验这个组的属性
    
*@Validated注解表示使用Spring的校验机制,支持分组校验,声明在入参上.
*@Valid注解表示使用Hibernate的校验机制,不支持分组校验,声明在入参上.

10.统一异常拦截

后台代码出错了,应该给用户返回一个比较友好的提示,例如:程序君崩溃了

package cn.cdqf.param;

import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class Param2Controller {
     

    @GetMapping("param/check01")
    public Map<Object,Object> check01(@Validated User user, BindingResult bindingResult){
     
        BindingResultUtil.check(bindingResult);//校验,不应该有返回值 不然跟业务耦合了。。
        
        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
        return objectObjectHashMap;
    }
}


package cn.cdqf.param;

import java.util.Map;

public class CustomException extends RuntimeException{
    private Map map;
    public CustomException(){
        super();
    }

    public CustomException(Map map){
        super();
        this.map = map;
    }

    public Map getMap(){
        return map;
    }
}


package cn.cdqf.param;

import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;

import java.util.HashMap;
import java.util.List;

public class BindingResultUtil {
     
    public static  void check(BindingResult bindingResult){
     
        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
        if(bindingResult.hasErrors()){
     //参数校验没有过
            //取出错误
            List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            for(FieldError fieldError:fieldErrors){
     
                String field = fieldError.getField();//username属性名
                String defaultMessage = fieldError.getDefaultMessage();//错误信息
                objectObjectHashMap.put(field,defaultMessage);
            }
        }
        //没有错
        if(objectObjectHashMap.size()==0)return;
        //人为抛出异常,代码中尽量不要去抛异常,效率低
        throw new CustomException(objectObjectHashMap);
    }
}


package cn.cdqf.param;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

/**
 * 我的异常处理器:拦截所有controller,所有controller抛出异常这个地方都能知道
 * 虽然没有配置也起效果,因为它在被扫描的包
 */
//@ControllerAdvice//增强所有controller的功能
@RestControllerAdvice//ControllerAdvice+responseBody
public class MyExceptionHandler {
     

    @ExceptionHandler(Exception.class)//抓异常,只要有我们指定的异常就会这个注解拦到
    public Map<Object,Object> exception(Exception ex){
     
        //代码走到这里 说明出现了在开发阶段,以及测试阶段都没有发现的异常 程序出了bug
        //发邮箱给这个项目的负责人,后台要打印日志(为了后面改bug)
        return new HashMap<>();//这儿应该给用户返回比较友好的界面,比如:服务器奔溃了。。。
    }
    //拦截的是自定异常
    @ExceptionHandler(CustomException.class)
    public Map<Object,Object> customException(CustomException ex){
     
        Map<Object, Object> map = ex.getMap();
        return map;
    }

}


11.swagger集成

这里只是入门,因为这个跟项目业务不相关,不用单独花时间去记,后面写项目会天天用

springfox-swagger2
springfox-swagger-ui

 <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
    <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger2</artifactId>
      <version>2.9.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
    <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger-ui</artifactId>
      <version>2.9.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.11.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.11.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.11.0</version>
    </dependency>

配置:记得扫描配置类

package cn.cdqf.swagger;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2//开启swagger支持
public class SwaggerConfig {
     
    @Bean//对象 把这个对象交给spring管理
    public Docket api() {
     
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())  //显示所有类
                //.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))  //只显示添加@Api注解的类
                .build()
                .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
     
        return new ApiInfoBuilder()
                .title("军哥测试swagger")  //粗标题
                .description("java2007测试,有问题请拨打电话1888888888")   //描述
                .version("1.0.0")   //api version
                .termsOfServiceUrl("http://xxx.xxx.com")
                .license("LICENSE")   //链接名称
                .licenseUrl("http://xxx.xxx.com")   //链接地址
                .build();
    }

}


简单使用:

package cn.cdqf.swagger;

import cn.cdqf.pojo.Student;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Api("swagger测试controller")
public class SwaggerController {
     

    @GetMapping("swagger")
    @ApiOperation(value = "swagger测试接口")
    public Student swagger(
            String username,
            String password){
     
        Student student = new Student();
        student.setName(username);
        student.setPassword(password);
        return student;
    }
}


配置swagger界面放过:


    <mvc:resources mapping="swagger-ui.html" location="classpath:/META-INF/resources/" />
    <mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/" />

访问:

http://localhost:xxxx/swagger-ui.html

配套视频地址:
https://www.bilibili.com/video/BV1ra411F7Er/
https://www.bilibili.com/video/BV18Z4y1g7Si/

欢迎加入qq群,一起学习
springmvc基本使用_第4张图片

你可能感兴趣的:(ssm,java,spring)