Spring-MVC学习笔记

MVC三层架构

MVC

  • Model:模型
  • View:视图
  • Controller:控制器

1.初识MVC

springMVC官方文档:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html
SpringMVC框架技术:https://blog.csdn.net/weixin_44900198/article/details/105710177

项目:springMVC_study
导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>springMVC_study</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>springMVC_01_servlet</module>
    </modules>

    <!--导入依赖-->
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>


    </dependencies>

</project>

需要回顾servlet

  • Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。

2.HelloMVC

模块:springMVC_02_helloMVC
结构
在这里插入图片描述
步骤

  1. 配置web.xml配置文件 注册DispatcherServlet
<?xml version="1.0" encoding="UTF-8"?>
<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">

    <!--1.注册DispatcherServlet 前端控制器
    	这是SpringMVC的核心 :请求分发器
    	所有的请求都会通过它-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <!--DispatcherServlet需要关联一个spring配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
		<!--启动级别 1 服务器启动就会启动-->
        <load-on-startup>1</load-on-startup>
    </servlet>
        <!--springMVC中  /  /*
    	/  : 匹配所有的请求,不匹配jsp页面
    	/* : 匹配所有请求,包括jsp页面
   	 -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
  1. 配置spring配置文件 springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd">

   <!--添加处理器映射器-->
   <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

   <!--添加处理器适配器-->
   <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

   <!--添加视图解析器-->
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
         id="internalResourceViewResolver">

       <!--前缀  也就是工程路径到jsp页面前面的一部分-->
       <property name="prefix" value="/WEB-INF/jsp/"/>
       <!--后缀  也就是jsp文件的后缀名-->
       <property name="suffix" value=".jsp"/>
   </bean>

   <!--将自己得类交给IOC容器 注册bean
   处理器映射器根据id去映射  相当于url-pattern -->
   <bean id="/hello" class="com.it.controller.HelloController"/>
</beans>

编写HelloController.java

package com.it.controller;


import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

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

/**
* @author shkstart
* @create 2020-04-19 11:49
*/
//注意:我们这的到的包是是接口包不是注释包
public class HelloController implements Controller {

   public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
      //ModelAndView 模型和视图
       ModelAndView mv = new ModelAndView();
   
      //业务代码
      String result = "HelloSpringMVC";

       //封装对象 放在ModelAndView中
       mv.addObject("msg","result");

       //封装要跳转的视图 放在ModelAndView中
       mv.setViewName("hello");// /WEB-INF/jsp/hello.jsp
       //返回模型视图对象
       return mv;

   }
}

WEB-INF / jsp / hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    ${msg}
</body>
</html>

执行步骤

  • 用户访问页面
  • 调用DispatcherServlet 前端控制器
  • 请求映射器 HandlerMappeing
  • 请求适配器 HandlerAdapter
  • 控制器
  • 视图解析器

注意

  • 如果我们访问tomcat 网页出现 404 错误
    我们先检查代码,如果代码没问题就可能是环境问题
    可能是jar包没有导入进来 解决方法
    在这里插入图片描述

3.使用注解开发SpringMVC

模块 springMVC_03_annotation

注意:maven项目我们需要右击模块,点Add Frameworks Support ,勾选java web ,在点击file,选择project structure ,选择Artifacts ,选中模块,在web-inf 目录下创建lib文件夹,添加jar包
在这里插入图片描述

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">
    
    <!--注册DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--配置springmvc配置文件 进行关联-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>

        <!--启动顺序,数字越小启动越快-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--所有请求都被springmvc拦截-->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

springmvc-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--配置自动扫描包,此包下的所有注解生效-->
    <context:component-scan base-package="com.it.controller"/>

    <!--让Spring不处理静态资源 例如 .css .js .html .mp3-->
    <mvc:default-servlet-handler/>

    <!--支持MVC注解
        在springMVC中一般使用@RequestMapping完成映射
        想要使@RequestMapping生效
        必须在上下文中注册DefaultAnnotationMapping
        和一个AnnotationMethodHandlerAdapter实例
        这两个实例分别在类级别和方法级别处理
        而annotation-driven配置帮助我们自动完成上述两个实例的注入-->
    <mvc:annotation-driven/>

    <!--配置视图解析器-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

