SpringMVC

坚强是说给别人听的谎言 提交于 2020-02-27 03:03:30

SpringMVC

狂神说java SpringMVC视频B站地址

1. 什么是MVC

MVC:

model 模型(dao,service)执行业务,保存数据

view 视图(jsp) : 显示页面

Controller 控制器(Servlet) :获得前端数据,调用业务,页面跳转

这是一种规范

1.1 回顾servlet

jar包:

<!--        Jstl 表达式 依赖-->
     <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>jstl</artifactId>
         <version>1.2</version>
     </dependency>
     <!--        servlet  依赖-->
     <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>javax.servlet-api</artifactId>
         <version>3.1.0</version>
     </dependency>
     <!--        jsp 依赖-->
     <dependency>
         <groupId>javax.servlet.jsp</groupId>
         <artifactId>javax.servlet.jsp-api</artifactId>
         <version>2.3.1</version>
     </dependency>
     
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-webmvc</artifactId>
         <version>5.1.10.RELEASE</version>
     </dependency>

编写servlet类

		//1.从前端获得参数
        String method = req.getParameter("method");
        if (method.equals("add")){
            req.setAttribute("hello","执行add方法");
        }else if (method.equals("delete")){
            req.setAttribute("hello","执行了delete方法");
        }
        //2.交给业务层去做
        //3.视图跳转
        req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);

在web.xml中注册

    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.liang.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

启动tomcat 测试

http://localhost:8080/hello?method=delete

http://localhost:8080/hello?method=add

1.2 MVC框架要做哪些事

1.将url映射到java类或者java类的方法

2.封装用户提交的数据

3.处理请求——调用相关业务处理——封装响应数据

4.将响应的数据进行渲染 jsp/html等表示层数据

2. 初识springMVC

基于Java实现MVC的轻量级web框架

2.1 为什么要学springMVC

1.轻量级,简单好学

2.高效,基于请求响应的MVC框架

3.与Spring兼容性好,无缝结合

4.预定大于配置

5.功能强大

中心控制器:

​ spring的web框架围绕DispatcherServlet(调度servlet)设计

​ DispatchaerServlet的作用:将请求分发到不同的处理器

以请求为驱动,围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个实际的Servlet(他继承自HttpServlet基类)

在这里插入图片描述

2.2 spring MVC原理:(重点)

当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器再将结果返回给请求者

在这里插入图片描述

在这里插入图片描述

1.DispatcherServlet表示前端控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。

  • 我们假设请求的url为 : http://localhost:8080/SpringMVC/hello
  • 如上url拆分成三部分:
  • http://localhost:8080服务器域名
  • SpringMVC部署在服务器上的web站点
  • hello表示控制器
  • 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。

2.HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler

3.HandlerExecution表示具体的Handler其主要作用是根据url查找控制器,如上url被查找控制器为:hello。

4.HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。

5.HandlerAdapter表示处理器适配器,(寻找hangdler到底对应哪个controller)其按照特定的规则去执行Handler。

6.Handler让具体的Controller执行。

7.Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。

8.HandlerAdapter将视图逻辑名或模型(需要跳转的页面和传递的数据)传递给DispatcherServlet。

9.DispatcherServlet调用**视图解析器(ViewResolver)**来解析HandlerAdapter传递的逻辑视图名。

10.视图解析器将解析的逻辑视图名传给DispatcherServlet。

11.DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。

12.最终视图呈现给用户

2.3 HelloSpringMVC

