Spring MVC框架详解

目录

SpringMVC三层架构

SpringMVC入门

2.1、环境搭建

2.1.1、引入依赖

2.1.2、编写配置文件

2.1.3、配置web.xml

2.1.4、编写控制器

2.2、注解详解

2.2.1、@Controller

2.2.2、@RequestMapping

2.3、SpringMVC的跳转方式

2.3.1、Controller ——>前台页面

2.3.1.1、forward

2.3.1.2、redirect

2.3.1Controller ——>Controller

2.3.1.1、forward

2.3.1.2、redirect

2.4、SpringMVC的参数接收

2.4.1、Servlet接收参数的方式

2.4.2、SpringMVC的参数接收

2.4.2.1、基本数据类型

2.4.2.2、对象类型

2.4.2.3、数组类型

2.4.2.4、集合类型

2.5、SpringMVC接收参数中文乱码问题

2.5.1、GET请求

2.5.2、POST请求

2.5.2.1、自定义过滤器解决POST乱码请求

2.5.2.2、使用CharacterEncodingFilter解决POST乱码请求

2.6、SpringMVC中数据传递机制

2.6.1、什么事数据传递机制

2.6.2、Servlet的数据传递机制

请求转发和重定向

3.1请求转发和重定向的区别

3.2请求转发

3.3重定向

3.4请求路径

文件上传与下载

4.1文件上传

4.2编写表单

4.3修改web.xml

4.4配置上传解析器

4.5配置上传控制器

4.6文件下载

4.7开发控制器


Spring MVC(Model-View-Controller)是一个基于Java的Web框架,它是Spring框架的一部分,用于开发Web应用程序。Spring MVC提供了一种灵活的模型-视图-控制器(MVC)体系结构,用于开发Web应用程序。它使用基于注释的配置和声明性模板来减少开发时间,并以模块化的方式提供了许多功能,包括数据绑定、数据验证、视图解析和异常处理等。

SpringMVC三层架构

java SpringMVC的工程结构一般来说分为三层,自下而上是Modle层(模型,数据访问层)、Cotroller层(控制,逻辑控制层)、View层(视图,页面显示层),其中Modle层分为两层:dao层、service层,MVC架构分层的主要作用是解耦。采用分层架构的好处,普遍接受的是系统分层有利于系统的维护,系统的扩展。就是增强系统的可维护性和可扩展性。

对于Spring这样的框架,(View\Web)表示层调用控制层(Controller),控制层调用业务层(Service),业务层调用数据访问层(Dao)

service层:业务层,用来实现业务逻辑。能调用dao层或者service层,返回数据对象DO或者业务对象BO,BO通常由DO转化、整合而来,可以包含多个DO的属性,也可以是只包含一个DO的部分属性。通常为了简便,如果无需转化,service也可以直接返回DO。外部调用(HTTP、RPC)方法也在这一层,对于外部调用来说,service一般会将外部调用返回的DTO转化为BO。是专注业务逻辑,对于其中需要的数据库操作,都通过Dao去实现。主要去负责一些业务处理,比如取得连接、关闭数据库连接、事务回滚,一些复杂的逻辑业务处理就放到service层。

DAO层:负责访问数据库进行数据的操作,取得结果集,之后将结果集中的数据取出封装到VO类对象之后返回给service层。数据层,直接进行数据库的读写操作,返回数据对象DO,DO与数据库表一一对应。Dao的作用是封装对数据库的访问:增删改查,不涉及业务逻辑,只是达到按某个条件获得指定数据的要求。

Cotroller层:叫做控制层,主要的功能是处理用户发送的请求。主要处理外部请求。调用service层,将service层返回的BO/DO转化为DTO/VO并封装成统一返回对象返回给调用方。如果返回数据用于前端模版渲染则返回VO,否则一般返回DTO。不论是DTO还是VO,一般都会对BO/DO中的数据进行一些转化和整合。

View层:叫做显示层,主要是负责现实数据。

SpringMVC入门

2.1、环境搭建

2.1.1、引入依赖

依赖就忽略了