根据springmvc中的视图解析器前缀后缀自动找到包
web-inf / jsp / hello.jsp

<%--
  Created by IntelliJ IDEA.
  User: 刘浩
  Date: 2020/4/19
  Time: 16:16
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${msg}
</body>
</html>

创建controller 包 HelloController类

package com.it.controller;

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

/**
 * @author shkstart
 * @create 2020-04-19 16:18
 */
@Controller
public class HelloController {

    //真实访问地址:项目名/hello
    @RequestMapping("/hello")
    public String hello(Model model){
        //向模型中添加msg属性 可以在jsp页面中取
        model.addAttribute("msg","Hello,SpringMVCAnnotation");
        //被解析器解析处理 对应跳转的jsp名称
        //web-inf/jsp/hello.jsp
        return "hello";
    }
}

4.Controller 和 RestFul风格

模块:springMVC_04_controller

控制器 Controller

  • 控制器复杂提供访问应用程序的行为,通常通过接口定义注解定义
  • 控制器负责解析用户的请求并将其转换为Model模型
  • 在SpringMVC中一个控制器可以包含多个方法
  • 在SpringMVC中,对Controller的配置有很多种

实现Controller接口的操作步骤(不建议使用)
1.配置Web.xml配置文件

  • 注册DispatcherServlet
  • initParam标签配置spring配置文件关联
  • load-on.startup 启动顺序
  1. 配置关联的spring配置文件
  • 注册视图解析器对象

3.创建Controller类 实现Controller接口

  • 重写HandleRequest 方法 返回ModelAndView对象
  1. 将Controller类注册到IOC容器中
  • bean name 为访问路径
  • class 为 对应处理请求的类 也就是Controller

5.编写前端jsp页面,注意要对应视图解析器的前缀后缀

代码在模块中

使用注解实现Controller 操作步骤(建议使用)
1.配置Web.xml配置文件

  • 注册DispatcherServlet
  • initParam标签配置spring配置文件关联
  • load-on.startup 启动顺序
  1. 配置关联的spring配置文件
  • 配置自动扫描包,确保spring能扫描到控制器
  • 配置spring不处理静态资源
  • 配置mvc:annotation-driven 支持MVC注解
    <!--自动扫描包下的类 使类下注解生效-->
   <context:component-scan base-package="com.it.controller"/>
   <!--springmvc 不处理静态资源-->
   <mvc:default-servlet-handler/>
   <!--支持MVC注解 这个注解会帮助我们自动生成 映射器 和 适配器-->
   <mvc:annotation-driven/>

3.创建Controller类 类名上加注解@Controller

  • 写方法 方法名上@RequestMapping(“访问地址”)
  • 返回值为视图位置
@Controller//代表这个类会被spring接管,别注解的类下的方法如果返回值为string
           //并且有具体页面可以跳转,就会被视图解析器解析
public class HelloControllerAnnotation {

   @RequestMapping("/hello")//配置访问地址
   public String hello(Model model){

       //处理业务层代码
       String result = "Service层业务逻辑";

       //封装对象到Model
       model.addAttribute("msg",result);

       //返回的值通过视图解析器前缀后缀拼接成一个url
       return "hello";
   }

4.编写前端jsp页面,注意要对应视图解析器的前缀后缀

RequestMapping()
@requestMapping 注解用于映射url到控制器类或特定的一个处理程序方法,可用于类上方法上 类上表示所有请求都是以该地址作为父路径

运用在类上 访问地址就变成了 parent/url
@Controller
@RequestMapping("parent")
public class controller{
	@RequestMapping("url")
	public String test1(){
		return "";
	}
}

运用在方法上 访问地址 url
@Controller
public class Controller(){
	@RequestMapping("url")
	public String test1(){
		
	}
}

RestFul风格
RestFul就是一个资源定位及资源操作风格,不是标准也不是协议,只是一种风格,基于这个风格设计软件更简洁,更有层次,更易实现缓存机制
@PathVariable 路径变量 将参数绑定到url模板上
在这里插入图片描述

@Controller
public class HelloControllerRestFul {

    //原来的访问路径:http://localhost:8080/add?a=2&b=3
    //RestFul的访问路径:http://localhost:8080/add/1/2
    //两种都是传递参数