配置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">
   <!--1.注册DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
        <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>

    <!--/ 匹配所有的请求;(不包括.jsp)-->
    <!--/* 匹配所有的请求;(包括.jsp)-->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

编写SpringMVC 的 配置文件!名称: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
       http://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>

添加 处理映射器

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

添加 处理器适配器

<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

添加 视图解析器

<!--视图解析器:DispatcherServlet给他的ModelAndView
	获取ModelAndView的数据
    解析ModelAndView的视图名字
    拼接视图名字 /WEB_INF/jsp/hello.jsp
    将数据渲染到视图上,呈现视图
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
    <!--前缀-->
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <!--后缀-->
    <property name="suffix" value=".jsp"/>
</bean>

编写我们要操作业务Controller ,要么实现Controller接口,要么增加注解;需要返回一个ModelAndView,装数据,封视图;

//注意:这里我们先导入Controller接口
public class HelloController implements Controller {

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //ModelAndView 模型和视图
        ModelAndView mv = new ModelAndView();

        //封装对象,放在ModelAndView中。Model
        mv.addObject("hello","HelloSpringMVC!");
        //封装要跳转的视图,放在ModelAndView中
        mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
        return mv;
    }
    
}

将自己的类交给SpringIOC容器,注册bean

<!--Handler-->
<bean id="/hello" class="com.liang.controller.HelloController"/>

写要跳转的jsp页面,显示ModelandView存放的数据,以及我们的正常页面

(坑)注意:

在这里插入图片描述

2.4 注解版 HelloSpringMVC

  1. 搭建环境

导入jar包

防止资源过滤

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>

​ 2.配置web.xml(web.xml必须用最新版本4.0)

<?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.注册servlet-->
    <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 的配置:

  • 让ioc注解生效
  • 静态资源过滤:HTML,JS,CSS
  • MVC注解驱动(处理器映射器,处理器适配器)
  • 配置视图解析器
<?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
        http://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">

    <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="com.liang.controller"/>
    <!-- 让Spring MVC不处理静态资源 -->
    <mvc:default-servlet-handler />
    <!--
    支持mvc注解驱动
        在spring中一般采用@RequestMapping注解来完成映射关系
        要想使@RequestMapping注解生效
        必须向上下文中注册DefaultAnnotationHandlerMapping
        和一个AnnotationMethodHandlerAdapter实例
        这两个实例分别在类级别和方法级别处理。
        而annotation-driven配置帮助我们自动完成上述两个实例的注入。
     -->
    <mvc:annotation-driven />

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

创建Controller

@org.springframework.stereotype.Controller
public class Controller {
//    访问地址: localhost:8080/hello
    @RequestMapping("/hello")
    public String hello(Model model){
        //向模型中添加数据 会在jsp页面渲染视图
        model.addAttribute("hello", "Hello!SpringMVCannotation!");
        // 视图解析器完成解析后: WEB_INF/jsp/hello.jsp
        return "hello";
    }
}
  • @org.springframework.stereotype.Controller 为了让spring IOC容器初始化能够自动扫描到(被注释的类,所有方法中如果返回String且有这个页面可以跳转,就会被视图解析器解析)

  • @RequestMapping是为了映射请求路径

  • 方法中的参数是为了把数据带到视图

  • 方法中的返回结果是视图名称 加上前后缀就是:WEB_INF/jsp/hello.jsp

最后创建视图层 ,启动tomcat测试

使用SpringMVC 必须配置三大件:处理器映射器(HandlerMapping),处理器适配器(HandlerAdapter),视图解析器(ViewResolver)

通常,我们只需要手动配置视图解析器,而处理器映射器处理器适配器只需要开启注解驱动即可,而省去了大段的xml配置

3. RestFul 风格

3.1 功能

资源:互联网所有事物都可以被抽象为资源

资源操作:使用POST(添加),DELETE(删除),PUT(修改),GET(查询),使用不同方法对资源进行操作

3.2 对比传统方式

传统方式操作资源:通过不同的参数来实现不同效果,方法只有post,get

RestFul操作资源:通过不同的请求方式来实现不同的效果(请求地址一样,但是可以实现不同功能)

@Controller
public class Restful {
    @RequestMapping("/test/{a}/{b}")
    public String test(@PathVariable int a,@PathVariable int b, Model model){
        //传统方式url:    http://localhost:8080/test?a=1&b=1
        //Restful方式url: http://localhost:8080/test/1/1

        int count = a + b;
        model.addAttribute("test","总计:"+count);

        return "test";
    }
}

注释: @PathVariable 用来在浏览器输入的值绑定该方法的参数

Restful还可以使用method属性指定请求类型(这里指定GET方法)

@RequestMapping(value = "/test/{a}/{b}",method = RequestMethod.GET)

等价于

@GetMapping("/test/{a}/{b}")

小结:

SpringMVC 的@RequestMapping注解能够处理HTTP请求的方法(GET, PUT, POST, DELETE 以及 PATCH)

@RequestMapping
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping

4. 结果跳转方式

真正页面地址:视图解析器前缀+viewname+视图解析器后缀

4.1 通过SpringMVC实现转发与重定向

无视图解析器时(需要写的路径非常麻烦):

//转发
return "forward:/WEB-INF/jsp/test.jsp";
//重定向
return "redirect:/WEB-INF/jsp/test.jsp";

有视图解析器时(不仅可以重定向路径还可以重定向一个请求):

//转发
return "test";
//重定向 一个路径
return "redirect:/index.jsp";
//重定向 一个请求 hello.do为另一个请求/
return "redirect:hello.do"; 

重定向不需要视图解析,因为本来就是重新请求一个新地方,所以注意路径问题

默认[forward:] 不用写

5. 数据处理

5.1 前端参数

参数相同

提交数据:http://localhost:8080/param1?name=chenliang

@Controller
public class Params {
    @RequestMapping("/param1")
    public String param01(String name, Model model){
        //获取前端参数
       System.out.println(name);
        //视图跳转
        return "param";
    }
}

后台显示:chenliang

参数不同

提交数据:http://localhost:8080/param1?username=chenliang

@Controller
public class Params {
    @RequestMapping("/param1")
    public String param01(@RequestParam("username") String name, Model model){
        //获取前端参数
        System.out.println(name);
        //视图跳转
        return "param";
    }
}

前端显示:{username=chenliang}

参数是对象

提交数据:http://localhost:8080/param1?username=chenliang&age=18&sex=boy

@Controller
public class Params {
    @RequestMapping("/param1")
    public String param01(User user, Model model){
        //获取前端参数
        System.out.println(user);
        //视图跳转
        return "param";
    }
}

后台显示:{username=chenliang,age=18,sex=boy}

如果参数是一个对象,传递的参数名要和对象的字段名一致,不然为null

注意:

最好都打注释@RequestParam,方便查看前端传递参数是什么

5.2 数据显示到前端

第一种:ModelAndView

public class ControllerTest1 implements Controller {
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //返回一个模型视图对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","ControllerTest1");
        mv.setViewName("test");
        return mv;
    }
}

第二种:ModelMap

@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, ModelMap model){
    //封装要显示到视图中的数据
    //相当于req.setAttribute("name",name);
    model.addAttribute("name",name);
    System.out.println(name);
    return "hello";
}

第三种:Model

@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Model model){
    //封装要显示到视图中的数据
    //相当于req.setAttribute("name",name);
    model.addAttribute("msg",name);
    System.out.println(name);
    return "test";
}

对比:

  • Model 只适合用于储存数据

  • ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;

  • ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。

5.3 乱码问题

SpringMVC为我们提供的过滤器

<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>

如有极端方式(自定义过滤器):

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;

/**
 * 解决get和post请求 全部乱码的过滤器
 */