2.1.2、编写配置文件

<?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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

<!--  1. 开启注解扫描-->
  <context:component-scan base-package="com.lin.controller"/>
<!--  2. 配置处理器映射器-->
<!--  <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />-->
<!--  3. 开启处理器适配器-->
<!--  <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />-->
<!--  上面两段配置被下面的一句话所替代(封装)-->
  <mvc:annotation-driven />
  <!--  4. 开启视图解析器-->
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
  </bean>
</beans>

2.1.3、配置web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

<!--  配置springmvc的核心servlet-->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
<!--      告诉springmvc配置文件的位置-->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
<!--    拦截所有请求-->
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

2.1.4、编写控制器

package com.lin.controller;

import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author XiaoLin
 * @date 2021/2/17 17:09
 */
@Controller
public class HellowController {

  /**
      * @Description:第一个springmvc测试类
      * @author XiaoLin
      * @date 2021/2/17
      * @Param: [username, password]
      * @return java.lang.String
      */
     /*
      RequestMapping的修饰范围:可以用在类上和方法上,他的作用如下:
      1. 用在方法上可以给当前方法加入指定的请求路径
      2. 用在类上可以给类中的所有方法都加入一个统一的请求路径,在这个方法访问之前都必须加上
      */
  @RequestMapping("/hello")
  public String hello(String username,String password){
    System.out.println("hello");
    return "index";
  }
}

2.2、注解详解

2.2.1、@Controller

该注解用来类上标识这是一个控制器组件类并创建这个类实例,告诉spring我是一个控制器。

2.2.2、@RequestMapping

这个注解可以作用在方法上或者是类上,用来指定请求路径。

2.3、SpringMVC的跳转方式

传统的Servlet开发跳转方式有两种:

  1. forward:forward跳转,是在服务器内部跳转,所以是一次请求,地址栏不变。跳转时可以携带数据进行传递(使用request作用域进行传递)。
  2. redirect:redirect跳转是客户端跳转,所以是多次请求,地址栏会改变,跳转时不可以携带数据传递。

2.3.1、Controller ——>前台页面

2.3.1.1、forward

通过测试我们可以发现,SpringMVC默认的就是使用请求转发的方式来进行跳转到前台页面的;

@Controller
@RequestMapping("forwoartAndRedirect")
public class TestForwoartAndRedirect {

  @RequestMapping("test")
  public String test(){
    System.out.println("test");
    return"index";
  }
}

2.3.1.2、redirect

如果我们想使用重定向的方式来进行跳转的话,需要使用SpringMVC提供给我们的关键字——redirect:来完成。

语法:return "redirect:/视图全路径名";

**注意:**在redirect:后接页面的不是逻辑名,而是全路径名。因为redirect跳转不会经过视图解析器。

2.3.1Controller ——>Controller

2.3.1.1、forward

如果我们想使用请求转发的方式跳转到相同(不同)Controller的不同方法的时候,我们也需要使用SpringMVC提供的关键字:forward:。

语法:return:"forward: /需要跳转的类上的@RequestMapping的值/需要跳转的方法上的@RequestMapping的值;"

2.3.1.2、redirect

如果我们想使用重定向的方式跳转到相同(不同)Controller的不同方法的时候,我们也需要使用SpringMVC提供的关键字:redirect:。

语法:return:"redirect: /需要跳转的类上的@RequestMapping的值/需要跳转的方法上的@RequestMapping的值;"

2.4、SpringMVC的参数接收

2.4.1、Servlet接收参数的方式

在传统的Servlet开发,我们一般都是用这种方式来进行接收请求参数的。

// 接收名字为name的参数
request.getParameter(name)

他有几个需要注意的点:

  1. 参数要求是表单域的name属性。
  2. getParameter方法用于获取单个值, 返回类型是String。
  3. getParameterValues方法用于获取一组数据, 返回结果是String[]。
  4. 冗余代码较多, 使用麻烦, 类型需要自己转换。

2.4.2、SpringMVC的参数接收