    //value属性 就是请求的url地址+参数
    //method属性 就是限制用什么请求方式访问
    @RequestMapping(value="/add/{a}/{b}",method = RequestMethod.GET)
    public String add(@PathVariable int a, @PathVariable String b, Model model){
         //@PathVariable 路径变量 将参数绑定到url模板上
        String result = a + b;
        model.addAttribute("msg","结果:" + result);
        return "hello";
    }
}

还可以通过不同的注解限定请求方式

@GetMapping("add/a/b")
@PostMapping("add/a/b")
@DeleteMapping("add/a/b")
@PutMapping("add/a/b")
@PatchMapping("add/a/b")

5. 请求转发 和 请求重定向

ModelAndView
设置ModelAndView对象,根据view名称和视图解析器跳转到指定页面
页面: 视图解析器前缀 + viewName + 视图解析器后缀

- SpringMVC 不配置视图解析器

显式配置转发  forward

@Controller
public class ModelTest1 {
    @RequestMapping("/test")
    public String test1(Model model){
        model.addAttribute("msg","不配置视图解析器");
        //返回值  :  forward: / + 项目路径
        return "forward:/WEB-INF/jsp/hello.jsp";
    }
}
显式配置重定向   redirect

@Controller
public class ModelTest1 {
    @RequestMapping("/test")
    public String test1(Model model){
        model.addAttribute("msg","不配置视图解析器");
        //返回值  :  forward: / + 项目路径
        return "redirect: /index.jsp";
    }
}

- SpringMVC配置视图解析器

  • springMVC 默认式转发
  • 如果需要转发,就直接return 视图解析拼接的中间部分 因为视图解析器会根据 前缀 + return的值 + 后缀 拼接一个完整的url
  • 如果需要重定向,就需要return redirect:重定向地址 需要写重定完全地址
    在这里插入图片描述
重定向
@Controller
public class ModelTest1 {
    @RequestMapping("/test")
    public String test1(Model model){
        model.addAttribute("msg","不配置视图解析器");
        //重定向:redirect后跟全地址
        return "redirect: /index.jsp";
    }
}
转发
@Controller
public class ModelTest1 {
    @RequestMapping("/test")
    public String test1(Model model){
        model.addAttribute("msg","不配置视图解析器");
        //转发: return 需要拼接的
        return "hello";
    }
}
return "forward:hello" : WEB-INF/jsp/return "forward:/hello" : WEB-INF/jsp 下

6.接收请求参数以及回显数据

接收普通类型前端参数

@Controller //注册到IOC容器 交给Spring管理
@RequestMapping("user") //将该地址作为父路径
public class UserController {

    //方法参数 --- 就是客户端传递过来的参数
    @RequestMapping("/t1") //@RequestParam() 如果参数是前端的就必须加上
    public String test1(@RequestParam("username") String name, Model model){

        //1.接收前端参数
        System.out.println(name);

        //将返回结果传递给前端
        model.addAttribute("name",name);
        //视图跳转
        return "forward:/hello";
    }
}

接收对象前端参数

    //前端传递一个对象
    /*
        前端传递的参数名和User类的属性名去比较 如果一样就赋值 不一样为null

        要求就是提交的表单域和对象的属性名一致,参数使用对象即可
     */

    @GetMapping("/t2")
    public String test2(User user){
        System.out.println(user);
        return "forward:/hello";
    }
}

7.解决乱码

Tomcat配置文件 serve.xml

<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />

Spring的filter过滤器

<!--    spring的编码过滤器-->
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

如果spring的filter过滤器都无法解决 就用下面这个

package com.it.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;

public class EncodingFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //处理response的字符编码
        HttpServletResponse myResponse=(HttpServletResponse) response;
        myResponse.setContentType("text/html;charset=UTF-8");

        // 转型为与协议相关对象
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        // 对request包装增强
        HttpServletRequest myrequest = new MyRequest(httpServletRequest);
        chain.doFilter(myrequest, response);
    }

    public void init(FilterConfig filterConfig) throws ServletException {
    }

}

//自定义request对象,HttpServletRequest的包装类
class MyRequest extends HttpServletRequestWrapper {