public class GenericEncodingFilter implements Filter {

    @Override
    public void destroy() {
    }

    @Override
    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);
    }

    @Override
    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;
    }
}

6. JSON

6.1 什么是JSON

JSON(JavaScript Object Notation, JS 对象标记)是一种轻量级的数据交换格式,使用广泛

采用完全独立于编程语言的文本格式来存储,表示数据

简单,结构清晰,易于人阅读编写,机器解析生成,提高网络传输效率

6.2 JSON语法格式

  • 对象表示为键值对,数据用逗号分隔
  • 花括号保存对象
  • 方括号保存数组

6.3 使用Jackson

导入Jar包

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

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">

    <!--1.注册servlet-->
    <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>

    <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
        http://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">

    <!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 -->
    <context:component-scan base-package="com.kuang.controller"/>

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

</beans>

乱码解决

第一种(固定不变):

<mvc:annotation-driven>
    <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>

第二种:

//produces:指定响应体返回类型和编码
@RequestMapping(value = "/json1",produces = "application/json;charset=utf-8")

编写实体类User

(略)

编写Controller

//@RestController 在类上使用后,此类所有方法返回结果为json字符串 不用每个方法都加注释@ResponseBody(将str转成json格式返回)
@Controller
public class UserController {

    @RequestMapping("/json1")
    @ResponseBody
    public String json1() throws JsonProcessingException {
//创建一个jackson的对象映射器,用来解析数据
    ObjectMapper mapper = new ObjectMapper();
    //创建一个对象
    User user1 = new User("张三", 3, "男");
    User user2 = new User("李四", 3, "男");
    
    List<User> list = new ArrayList<User>();
    list.add(user1);
    list.add(user2);
    //将我们的对象解析成为json格式
    String str = mapper.writeValueAsString(list);
    return str;
    }
}