SpringMVC使用的是控制器中方法形参列表来接收客户端的请求参数,他可以进行自动类型转换,要求传递参数的key要与对应方法的形参变量名一致才可以完成自动赋值。他的优势很明显:

  1. 简化参数接收形式(不需要调用任何方法, 需要什么参数, 就在控制器方法中提供什么参数)。
  2. 参数类型不需要自己转换了。日期时间(默认为yyyy/MM/dd)得注意,需要使用@DateTimeFormat注解声明日期转换时遵循的格式, 否则抛出400异常。

2.4.2.1、基本数据类型

要求传递参数的key要与对应方法的形参变量名一致才可以完成自动赋值。

2.4.2.2、对象类型

如果我们需要接收对象类型的话,直接将需要接收的对象作为控制器的方法参数声明即可。SpringMVC会自动封装对象,若传递参数key与对象中属性名一致,就会自动封装成对象。

2.4.2.3、数组类型

如果我们需要接收数组类型的时候,只需将要接收的数组类型直接声明为方法的形式参数即可。

2.4.2.4、集合类型

SpringMVC不能直接通过形式参数列表的方式接收集合类型的参数,如果需要接收集合类型的参数必须将集合放入一个对象中,并且提供get/set方法,才可以。推荐放入VO对象中进行封装,进而使用对象类型来进行接收。

2.5、SpringMVC接收参数中文乱码问题

2.5.1、GET请求

GET请求方式出现乱码需要分Tomcat版本进行讨论:

  1. Tomcat8.x版本之前:默认使用server.xml中的URIEncoding="ISO-8859-1"编码,而不是"UTF-8"编码,进而会出现中文乱码。
  2. Tomcat8.x版本之后:默认使用server.xml中的URIEncoding="UTF-8",所以不会出现中文乱码问题。

2.5.2、POST请求

SpringMVC中默认没有对POST请求进行任何编码处理,所以无论什么版本直接接收POST请求都会出现中文乱码。

2.5.2.1、自定义过滤器解决POST乱码请求

在Servlet阶段,我们学过过滤器,我们可以自定义过滤器来进行过滤编码。

package com.filter;

import javax.servlet.*;
import java.io.IOException;

//自定义编码filter
public class CharacterEncodingFilter  implements Filter {

    private String encoding;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.encoding = filterConfig.getInitParameter("encoding");
        System.out.println(encoding);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}
<!--配置post请求方式中文乱码的Filter-->
  <filter>
    <filter-name>charset</filter-name>
    <filter-class>com.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>charset</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

2.5.2.2、使用CharacterEncodingFilter解决POST乱码请求

<!--配置post请求方式中文乱码的Filter-->
  <filter>
    <filter-name>charset</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>charset</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
package com.filter;

import javax.servlet.*;
import java.io.IOException;

//自定义编码filter
public class CharacterEncodingFilter  implements Filter {

    private String encoding;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.encoding = filterConfig.getInitParameter("encoding");
        System.out.println(encoding);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}

2.6、SpringMVC中数据传递机制

2.6.1、什么事数据传递机制

数据传递机制主要包含三个问题:

  1. 数据如何存储?
  2. 如何在页面中获取数据?
  3. 在页面中获取的数据该如何展示?

2.6.2、Servlet的数据传递机制

在以前的Servlet开发中,我们一般是将数据放入作用域(request、session、application),如果数据是单个的直接用EL表达式在前端进行展示,如果是集合或者数组,可以用EL表达式➕JSTL标签进行遍历后在前端进行展示。

请求转发和重定向

3.1请求转发和重定向的区别

几次请求地址栏WEB-INF中资源共享请求数据有无表单重复提交
请求转发1次不改变可以访问可以共享
重定向多次改变不可访问不可共享

3.2请求转发

加上forward 关键字,表示请求转发,相当于
request.getRequestDispatcher().forward(request,response),转发后浏览器地址栏不变,共享之前请求中的数据。加了关键字后,配置的视图解析器就不起作用了。如果返回视图必须写全路径

package cn.linstudy.web.controller;
@Controller
public class ResponseController {