    private HttpServletRequest request;
    //是否编码的标记
    private boolean hasEncode;
    //定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
    public MyRequest(HttpServletRequest request) {
        super(request);// super必须写
        this.request = request;
    }

    // 对需要增强方法 进行覆盖
    @Override
    public Map getParameterMap() {
        // 先获得请求方式
        String method = request.getMethod();
        if (method.equalsIgnoreCase("post")) {
            // post请求
            try {
                // 处理post乱码
                request.setCharacterEncoding("utf-8");
                return request.getParameterMap();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        } else if (method.equalsIgnoreCase("get")) {
            // get请求
            Map<String, String[]> parameterMap = request.getParameterMap();
            if (!hasEncode) { // 确保get手动编码逻辑只运行一次
                for (String parameterName : parameterMap.keySet()) {
                    String[] values = parameterMap.get(parameterName);
                    if (values != null) {
                        for (int i = 0; i < values.length; i++) {
                            try {
                                // 处理get乱码
                                values[i] = new String(values[i]
                                        .getBytes("ISO-8859-1"), "utf-8");
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                hasEncode = true;
            }
            return parameterMap;
        }
        return super.getParameterMap();
    }

    //取一个值
    @Override
    public String getParameter(String name) {
        Map<String, String[]> parameterMap = getParameterMap();
        String[] values = parameterMap.get(name);
        if (values == null) {
            return null;
        }
        return values[0]; // 取回参数的第一个值
    }

    //取所有值
    @Override
    public String[] getParameterValues(String name) {
        Map<String, String[]> parameterMap = getParameterMap();
        String[] values = parameterMap.get(name);
        return values;
    }
}

web.xml

<filter>
	<filter-name>encodingFilter</filter-name>
	<filter-class>com.it.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>encodingFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

8.JSON

模块springMVC_05_json

导入依赖

    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.3</version>
        </dependency>
    </dependencies>

写一个JsonUtils工具类

package com.it.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import java.text.SimpleDateFormat;

/**
 * @author shkstart
 * @create 2020-04-21 10:08
 */
public class JsonUtils {

    /**
     *
     * @param object  返回object对应的json字符串
     * @return
     */
    public static String getJson(Object object){
        //不需要重复造轮子 直接调用下面的方法,给一个默认值
        return getJson(object,"yyyy-MM-dd HH:mm:ss");
    }


    /**
     *
     * @param object  日期对象 最后转换为json字符串
     * @param dateFormat 自定义日期格式,不适用json默认时间戳
     * @return  返回json字符串
     */
    public static String getJson(Object object,String dateFormat){
        ObjectMapper mapper = new ObjectMapper();

        //设置mapper不适用默认时间戳
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);

        //设置自定义时间戳
        mapper.setDateFormat(new SimpleDateFormat(dateFormat));

        try {
            //返回json字符串
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

在springmvc-servlet.xml中配置防止json乱码

 <!--mvc注解-->
    <mvc:annotation-driven>
        <!--    json乱码解决-->
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="UTF-8"/>
            </bean>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                        <property name="failOnEmptyBeans" value="false"/>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

测试

package com.it.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.it.pojo.User;
import com.it.utils.JsonUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author shkstart
 * @create 2020-04-21 9:21
 */
//@Controller  会走视图解析器
@RestController //标注这个类下的所有都不走视图解析器,都返回字符串
public class UserController {
    //produces 解决中文乱码
    //@RequestMapping(value="/j1",produces = "application/json;charset=utf-8")
    @RequestMapping(value="/j1")
   // @ResponseBody  表示这个方法不会走视图解析器,返回一个字符串,配合Controller使用
    public String json1() throws JsonProcessingException {

        //jackson ,ObjectMapper
        ObjectMapper mapper = new ObjectMapper();

        //创建一个对象
        User user = new User(1,"黄沙","123123");

        //将对象转化为Json字符串形式
        String userString = mapper.writeValueAsString(user);
        //JSON字符串形式 {键:值,键:值...}

        return userString;
    }

    @RequestMapping("j2")
    public String json2() throws JsonProcessingException {

        User user1 = new User(1,"流1","11");
        User user2 = new User(2,"流2","22");
        User user3 = new User(3,"流3","33");
        User user4 = new User(4,"流4","44");

        List<User> list = new ArrayList<User>();
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);

        //将list集合转化为json字符串
        return JsonUtils.getJson(list);
    }

    @RequestMapping("j3")
    public String json3() throws JsonProcessingException {

        return JsonUtils.getJson(new Date());

        //纯java方式
/*        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //将时间转换为json
        return new ObjectMapper().writeValueAsString(sdf.format(date));*/
    }
}
@RestController 标注这个类下的所有都不走视图解析器,都返回字符串
@@ResponseBody  表示这个方法不会走视图解析器,返回一个字符串,
配合@Controller使用

9. Ajax

模块:spinrgMVC_06_ajax
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。

  • AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

  • Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。

使用jQuery提供的ajax支持

jQuery.ajax(...)
      部分参数:
            url:请求地址
            type:请求方式,GET、POST(1.9.0之后用method)
        headers:请求头
            data:要发送的数据
    contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")
          async:是否异步
        timeout:设置请求超时时间(毫秒)
      beforeSend:发送请求前执行的函数(全局)
        complete:完成之后执行的回调函数(全局)
        success:成功之后执行的回调函数(全局)
          error:失败之后执行的回调函数(全局)
        accepts:通过请求头发送给服务器,告诉服务器当前客户端可接受的数据类型
        dataType:将服务器端返回的数据转换成指定类型
          "xml": 将服务器端返回的内容转换成xml格式
          "text": 将服务器端返回的内容转换成普通文本格式
          "html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。
        "script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式
          "json": 将服务器端返回的内容转换成相应的JavaScript对象
        "jsonp": JSONP 格式使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数

使用SpringMVC实现Ajax异步请求

实体类User.java

public class User {
    private int id;
    private String name;
    private String password;
   有参构造 无参构造  get/set方法  toString方法
}

web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<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">

	<!--DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

  	<!--编码过滤器-->
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

springmvc-servlet.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--自动扫描包-->
    <context:component-scan base-package="com.it.controller"/>
    <!--支持mvc注解-->
    <mvc:annotation-driven>
        <!--    json乱码解决-->
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="UTF-8"/>
            </bean>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                        <property name="failOnEmptyBeans" value="false"/>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    <!--spring不处理静态资源-->
    <mvc:default-servlet-handler/>
    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>


上面的springMVC环境基本搭建完成
我们来创建一个AjaxController类
AjaxController.java

package com.it.controller;

import com.it.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author shkstart
 * @create 2020-04-22 16:20
 */
@Controller
@RestController //返回字符串  不走视图解析器
public class AjaxController {

    @RequestMapping("/t1")
    public String test(){
        return "hello";
    }


    @RequestMapping("/a1")
    public void a1(String name, HttpServletResponse response) throws IOException {

        if("kasha".equals(name)){
            response.getWriter().write("true");
        }else{
            response.getWriter().write("false");
        }
    }
    //返回list集合
    @RequestMapping("/a2")
    public List<User> a2(){
        List<User> list = new ArrayList<User>();
        list.add(new User(1,"卡莎","123"));
        list.add(new User(2,"塞恩","456"));
        list.add(new User(3,"薇恩","789"));

        return list;
    }

    @RequestMapping("/a3")
    public String a3(String name,String pwd){
        String msg = "";
        if(name != null){
            if("admin".equals(name)){
                msg = "用户名正确";
            }else{
                msg = "用户名错误";
            }
        }
        if(pwd != null){
            if("123456".equals(pwd)){
                msg = "密码正确";
            }else{
                msg = "密码错误";
            }
        }
        return msg;
    }
}

上面AjaxController类中的方法对应的jsp页面↓

a1()方法对应的jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
    <script src="statics/js/jquery-3.5.0.js"></script>
    <script type="text/javascript">
      function a1(){
        $.get({
          url:"${pageContext.request.contextPath}/a1", <%--ajax请求到的地址--%>
          data:{"name":$("#username").val()},   <%--ajax请求携带的参数--%>
          success:function(data,status){   <%--请求成功后回调函数 data就是后端返回的参数也可以是json--%>
            console.log("data:" +data);
            console.log("status:" + status)
          }
        })
      }

    </script>
  </head>
  <body>
  <%--  失去焦点发起请求--%>
  用户名:<input type="text" id="username" οnblur="a1()">
  </body>
</html>

在这里插入图片描述
a2()方法对应的jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script src="statics/js/jquery-3.5.0.js"></script>
    <script type="text/javascript">
        $(function(){
            $("#btn_1").click(function(){
                $.ajax({
                    url:"${pageContext.request.contextPath}/a2",
                    success:function(data){
                        var html = "";
                        for (let i = 0; i < data.length; i++){
                            html += "<tr>" +
                                    "<td>" + data[i]?.id + "</td>" +
                                    "<td>" + data[i]?.name + "</td>" +
                                    "<td>" + data[i]?.password + "</td>" +
                                    "</tr>"
                        }
                        $("#content").html(html)
                    }
                })
            });
        })
    </script>
</head>
<body>
    <input type="button" value="加载数据" id="btn_1">
    <table>
        <thead>
            <tr>
                <th>用户ID</th>
                <th>用户名</th>
                <th>密码</th>
            </tr>
        </thead>
        <tbody id="content">
        </tbody>
    </table>
</body>
</html>

Ajax请求后,前端接收到后台返回的list集合 将集合循环遍历到页面

a3()对应的jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script src="statics/js/jquery-3.5.0.js"></script>
    <script type="text/javascript">
        function f1(){
            $.post({
                url:"${pageContext.request.contextPath}/a3",
                data:{"name":$("#name").val()},
                success:function(data){
                    if(data == "用户名正确"){
                        $("#userInfo").css("color","green");
                    }else{
                        $("#userInfo").css("color","red");
                    }
                    $("#userInfo").html(data);
                }
            })
        }

        function f2(){
            $.post({
                url: "${pageContext.request.contextPath}/a3",
                data:{"pwd":$("#pwd").val()},
                success:function(data){
                    if(data == "密码正确"){
                        $("#pwdInfo").css("color","green");
                    }else{
                        $("#pwdInfo").css("color","red");
                    }
                    $("#pwdInfo").html(data);
                }
            })
        }
    </script>
</head>
<body>

<p>
    用户名:<input type="text" id="name" οnblur="f1()">
    <span id="userInfo" style="color: red;width: 20px"></span>
</p>
<p>
    密码:<input type="password" id="pwd" οnblur="f2()">
    <span id="pwdInfo" style="color: red;width: 20px"></span>
</p>

</body>
</html>

Ajax 请求 判断用户名或密码是否正确 异步刷新

10.拦截器+文件上传

拦截器

模块:springMVC_07_interceptor

SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。

过滤器与拦截器的区别:拦截器是AOP思想的具体应用。
过滤器 filter

  • servlet规范中的一部分,任何java web工程都可以使用

  • 在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截

拦截器 interceptor

  • 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用

  • 拦截器只会拦截访问的控制器方法, 如果访问的是jsp/html/css/image/js是不会进行拦截的

自定义拦截器
  1. 创建模板springMVC_07_interceptor 支持web
  2. 配置web.xml 和 applicationContext.xml 或 springMVC-servlet.xml
  3. 编写一个类(拦截器) 实现HandlerInterceptor接口 重写方法
package com.it.MyInterceptor;

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

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

/**
 * @author shkstart
 * @create 2020-04-23 10:18
 */
//实现HandlerInterceptor 接口 就是一个拦截器了
public class MyInterceptor implements HandlerInterceptor {

    //请求处理之前执行
    // return true : 执行下一个拦截器,放行
    //return false : 不执行下一个拦截器
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("===========处理前=========");
        return false;
    }

    //请求处理之后执行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("=========处理后==========");
    }

    //dispatcherservlet处理后执行,做清理工作
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("==============清理===========");
    }
}

  1. 配置sringMVC-servlet.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="com.it.controller"/>
    <mvc:default-servlet-handler/>
    <mvc:annotation-driven/>

    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--配置SpringMVC拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--
                 /**    表示  包括路径及其子路径
                 /admin/*  表示 拦截admin/add这种,admin/add/user 就不会被拦截
                 /admin/** 表示 拦截admin/下所有
            -->
            <mvc:mapping path="/**"/>
            <!--bean 就是配置的拦截器-->
            <bean class="com.it.MyInterceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

</beans>
  1. 编写一个Controller类测试拦截器
package com.it.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author shkstart
 * @create 2020-04-23 10:15
 */

//测试拦截器
@RestController
public class MyController {

    @RequestMapping("/t1")
    public String test1(){
        System.out.println("OK");
        return "OK";
    }
}

  1. 启动Tomcat 访问t1 控制台输出
    在这里插入图片描述
利用拦截器验证用户是否登录
  1. 创建三个页面 WEB-INF/jsp/login.jsp , WEB-INF/jsp/main.jsp 还有默认index.jsp
    login.jsp登录页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
</head>
<body>

<form action="${pageContext.request.contextPath}/user/login" method="post">

    用户名:<input type="text" name="username"> <br/>
    密码: <input type="password" name="password">
    <input type="submit" value="登录">
</form>

</body>
</html>
  1. 创建LoginController类
package com.it.controller;

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

import javax.servlet.http.HttpSession;

/**
 * @author shkstart
 * @create 2020-04-23 11:15
 */
@Controller
@RequestMapping("user")
public class LoginController {

    //跳转到登录页面
    @RequestMapping("/goLogin")
    public String goLogin(){
        return "login";
    }

    //跳转到首页
    @RequestMapping("/goMain")
    public String main(){
        return "main";
    }

    //登录提交
    @RequestMapping("/login")
    public String login(HttpSession session,String username){
        System.out.println("接收前端=====");
        //向session记录登录信息
        session.setAttribute("user",username);
        return "main";
    }

    //注销操作
    @RequestMapping("/goOut")
    public String goOut(HttpSession session){
        session.removeAttribute("user");
        return "redirect:/index.jsp";
    }
}

  1. 编写main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>首页</title>
</head>
<body>

    <h1>首页</h1>
    <h4>用户:${sessionScope.get("user")}</h4>
    <h3><a href="${pageContext.request.contextPath}/user/goOut">注销</a></h3>
</body>
</html>
  1. 编写Index.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title></title>
  </head>
  <body>
  <h1>
    <a href="${pageContext.request.contextPath}/user/goLogin">登录</a>
  </h1>
  <h1>
    <a href="${pageContext.request.contextPath}/user/goMain">首页</a>
  </h1>

  </body>
</html>

  1. 编写LoginInterceptor拦截器
package com.it.MyInterceptor;

import org.springframework.web.servlet.HandlerInterceptor;

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

/**
 * @author shkstart
 * @create 2020-04-23 11:27
 */
public class LoginInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();

        //判断如果当前页面是login页面就放行
        if(request.getRequestURI().contains("login")){
            return true;
        }
        //如果已经登陆 Session中有数据 也放行
        if(session.getAttribute("user") != null){
            return true;
        }

        //用户没有登录 跳转到登录页面
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
        return false;
    }
}