结果:

[{"name": "张三""age": "3""sex": "男"},{"name": "李四""age": "3""sex": "男"}]

输出时间对象

  • 默认日期格式会变成一个数字,是1970年1月1日到当前日期的毫秒数!
  • Jackson 默认是会把时间转成timestamps(时间戳)形式
@RequestMapping("/json3")
public String json3() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    //创建时间一个对象,java.util.Date
    Date date = new Date();
    
    //自定义日期格式
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
    //将我们的对象解析成为json格式
    String str = mapper.writeValueAsString(sdf.format(date));
    return str;
}

6.4 使用FastJson

导入依赖:

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

FastJson三个主要的类:

  • 【JSONObject 代表 json 对象 】
    • JSONObject实现了Map接口, 猜想 JSONObject底层操作是由Map实现的。
    • JSONObject对应json对象,通过各种形式的get()方法可以获取json对象中的数据,也可利用诸如size(),isEmpty()等方法获取"键:值"对的个数和判断是否为空。其本质是通过实现Map接口并调用接口中的方法完成的。
  • 【JSONArray 代表 json 对象数组】
    • 内部是有List接口中的方法来完成操作的。
  • 【JSON 代表 JSONObject和JSONArray的转化】
    • JSON类源码分析与使用
    • 仔细观察这些方法,主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化。
  //创建一个对象
        User user1 = new User("秦疆1号", 3, "男");
        User user2 = new User("秦疆2号", 3, "男");
        User user3 = new User("秦疆3号", 3, "男");
        User user4 = new User("秦疆4号", 3, "男");
        List<User> list = new ArrayList<User>();
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);

        System.out.println("*******Java对象 转 JSON字符串*******");
        String str1 = JSON.toJSONString(list);
        System.out.println("JSON.toJSONString(list)==>"+str1);
        String str2 = JSON.toJSONString(user1);
        System.out.println("JSON.toJSONString(user1)==>"+str2);

        System.out.println("\n****** JSON字符串 转 Java对象*******");
        User jp_user1=JSON.parseObject(str2,User.class);
        System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);

        System.out.println("\n****** Java对象 转 JSON对象 ******");
        JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
        System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name"));

        System.out.println("\n****** JSON对象 转 Java对象 ******");
        User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
        System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>"+to_java_user);

后台显示:

Java对象 转 JSON字符串
JSON.toJSONString(list)>[{“age”:3,“name”:“秦疆1号”,“sex”:“男”},{“age”:3,“name”:“秦疆2号”,“sex”:“男”},{“age”:3,“name”:“秦疆3号”,“sex”:“男”},{“age”:3,“name”:“秦疆4号”,“sex”:“男”}]
JSON.toJSONString(user1)
>{“age”:3,“name”:“秦疆1号”,“sex”:“男”}