	@RequestMapping("/TestForward")
	public String forward() {
		return "forward:/WEB-INF/views/welcome.jsp";
	}
}

3.3重定向

加上 redirect 关键字,表示重定向,相当于 response.sendRedirect(),重定向后浏览器地址栏变为重定向后的地址,不共享之前请求的数据。

package cn.linstudy.web.controller;
@Controller
public class ResponseController {
	// localhost/r
	@RequestMapping("/TestRedirect")
	public String redirect() {
		return "redirect:/static/demo.html";
	}
}

3.4请求路径

在请求转发和重定向的时候,我们一般有两种方式来写请求路径:

  1. 加/:使用是绝对路径(推荐使用),从项目根路径找。(/response/test6 ---> "redirect:/hello.html" ---> localhost:/hello.html)
  2. 不加/:使用是相对路径,相对于上一次访问上下文路径的上一级找。(/response/test6 ---> "redirect:hello.html" ---> localhost:/response/hello.html)

 

文件上传与下载

4.1文件上传

回顾之前使用 Servlet3.0 来解决文件上传的问题,编写上传表单(POST、multipart/form-data),还在处理方法 doPost 中编写解析上传文件的代码。但是在SpringMVC是可以帮我们简化文件上传的步骤和代码。

4.2编写表单

注意请求数据类型必须是:multipart/form-data,且请求方式是POST。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
	<form action="/upload" method="POST" enctype="multipart/form-data">
		文件:<input type="file" name="pic"><br>
		<input type="submit" value="提交"/>
	</form>
</body>
</html>

4.3修改web.xml

我们可以在web.xml中指定上传文件的大小。

<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:mvc.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
	<multipart-config>
		<max-file-size>52428800</max-file-size>
		<max-request-size>52428800</max-request-size>
	</multipart-config>
</servlet>
<servlet-mapping>
	<servlet-name>dispatcherServlet</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>

4.4配置上传解析器

在mvc.xml中配置上传解析器,使用springmvc中multipartfile接收客户端上传的文件必须配置文件上传解析器且解析的id必须为multipartResolver

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  <!--控制文件上传大小单位字节 默认没有大小限制 这里是2-->
  <property name="maxUploadSize" value="2097152"/>
</bean>

4.5配置上传控制器

package cn.linstudy.controller;
	@Controller
	public class UploadController {
	// Spring 容器存在 ServletContext 类型的对象,所以定义好 ServletContext 类型字段贴@Autowired 注解即可获取到
	@Autowired
	private ServletContext servletContext;
	@RequestMapping("/upload")
	public ModelAndView upload(Part pic) throws Exception {
		System.out.println(pic.getContentType()); // 文件类型
		System.out.println(pic.getName()); // 文件参数名
		System.out.println(pic.getSize()); // 文件大小
		System.out.println(pic.getInputStream()); // 文件输入流
		// FileCopyUtils.copy(in, out),一个 Spring 提供的拷贝方法
		// 获取项目 webapp 目录下 uploadDir 目录的绝对路径
		System.out.println(servletContext.getRealPath("/uploadDir"));
		return null;
	}
}

4.6文件下载

文件下载:将服务器上的文件下载到当前用户访问的计算机的过程称之为文件下载

4.7开发控制器

下载时必须设置响应的头信息,指定文件以何种方式保存,另外下载文件的控制器不能存在返回值,代表响应只用来下载文件信息`

/**
     * 测试文件下载
     * @param fileName 要下载文件名
     * @return
     */
    @RequestMapping("download")
    public String download(String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException {
        //获取下载服务器上文件的绝对路径
        String realPath = request.getSession().getServletContext().getRealPath("/down");
        //根据文件名获取服务上指定文件
        FileInputStream is = new FileInputStream(new File(realPath, fileName));
        //获取响应对象设置响应头信息
        response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode(fileName,"UTF-8"));
        ServletOutputStream os = response.getOutputStream();
        IOUtils.copy(is,os);
        IOUtils.closeQuietly(is);
        IOUtils.closeQuietly(os);
        return null;
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值