  1. 将拦截器配置到spirngmvc-servlet.xml中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="com.it.controller"/>
    <mvc:default-servlet-handler/>
    <mvc:annotation-driven/>

    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--配置SpringMVC拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--
                 /**    表示  包括路径及其子路径
                 /admin/*  表示 拦截admin/add这种,admin/add/user 就不会被拦截
                 /admin/** 表示 拦截admin/下所有
            -->
            <mvc:mapping path="/**"/>
            <!--bean 就是配置的拦截器-->
            <bean class="com.it.MyInterceptor.MyInterceptor"/>
        </mvc:interceptor>

        <mvc:interceptor>
            <mvc:mapping path="/user/**"/>
            <bean class="com.it.MyInterceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

</beans>

文件上传和下载

模块:springMVC_08_file

  • 如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver
  • 前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器;

文件上传
1.导入依赖

        <!--文件上传-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>
        
        <!--servlet-api导入高版本的-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>

编写web.xml 配置dispatcher和filter编码过滤器

编写applicationContext.xml 配置MVC注解、过滤静态资源,自动扫描表、视图解析器、文件上传bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--自动扫描包-->
    <context:component-scan base-package="com.it.controller"/>
    <!--过滤静态资源-->
    <mvc:default-servlet-handler/>
    <!--MVC注解支持-->
    <mvc:annotation-driven/>

    <!--视图解析器-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--文件上传配置-->
    <bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
        <property name="defaultEncoding" value="utf-8"/>
        <!-- 上传文件大小上限,单位为字节(10485760=10M) -->
        <property name="maxUploadSize" value="10485760"/>
        <property name="maxInMemorySize" value="40960"/>
    </bean>
</beans>
CommonsMultipartFile 的 常用方法:

String getOriginalFilename():获取上传文件的原名

InputStream getInputStream():获取文件流

void transferTo(File dest):将上传文件保存到一个目录文件中

编写jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>文件上传和下载</title>
  </head>
  <body>
  <%--必须将 method设置为post请求  enctype设置为multipart/form-data --%>
  <form action="${pageContext.request.contextPath}/upload1" method="post" enctype="multipart/form-data">
    <input type="file" name="file"><br/>
    <input type="submit" value="upload">
  </form>
  </body>
</html>

编写Controller层
方式一:

package com.it.controller;

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.RestController;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;

/**
 * @author shkstart
 * @create 2020-04-24 10:05
 */
//@RestController 不走视图解析器
@Controller
public class MyController {