****** JSON字符串 转 Java对象*******
JSON.parseObject(str2,User.class)==>User{age=3, name=‘秦疆1号’, sex=‘男’}

****** Java对象 转 JSON对象 ******
(JSONObject) JSON.toJSON(user2)==>秦疆2号

****** JSON对象 转 Java对象 ******
JSON.toJavaObject(jsonObject1, User.class)==>User{age=3, name=‘秦疆2号’, sex=‘男’}

7. 整合SSM

在这里插入图片描述

7.1 数据库环境

CREATE DATABASE `ssmbuild`;

USE `ssmbuild`;

DROP TABLE IF EXISTS `books`;

CREATE TABLE `books` (
  `bookID` INT(10) NOT NULL AUTO_INCREMENT COMMENT '书id',
  `bookName` VARCHAR(100) NOT NULL COMMENT '书名',
  `bookCounts` INT(11) NOT NULL COMMENT '数量',
  `detail` VARCHAR(200) NOT NULL COMMENT '描述',
  KEY `bookID` (`bookID`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT  INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)VALUES 
(1,'Java',1,'从入门到放弃'),
(2,'MySQL',10,'从删库到跑路'),
(3,'Linux',5,'从进门到进牢');

7.2 环境搭建

依赖:

  1. <dependencies>
        <!--Junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!-- 数据库连接池 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
    
        <!--Servlet - JSP -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    
        <!--Mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.2</version>
        </dependency>
    
        <!--Spring-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
    </dependencies>
    

静态资源过滤

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>

建立基本结构和配置框架

  • com.liang.pojo

  • com.liang.dao

  • com.liang.service

  • com.liang.controller

  • mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    
    </configuration>
    
  • applicationContext.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
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    </beans>
    

7.3 Mybatis层

1. 数据库配置文件 database.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456

2. idea关联数据库

3.实体类

public class Books {
    private int bookID;
    private String bookName;
    private  int bookCounts;
    private String detail;
    //set,get,构造,tostring
}

4. Mybatis核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

<!--    配置数据源,交给spring去做     -->
    <typeAliases>
        <package name="com.liang.pojo"/>
    </typeAliases>

<!--    注册mapper-->
    <mappers>
        <mapper class="com.liang.dao.BookMapper"/>
    </mappers>
</configuration>

5. Dao层BookMapper接口

public interface BookMapper {
    //增加一本书
    int addBooks(Books books);

    //删除一本书
    int deleteBookByid(@Param("bookID") int id);

    //更新一本书
    int updateBook(Books books);

    //查询一本书
    Books queryBook(@Param("bookID") int id);

    //查询全部的书
    List<Books> queryAllBook();
}

6. BookMapper接口对应的Mapper.xml文件

此文件的头文件只需要将mybatis核心配置文件做出一下调整即可

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.liang.dao.BookMapper">

    <insert id="addBooks" parameterType="Books">
        insert into ssmbuild.books (bookName, bookCounts, detail)
        values (#{bookName},#{bookCounts},#{detail});
    </insert>

    <delete id="deleteBookByid" parameterType="int">
        delete from ssmbuild.books where ssmbuild.books.bookID = #{bookID}
    </delete>

    <update id="updateBook" parameterType="Books">
        update ssmbuild.books
        set bookName =#{bookName} ,bookCounts = #{bookCounts},detail =#{detail}
        where bookID=#{bookID};
    </update>

    <select id="queryBook"  resultType="Books">
        select * from ssmbuild.books where bookID=#{bookID};
    </select>
    
    <select id="queryAllBook" resultType="Books">
        select * from ssmbuild.books;
    </select>
</mapper>

注意:每次写完Mapper.xml文件就应该去mybatis核心配置文件进行注册

7. Service层接口

public interface BookService {
    //增加一本书
    int addBooks(Books books);

    //删除一本书
    int deleteBookByid(int id);

    //更新一本书
    int updateBook(Books books);

    //查询一本书
    Books queryBook(int id);

    //查询全部的书
    List<Books> queryAllBook();
}

8. Service层 接口实现类

public class BookServiceImpl implements BookService {
    //因为要调用dao 所以引入
    private BookMapper bookMapper;
    public void setBookMapper(BookMapper bookMapper) {
        this.bookMapper = bookMapper;
    }

    public int addBooks(Books books) {
        return bookMapper.addBooks(books);
    }

    public int deleteBookByid(int id) {
        return bookMapper.deleteBookByid(id);
    }

    public int updateBook(Books books) {
        return bookMapper.updateBook(books);
    }

    public Books queryBook(int id) {
        return bookMapper.queryBook(id);
    }

    public List<Books> queryAllBook() {
        return bookMapper.queryAllBook();
    }
}

7.4 Spring层

1.spring整合mybatis配置文件 spring-dao.xml

此文件的头文件只需将application.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

<!--    1.读取资源文件 -->
        <context:property-placeholder location="classpath:detebase.properties"/>
<!--    2.数据库连接池-->
        <bean id="database" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${jdbc.driver}"/>
            <property name="jdbcUrl" value="${jdbc.url}"/>
            <property name="user" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
            <!-- c3p0连接池的私有属性 -->
            <property name="maxPoolSize" value="30"/>
            <property name="minPoolSize" value="10"/>
            <!-- 关闭连接后不自动commit -->
            <property name="autoCommitOnClose" value="false"/>
            <!-- 获取连接超时时间 -->
            <property name="checkoutTimeout" value="10000"/>
            <!-- 当获取连接失败重试次数 -->
            <property name="acquireRetryAttempts" value="2"/>
        </bean>
<!--    3.配置sqlSessionFactory对象-->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--     注入数据库连接池-->
            <property name="dataSource" ref="database"/>
        <!--     配置MyBaties全局配置文件:mybatis-config.xml-->
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
        </bean>
<!--4.配置扫描Dao接口包,动态实现Dao接口注入到spring容器中-->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--     注入sqlSessionFactory      -->
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!--     给出需要扫描的dao接口包   后面  -->
            <property name="basePackage" value="com.liang.dao"/>
        </bean>

</beans>

2. spring整合service层 spring-service.xml

此文件头文件如spring-dao.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!--1. 扫描service相关的bean -->
    <context:component-scan base-package="com.liang.service"/>

    <!--2.BookServiceImpl注入到IOC容器中-->
    <bean id="BookServiceImpl" class="com.liang.service.BookServiceImpl">
        <!--这里的bokkMapper 是spring-dao.xml中4.配置扫描dao接口包那里 扫描过来的       -->
        <property name="bookMapper" ref="bookMapper"/>
    </bean>

    <!--3.配置事务管理器-->
    <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
        <!--注入数据库连接池-->
        <property name="dataSource" ref="database"/>
    </bean>
    <!--4.aop事务  -->
</beans>

7.5 SpringMVC层

1. 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>DispatcherServlet</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>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
<!--    Filter-->
    <filter>
        <filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
<!--Session过期时间-->
    <session-config>
        <session-timeout>15</session-timeout>
    </session-config>
</web-app>

2. spring-mvc.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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解驱动-->
<mvc:annotation-driven/>

<!-- 过滤静态资源-->
<mvc:default-servlet-handler/>
<!--视图解析-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>
<!--    扫描包-->
<context:component-scan base-package="com.liang.controller"/>
</beans>

3. spring整合配置文件 application.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
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <import resource="spring-dao.xml"/>
    <import resource="spring-service.xml"/>
    <import resource="spring-mvc.xml"/>
</beans>

7.6 增删改查

@Controller
@RequestMapping("/book")
public class BookController {
    //要调用业务层就要先引入
    @Autowired
    @Qualifier("BookServiceImpl")
    private BookService bookService;

    //查询所有书
    @RequestMapping("/allbook")
    public String query(Model model){
        List<Books> list = bookService.queryAllBook();
        model.addAttribute("list",list);
        return "allbook";
    }

    //点击新增
    @RequestMapping("/toAddBook")
    public String toAddBook(){

        return "addBook";//进入新增书籍页面
    }
    @RequestMapping("/addBook")
    public String add(Books books){
        System.out.println(books);
        bookService.addBooks(books);//数据库添加这个books
        return "redirect:/book/allbook";
    }

    //点击更改
    @RequestMapping("/toUpdateBook")
    public String toUpdateBook(int id,Model model){
        Books books = bookService.queryBook(id);
        System.out.println(books);
        model.addAttribute("book",books);//给前端传一个默认值(也就是要修改的那个他自己)
        return "updateBook";//进入更改页面
    }
    @RequestMapping("/updateBook")
    public String updateBook(Books book,Model model){
        bookService.updateBook(book);
        int bookID = book.getBookID();
        Books books = bookService.queryBook(bookID);
        model.addAttribute("book",books);
        System.out.println(books);
        return "redirect:/book/allbook";
    }

    //点击删除
    @RequestMapping("/del/{id}")
    public String del(@PathVariable int id){
         bookService.deleteBookByid(id);
         return "redirect:/book/allbook";
    }
}

8. 拦截器

SpringMVC的处理器拦截器:HandlerInterceptor

类似Servlet开发中的过滤器

过滤器

  • servlet的一部分,任何java web工程都可以用
  • 配置/*后,可以对所有要访问的资源进行拦截

拦截器

  • 是SpringMVC框架自有的,使用SpringMVC框架工程才可以用
  • 拦截器只会拦截访问的控制器方法,若访问的是jsp/image/html/css/js

等是不会进行拦截的

  • 拦截器是AOP思想(面向切面编程)

拦截器必须实现HanlerInterceptor接口

public class MyInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //返回 true 为通过 ,false为拦截(不通过)
        System.out.println("执行前============================");
        return true;
    }

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

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("清理");
    }
}

在配置文件中配置拦截器

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

编写控制器

@Controller
public class Interceptor {
    @RequestMapping("interceptor")
    public String test(){
        System.out.println("控制器的方法执行了!");
        return "interceptor";
    }
}

后台显示:

执行前============================
控制器的方法执行了!
执行后==============================
清理

8.1 登录判断验证

控制器

@Controller
@RequestMapping("user")
public class LoginController {

    //点击登录
    @RequestMapping("jumplogin")
    public String jumplogin(){
        return "login";
    }

    @RequestMapping("login")
    public String login(String username, String pwd, HttpSession session){
        System.out.println("接受前端信息:"+username+":"+pwd);
        session.setAttribute("UserName",username);//为了方便拦截器判断用户是否登录
        return "succussful";
    }

    @RequestMapping("logout")
    public String logout(HttpSession session){
        session.invalidate();//点击注销  注销session
        return "redirect:/index.jsp";
    }

    @RequestMapping("jumpSuccess")
    public String jumpSuccess(){
        return "succussful";
    }
}

拦截器

public class MyInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (request.getRequestURI().contains("jumplogin")){
            return true;//点击登录 不拦截
        } else if (request.getRequestURI().contains("login")){
            return true;//点击提交用户名密码时 不拦截
        }else if (request.getSession().getAttribute("UserName")!=null){
            return true;//如果有用户信息则不拦截
        }else {
            response.sendRedirect("/error.jsp");
            return  false;
        }

    }
}

配置拦截器

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

9. 文件上传与下载

9.1 文件上传

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

  • 后台:SpringMVC上下文中默认没有装配MultipartResolver,为了实现文件上传,需要在上下文中配置MultipartResolver

导入jar包:

<!--文件上传-->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
<dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
</dependency>

配置bean:multipartResolver(这个bena的id必须为:multipartResolver)

<!--文件上传配置-->
<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>

CommonsMultipartFile 的 常用方法:

  • String getOriginalFilename():获取上传文件的原名
  • InputStream getInputStream():获取文件流
  • void transferTo(File dest):将上传文件保存到一个目录文件中

控制器(第一种方式):

@Controller
public class FileController {
    //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
    //批量上传CommonsMultipartFile则为数组即可
    @RequestMapping("/upload")
    public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
        //获取文件名 : file.getOriginalFilename();
        String uploadFilename = file.getOriginalFilename();

        //如果文件名为空,直接回首页
        if ("".equals(uploadFilename)){
            return "redirect:/index.jsp";
        }
        System.out.println("上传文件名:"+uploadFilename);

        //上传路径保存设置  先获得servlet容器(tomcat容器) 再获取 在容器中的实际发布运行的根路径
        String path = request.getSession().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)

*
 * 采用file.Transto 来保存上传的文件
 */
@RequestMapping("/upload2")
public String  fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {

    //上传路径保存设置
    String path = request.getServletContext().getRealPath("/upload");
    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";
}

9.2 文件下载

@Controller
public class FileController {

    //上传文件
    //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
    //批量上传CommonsMultipartFile则为数组即可
    @RequestMapping("/upload")
    public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
        //获取文件名 : file.getOriginalFilename();
        String uploadFilename = file.getOriginalFilename();

        //如果文件名为空,直接回首页
        if ("".equals(uploadFilename)){
            return "redirect:/index.jsp";
        }
        System.out.println("上传文件名:"+uploadFilename);

        //上传路径保存设置  先获得servlet容器(tomcat容器) 再获取 在容器中的实际发布运行的根路径
        String path = request.getSession().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";
    }

    //下载文件
    @RequestMapping("/download")
    public String download(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //要下载的图片地址 只需要变这里的代码 地址与名字
        String path = request.getSession().getServletContext().getRealPath("/upload");
        String  fileName = "QQ截图20200222224904.png";

        //1.设置响应头
        response.reset();//不缓存 清空buffer
        response.setCharacterEncoding("UTF-8");
        response.setContentType("multipart/form-data");//二进制传输数据

        //设置响应头
        response.setHeader("Content-Disposition",
                "attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));

        File file = new File(path, fileName);

        //2.读取文件--输入流
        InputStream input = new FileInputStream(file);

        //3.写出文件--输出流
        OutputStream out = response.getOutputStream();

        byte[] buff = new byte[1024];
        int index=0;
        //4、执行 写出操作
        while((index= input.read(buff))!= -1){
            out.write(buff, 0, index);
            out.flush();
        }
        out.close();
        input.close();
        return null;
    }

}
oadFilename);

        //上传路径保存设置  先获得servlet容器(tomcat容器) 再获取 在容器中的实际发布运行的根路径
        String path = request.getSession().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";
    }

    //下载文件
    @RequestMapping("/download")
    public String download(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //要下载的图片地址 只需要变这里的代码 地址与名字
        String path = request.getSession().getServletContext().getRealPath("/upload");
        String  fileName = "QQ截图20200222224904.png";

        //1.设置响应头
        response.reset();//不缓存 清空buffer
        response.setCharacterEncoding("UTF-8");
        response.setContentType("multipart/form-data");//二进制传输数据

        //设置响应头
        response.setHeader("Content-Disposition",
                "attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));

        File file = new File(path, fileName);

        //2.读取文件--输入流
        InputStream input = new FileInputStream(file);

        //3.写出文件--输出流
        OutputStream out = response.getOutputStream();

        byte[] buff = new byte[1024];
        int index=0;
        //4、执行 写出操作
        while((index= input.read(buff))!= -1){
            out.write(buff, 0, index);
            out.flush();
        }
        out.close();
        input.close();
        return null;
    }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!