    @RequestMapping("/upload1")
    //@RequestParam("file") 将name=file的控件得到到文件封装成CommonsMultipartFile对象
    //批量上传 CommonsMultipartFile为数组即可
    public String fileUpload1(@RequestParam("file")CommonsMultipartFile file,
                              HttpServletRequest request) throws IOException {

        //获取文件名
        String uploadFileName = file.getOriginalFilename();

        //如果文件名为空,直接回到首页
        if("".equals(uploadFileName)){
            return "redirect:/index.jsp";
        }

        System.out.println("上传的文件名:" + uploadFileName);

        //上传路径设置
        String path = request.getServletContext().getRealPath("/upload");
        //如果路径不存在就创建一个
        File realPath = new File(path);
        if(!realPath.exists()){
            realPath.mkdir();
        }

        System.out.println("上传文件路径为:" + realPath);

        //文件输出流
        InputStream is = file.getInputStream();
        //文件输入流
        OutputStream os = new FileOutputStream(new File(realPath,uploadFileName));

        //读取写出
        int len = 0;
        byte[] buffer = new byte[1024];

        while((len = is.read(buffer)) != -1){
            os.write(buffer,0,len);
            os.flush();
        }
        os.close();
        is.close();
        return "redirect:/index.jsp";

    }
}

测试即可

方式二:采用file.Transto 来保存上传的文件

    @RequestMapping("/upload2")
    public String fileUpload2(@RequestParam("file") CommonsMultipartFile file,
                              HttpServletRequest request) throws IOException {

        //上传路径保存设置
        String path =  request.getServletContext().getRealPath("/upload");

        //获取到File对象
        File realPath = new File(path);

        //不存在就创建
        if(!realPath.exists()){
            realPath.mkdir();
        }

        //上传文件地址
        System.out.println("上传文件地址:" + realPath);

        //通过CommonsMultipartFile的方法直接写文件
        file.transferTo(new File(realPath + "/"
                + file.getOriginalFilename()));

        return "redirect:/index.jsp";
    }

文件下载
1.设置文件响应头 response
2.读写操作

    @RequestMapping("/download")
   public String fileDownload(HttpServletRequest request, HttpServletResponse response) throws IOException {

       //要下载的图片地址
       String path = request.getServletContext().getRealPath("/upload");
       //图片名
       String fileName = "这是要闹哪样.jpg";

       //1.设置response响应头
       response.reset();//设置页面不缓存,清空buffer
       response.setCharacterEncoding("utf-8");//字符编码
       response.setContentType("multipart/form-data");//二进制传输数据
       //设置响应头
       response.setHeader("Content-Disposition",
               "attachement;fileName="+ URLEncoder.encode(fileName,"utf-8"));

       File file = new File(path,fileName);
       //2.读取文件  输入流
       InputStream input = new FileInputStream(file);
       //3.读取文件 输出流
       OutputStream output = response.getOutputStream();

       byte[] buffer = new byte[1024];
       int index = 0;

       //4.执行写操作
       while((index = input.read(buffer)) != -1) {
           output.write(buffer,0,index);
           output.flush();
       }

       output.close();
       input.close();

       return null;
   }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值