SpringMVC超详解

文章目录

1 Spring MVC 介绍

1.1 MVC模型

MVC全名是Model View Controller 模型视图控制器,每个部分各司其职。

  • Model:数据模型,JavaBean的类,用来进行数据封装。
  • View:指JSP、HTML用来展示数据给用户
  • Controller:用来接收用户的请求,整个流程的控制器。用来进行数据校验等。

1.2 Spring MVC

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

Spring MVC主要由前端映射器DispatcherServlet、处理器映射器HandlerMapping、处理器适配器HandlAdapter、处理器Handler、视图解析器View Resolver、视图View组成。

两个核心:
处理器映射器:选择使用哪个控制器来处理请求
视图解析器:选择结果应该如何渲染

2 Spring MVC处理请求流程

2.1 流程介绍


第一步:用户发送请求到前端控制器(DispatcherServlet)。
第二步:前端控制器请求处理器映射器 HandlerMapping 查找 Handler,可以根据 xml 配置、注解进行查找。
第三步:处理器映射器 HandlerMapping 向前端控制器返回 Handler
第四步:前端控制器调用处理器适配器去执行 Handler
第五步:处理器适配器执行 Handler
第六步:Handler 执行完成后给适配器返回 ModelAndView
第七步:处理器适配器向前端控制器返回 ModelAndView
ModelAndView 是SpringMVC 框架的一个底层对象,包括 Model 和 View
第八步:前端控制器请求试图解析器去进行视图解析
根据逻辑视图名来解析真正的视图。
第九步:视图解析器向前端控制器返回 view
第十步:前端控制器进行视图渲染
就是将模型数据(在 ModelAndView 对象中)填充到 request 域
第十一步:前端控制器向用户响应结果

2.2 组件介绍

1、前端控制器DispatcherServlet(不需要程序员开发)。
作用:接收请求,响应结果,相当于转发器,中央处理器。有了DispatcherServlet减少了其它组件之间的耦合度。
2、处理器映射器HandlerMapping(不需要程序员开发)。
作用:HandlerMapping 负责根据用户请求的url找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
3、处理器适配器HandlerAdapter(不需要程序员开发)。
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler。
4、处理器Handler(需要程序员开发)。
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
5、视图解析器ViewResolver(不需要程序员开发)。
作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
6、视图View(需要程序员开发jsp)。
注意:View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)

注意:不需要程序员开发的,需要程序员自己做一下配置即可。
可以总结出:需要我们开发的工作只有处理器** Handler 的编写以及视图**比如JSP页面的编写。

3 SpringMVC的入门案例

1. SpringMVC的入门程序

1.1 WEB工程结构

image.png

1.2 创建WEB工程,引入的依赖

<?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>com.pikaqiu</groupId>
  <artifactId>SpringMVC_InitalCase</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>SpringMVC_InitalCase Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <spring.version>5.0.2.RELEASE</spring.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <build>
    <finalName>SpringMVC_InitalCase</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

1.3 配置核心的控制器(配置DispatcherServlet)

在web.xml配置文件中核心控制器DispatcherServlet

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

  <!--配置核心控制器DispatcherServle-->
  <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:springmvc.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>

</web-app>

1.4 编写springmvc.xml的配置文件

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

    <!--开启注解扫描-->
    <context:component-scan base-package="com.pikaqiu"></context:component-scan>

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

    <!--开启SpringMVC框架注解的支持-->
    <!--会自动注册RequestMappingHandlerMapping与RequestMappingHandlerAdapter两个Bean-->
    <mvc:annotation-driven/>
</beans>

注意:mvc:annotation-driven/的作用

它就相当于在 xml 中配置了:
<!-- 上面的标签相当于 如下配置-->
<!-- Begin -->
<!-- HandlerMapping --> 
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerM
apping"></bean> 
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- HandlerAdapter --> 
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerA
dapter"></bean> 
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean> <bean
class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- HadnlerExceptionResolvers --> 
<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExcept
ionResolver"></bean> 
<bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolv
er"></bean> 
<bean class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver"
></bean>
<!-- End -->

1.5 编写index.jsp和Controller控制器类

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Title</title>
  </head>
  <body>
    <h3>入门程序</h3>
    <a href="hello">入门程序</a>
  </body>
</html>

package com.pikaqiu;

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

/**
 * @author pikaqiu
 * @description: TODO 类描述
 * @date: 2022/3/26 14:49
 **/
@Controller
public class HelloController {
	@RequestMapping(path = "/hello")
	public String sayHello(){
		System.out.println("hello SpringMVC");
		return "success";
	}
}

1.6 在WEB-INF目录下创建pages文件夹,编写success.jsp的成功页面

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

1.7 Tomcat配置

image.png
image.png

1.8 启动Tomcat

image.png

1.9 入门案例的执行过程分析

  1. 当启动Tomcat服务器的时候,因为配置了load-on-startup标签,所以会创建DispatcherServlet对象, 就会加载springmvc.xml配置文件
  2. 开启了注解扫描,那么HelloController对象就会被创建
  3. 从index.jsp发送请求,请求会先到达DispatcherServlet核心控制器,根据配置@RequestMapping注解 找到执行的具体方法
  4. 根据执行方法的返回值,再根据配置的视图解析器,去指定的目录下查找指定名称的JSP文件
  5. Tomcat服务器渲染页面,做出响应

4 请求参数的绑定

4.1 请求参数的绑定说明

4.1.1 绑定机制

1️⃣ 表单提交的数据都是k=v格式的 username=haha&password=123 
2️⃣ SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的 
3️⃣ 要求:提交表单的name和参数的名称是相同的 

4.1.2 支持的数据类型

1️⃣ 基本数据类型和String类型 
2️⃣ POJO类型(包括实体类,以及关联的实体类) 
3️⃣ 数组和集合数据类型(List、map集合等)

4.2 基本数据类型和String类型

1️⃣ 提交表单的name和参数的**名称是相同**的 
2️⃣ 严格区分大小写 
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <a href="param/testBasicParamAndString?userName=zhangsan&age=23">基本类型和String类型请求参数绑定</a>
</body>
</html>
package com.pikaqiu;

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

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 16:06
 **/
@Controller
@RequestMapping("/param")
public class ParamController {
	@RequestMapping("/testBasicParamAndString")
	public String testBasicParamAndString(String userName, Integer age){
		System.out.println("正常运行");
		System.out.println("userName: " + userName + " age: " + age);
		return "success";
	}
}

4.3 POJO类型(JavaBean)

1️⃣ 提交表单的name和JavaBean中的**属性名称需要一致** 
2️⃣ 如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性 例	如: address.name 
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="param/testPoJO" method="post">
        姓名:<input type="text" name="userName"><br/>
        密码:<input type="text" name="passWord"><br/>
        工资:<input type="text" name="money"><br/>
        uName:<input type="text" name="user.uName"><br/>
        uAge:<input type="text" name="user.uAge"><br/>

        <input type="submit" value="提交">
    </form>
</body>
</html>

package com.pikaqiu.controller;

import com.pikaqiu.domain.Account;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 16:06
 **/
@Controller
@RequestMapping("/param")
public class ParamController {
	@RequestMapping("/testPoJO")
	public String testPOJOParam(Account account){
		System.out.println("正常运行");
		System.out.println(account);
		return "success";
	}
}

4.4 集合类型

第一种:
要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。
给 List 集合中的元素赋值,使用下标。
给 Map 集合中的元素赋值,使用键值对。

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

    <form action="param/testListAndMap" method="post">
        姓名:<input type="text" name="userName"><br/>
        密码:<input type="text" name="passWord"><br/>
        工资:<input type="text" name="money"><br/>
        用户姓名:<input type="text" name="uList[0].uName"><br/>
        用户年龄:<input type="text" name="uList[0].uAge"><br/>
        用户姓名:<input type="text" name="uList[1].uName"><br/>
        用户年龄:<input type="text" name="uList[1].uAge"><br/>
        用户姓名:<input type="text" name="uMap['one'].uName"><br/>
        用户年龄:<input type="text" name="uMap['one'].uAge"><br/>
        用户姓名:<input type="text" name="uMap['two'].uName"><br/>
        用户年龄:<input type="text" name="uMap['two'].uAge"><br/>

        <input type="submit" value="提交">
    </form>

</body>
</html>

package com.pikaqiu.controller;

import com.pikaqiu.domain.Account;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 16:06
 **/
@Controller
@RequestMapping("/param")
public class ParamController {

	@RequestMapping("/testListAndMap")
	public String test(Account account)
	{
		System.out.println("正常运行");
		System.out.println(account);
		return "success";
	}
}

第二种:
接收的请求参数是 json 格式数据。需要借助一个注解实现。(@ResponseBody)

4.5 请求参数中文乱码的解决

post请求: 在web.xml中配置Spring提供的过滤器类

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

  <!--配置中文乱码过滤器-->
  <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>

  <!--配置核心控制器DispatcherServle-->
  <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:springmvc.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>

</web-app>

**get请求:tomacat 对 GET 和 POST 请求处理方式是不同的,GET 请求的编码要改 tomcat 的server.xml **
配置文件

改为:

如果遇到 ajax 请求仍然乱码,请把:
useBodyEncodingForURI="true"改为 URIEncoding=“UTF-8”
即可。

4.6 自定义类型转换器

1.表单提交的任何数据类型全部都是字符串类型,但是后台定义Integer类型,数据也可以封装上,说明 Spring框架内部会默认进行数据类型转换。
2.如果想自定义数据类型转换,可以实现Converter的接口

4.6.1 自定义类型转换器

package com.pikaqiu.util;

import org.springframework.core.convert.converter.Converter;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 把字符串转换为日期
 **/
public class StringToDateConverter implements Converter<String, Date> {
	@Override
	public Date convert(String source) {
		if(source == null){
			throw new RuntimeException("请您传入数据");
		}
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		// 把字符串转为日期
		try {
			return df.parse(source);
		} catch (ParseException e) {
			throw new RuntimeException("数据类型转换出现错误");
		}
	}
}

4.6.2 注册自定义类型转换器,在springmvc.xml配置文件中编写配置

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

    <!--开启注解扫描-->
    <context:component-scan base-package="com.pikaqiu"></context:component-scan>

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

    <!--配置自定义类型转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.pikaqiu.util.StringToDateConverter"></bean>
            </set>
        </property>
    </bean>

    <!--开启SpringMVC框架注解的支持-->
    <!--会自动注册RequestMappingHandlerMappingRequestMappingHandlerAdapter两个Bean-->
    <mvc:annotation-driven conversion-service="conversionService"/>
</beans>

4.6.3 param.jsp

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

    <form action="param/testSelfConverter" method="post">
        姓名:<input type="text" name="uName"><br/>
        年龄:<input type="text" name="uAge"><br/>
        生日:<input type="text" name="birthDay"><br/>

        <input type="submit" value="提交">
    </form>

</body>
</html>

4.6.4 Controller类

package com.pikaqiu.controller;

import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 16:06
 **/
@Controller
@RequestMapping("/param")
public class ParamController {
	
	@RequestMapping("/testSelfConverter")
	public String testSelfConverter(User user)
	{
		System.out.println("正常运行");
		System.out.println(user);
		return "success";
	}
}

4.7 控制器使用原生的ServletAPI对象

只需要在控制器的方法参数定义HttpServletRequest和HttpServletResponse对象

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
  
    <a href="param/testServlet?username=haha&password=123">Servlet原生的API</a>

</body>
</html>
package com.pikaqiu.controller;

import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

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

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 16:06
 **/
@Controller
@RequestMapping("/param")
public class ParamController {
	/**
	 * 使用Servlet原生的API
	 * @param
	 * @return
	 */
	@RequestMapping("/testServlet")
	public String testServlet(HttpServletRequest request, HttpServletResponse response){
		System.out.println("正常运行");
		System.out.println(request);

		HttpSession session = request.getSession();
		System.out.println(session);

		ServletContext servletContext = session.getServletContext();
		System.out.println(servletContext);

		System.out.println(response);
		return "success";
	}
}

5 常用注解

5.1 RequestParam注解

1️⃣ 作用:把请求中的指定名称的参数传递给控制器中的形参赋值
2️⃣ 属性
value:请求参数中的名称
required:请求参数中是否必须提供此参数,默认值是true,必须提供

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

    <a href="param/testRequestParam?username=haha&password=123">RequestParam注解</a>

</body>
</html>
package com.pikaqiu.controller;

import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

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

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 16:06
 **/
@Controller
@RequestMapping("/param")
public class ParamController {
	/**
	 * @RequestParam注解
     */
	@RequestMapping("/testRequestParam")
	public String testRequestParam(@RequestParam(name = "username") String username, @RequestParam(name = "password") String password){
		System.out.println("正常运行");
		System.out.println(username);
		System.out.println(password);
		return "success";
	}
}

注意:AnnoController类中 @RequestParam(name = “name”),name的值与 href="anno/testRequestParam?name=哈哈"中 name值一致。

5.2 RequestBody注解

1️⃣ 作用:用于获取请求体的内容(注意:get方法不可以
2️⃣ 属性
required:是否必须有请求体,默认值是true

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
  <form action="param/testRequestBody" method="post">
        用户姓名:<input type="text" name="uname"><br/>
        用户年龄:<input type="text" name="uage"><br/>
        <input type="submit" value="提交">
  </form>
</body>
</html>

package com.pikaqiu.controller;

import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

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

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 16:06
 **/
@Controller
@RequestMapping("/param")
public class ParamController {
	/**
	 * @RequestBody注解
	 */
	@RequestMapping("/testRequestBody")
	public String testRequestBody(@RequestBody(required=false) String body){
		System.out.println("正常运行");
		System.out.println(body);
		return "success";
	}
}

5.3 PathVariable注解

1️⃣ 作用:拥有绑定url中的占位符的。例如:url中有/delete/{id},{id}就是占位符
2️⃣ 属性
value:指定url中的占位符名称
3️⃣ Restful风格的URL
①请求路径一样,可以根据不同的请求方式去执行后台的不同方法
②restful风格的URL优点
结构清晰
符合标准
易于理解
扩展方便

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <a href="param/testPathVariable/33">testPathVariable</a>
</body>
</html>
package com.pikaqiu.controller;

import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

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

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 16:06
 **/
@Controller
@RequestMapping("/param")
public class ParamController {
	/**
	 * @PathVariable注解
	 */
	@RequestMapping("/testPathVariable/{id}")
	public String testPathVariable(@PathVariable(name = "id") String id){
		System.out.println("正常运行");
		System.out.println(id);
		return "success";
	}
}

注意:path = "/testPathVariable/{id}"中id和 @PathVariable(name=“id”)中id保持一致,且href=“anno/testPathVariable/10”,直接写入值,无需参数.

5.4 RequestHeader注解

1️⃣ 作用:获取指定请求头的值
2️⃣ 属性
value:请求头的名称

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

</body>
</html>
package com.pikaqiu.controller;

import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

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

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 16:06
 **/
@Controller
@RequestMapping("/param")
public class ParamController {
	/**
	 * @RequestHeader注解
	 */
	@RequestMapping("/testRequestHeader")
	public String testRequestHeader(@RequestHeader(value = "Accept") String header) {
		System.out.println("正常运行");
		System.out.println(header);
		return "success";

	}
}

5.5 CookieValue注解

1️⃣ 作用:用于获取指定cookie的名称的值
2️⃣ 属性
value:cookie的名称

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

    <a href="param/testCookieValue">testCookieValue</a>

</body>
</html>
package com.pikaqiu.controller;

import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

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

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 16:06
 **/
@Controller
@RequestMapping("/param")
public class ParamController {
	/**
	 * @CookieValue注解
	 */
	@RequestMapping("/testCookieValue")
	public String testCookieValue(@CookieValue(value = "JSESSIONID") String header) {
		System.out.println("正常运行");
		System.out.println(header);
		return "success";
	}
}

5.6 ModelAttribute注解

1️⃣ 作用
① 出现在方法上:表示当前方法会在控制器方法执行前先执行。
② 出现在参数上:获取指定的数据给参数赋值。
2️⃣ 应用场景
① 当提交表单数据不是完整的实体数据时,保证没有提交的字段使用数据库原来的数据。

5.6.1 出现在方法上

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

    <form action="param/testModelAttribute" method="post">
        用户姓名:<input type="text" name="uName"><br/>
        用户年龄:<input type="text" name="uAge"><br/>

        <input type="submit" value="提交">
    </form>

</body>
</html>
	package com.pikaqiu.controller;

	import com.pikaqiu.domain.Account;
	import com.pikaqiu.domain.User;
	import org.springframework.stereotype.Controller;
	import org.springframework.web.bind.annotation.*;

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

	/**
	 * @description: TODO 类描述
	 * @date: 2022/3/26 16:06
	 **/
	@Controller
	@RequestMapping("/param")
	public class ParamController {
		/**
		 * @ModelAttribute注解
		 */
		@RequestMapping("/testModelAttribute")
		public String testModelAttribute() {
			System.out.println("testModelAttribute运行");
			return "success";

		}

		@ModelAttribute
		public void showUser(){
			System.out.println("showUser方法执行了");
		}
	}

运行结果:
image.png

5.6.2 基于 Map 的应用场景示例:ModelAttribute 修饰方法带返回值

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

    <form action="param/testModelAttribute" method="post">
        用户姓名:<input type="text" name="uName"><br/>
        用户年龄:<input type="text" name="uAge"><br/>

        <input type="submit" value="提交">
    </form>

</body>
</html>
	package com.pikaqiu.controller;

	import com.pikaqiu.domain.Account;
	import com.pikaqiu.domain.User;
	import org.springframework.stereotype.Controller;
	import org.springframework.web.bind.annotation.*;

	import javax.servlet.ServletContext;
	import javax.servlet.http.HttpServletRequest;
	import javax.servlet.http.HttpServletResponse;
	import javax.servlet.http.HttpSession;
	import java.util.Date;

	/**
	 * @description: TODO 类描述
	 * @date: 2022/3/26 16:06
	 **/
	@Controller
	@RequestMapping("/param")
	public class ParamController {
		/**
		 * @ModelAttribute注解
		 */
		@RequestMapping("/testModelAttribute")
		public String testModelAttribute(User user) {
			System.out.println("testModelAttribute运行");
			System.out.println(user);
			return "success";

		}


		/**
		 * 该方法会先执行
		 */
		@ModelAttribute
		public User showUser(String uName){
			System.out.println("showUser方法执行了");
			// 通过用户查询数据库(模拟)
			User user = new User();
			user.setuName(uName);
			user.setuAge(23);
			user.setBirthDay(new Date());
			return user;
		}

	}

结果:
image.png

5.6.3 基于 Map 的应用场景示例 :ModelAttribute 修饰方法不带返回值

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

    <form action="param/testModelAttribute" method="post">
        用户姓名:<input type="text" name="uName"><br/>
        用户年龄:<input type="text" name="uAge"><br/>

        <input type="submit" value="提交">
    </form>

</body>
</html>
	package com.pikaqiu.controller;

	import com.pikaqiu.domain.Account;
	import com.pikaqiu.domain.User;
	import org.springframework.stereotype.Controller;
	import org.springframework.web.bind.annotation.*;

	import javax.servlet.ServletContext;
	import javax.servlet.http.HttpServletRequest;
	import javax.servlet.http.HttpServletResponse;
	import javax.servlet.http.HttpSession;
	import java.util.Date;
	import java.util.Map;

	/**
	 * @description: TODO 类描述
	 * @date: 2022/3/26 16:06
	 **/
	@Controller
	@RequestMapping("/param")
	@SessionAttributes()
	public class ParamController {
		/**
		 * @ModelAttribute注解
		 */
		@RequestMapping("/testModelAttribute")
		public String testModelAttribute(@ModelAttribute("user") User user) {
			System.out.println("testModelAttribute运行");
			System.out.println(user);
			return "success";

		}

		/**
		 * 该方法会先执行
		 */
		@ModelAttribute
		public void showUser(String uName, Map<String, User> map){
			System.out.println("showUser方法执行了");
			// 通过用户查询数据库(模拟)
			User user = new User();
			user.setuName(uName);
			user.setuAge(23);
			user.setBirthDay(new Date());
			map.put("user", user);
		}
	}

image.png

5.7 SessionAttributes注解

1️⃣ 作用:
用于多次执行控制器方法间的参数共享。
2️⃣ 属性:
value:用于指定存入的属性名称
type:用于指定存入的数据类型。
未加@SessionAttributes注解

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>入门成功</h3>

    ${requestScope.name}
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    <a href="param/testSessionAttributes">testSessionAttributes</a>
    <br>

</body>
</html>
	package com.pikaqiu.controller;

	import com.pikaqiu.domain.Account;
	import com.pikaqiu.domain.User;
	import org.springframework.stereotype.Controller;
	import org.springframework.ui.Model;
	import org.springframework.web.bind.annotation.*;

	import javax.servlet.ServletContext;
	import javax.servlet.http.HttpServletRequest;
	import javax.servlet.http.HttpServletResponse;
	import javax.servlet.http.HttpSession;
	import java.util.Date;
	import java.util.Map;

	/**
	 * @description: TODO 类描述
	 * @date: 2022/3/26 16:06
	 **/
	@Controller
	@RequestMapping("/param")
	public class ParamController {
		/**
		 * @SessionAttributes注解
		 */
		@RequestMapping("/testSessionAttributes")
		public String testSessionAttributes(Model model) {
			System.out.println("正常运行");
			//  底层会存储到request域对象中
			model.addAttribute("name", "zhangsan");
			return "success";
		}
	}

@SessionAttributes注解

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>入门成功</h3>

    ${requestScope.name}
    ${sessionScope}
</body>
</html>
	package com.pikaqiu.controller;

	import com.pikaqiu.domain.Account;
	import com.pikaqiu.domain.User;
	import org.springframework.stereotype.Controller;
	import org.springframework.ui.Model;
	import org.springframework.web.bind.annotation.*;

	import javax.servlet.ServletContext;
	import javax.servlet.http.HttpServletRequest;
	import javax.servlet.http.HttpServletResponse;
	import javax.servlet.http.HttpSession;
	import java.util.Date;
	import java.util.Map;

	/**
	 * @description: TODO 类描述
	 * @date: 2022/3/26 16:06
	 **/
	@Controller
	@RequestMapping("/param")
	@SessionAttributes(value = {"name"}) // 把name=zhangsan存入到session域中
	public class ParamController {
		/**
		 * @SessionAttributes注解
		 */
		@RequestMapping("/testSessionAttributes")
		public String testSessionAttributes(Model model) {
			System.out.println("正常运行");
			//  底层会存储到request域对象中
			model.addAttribute("name", "zhangsan");
			return "success";
		}
	}

@SessionAttributes注解中实现获取和删除session域中对象

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>入门成功</h3>

    ${requestScope.name}
    ${sessionScope}
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    <a href="param/testSessionAttributes">testSessionAttributes</a>
    <br>
    <a href="param/getSessionAttributes">getSessionAttributes</a>
    <br>
    <a href="param/delSessionAttributes">delSessionAttributes</a>

</body>
</html>
	package com.pikaqiu.controller;

	import com.pikaqiu.domain.Account;
	import com.pikaqiu.domain.User;
	import org.springframework.stereotype.Controller;
	import org.springframework.ui.Model;
	import org.springframework.web.bind.annotation.*;

	import javax.servlet.ServletContext;
	import javax.servlet.http.HttpServletRequest;
	import javax.servlet.http.HttpServletResponse;
	import javax.servlet.http.HttpSession;
	import java.util.Date;
	import java.util.Map;

	/**
	 * @description: TODO 类描述
	 * @date: 2022/3/26 16:06
	 **/
	@Controller
	@RequestMapping("/param")
	@SessionAttributes(value = {"name"}) // 把name=zhangsan存入到session域中
	public class ParamController {
		/**
		 * @SessionAttributes注解
		 */
		@RequestMapping("/testSessionAttributes")
		public String testSessionAttributes(Model model) {
			System.out.println("正常运行");
			//  底层会存储到request域对象中
			model.addAttribute("name", "zhangsan");
			return "success";
		}
         /**
		 * Session域获取值
		 * @param modelMap
		 * @return
		 */
		@RequestMapping(path = "/getSessionAttributes")
		public String getSessionAttributes(ModelMap modelMap){
			System.out.println("getSessionAttributes....");
			String msg = (String)modelMap.get("name");
			System.out.println(msg);
			return "success";
		}

		/**
		 * Session域清除
		 * @param status
		 * @return
		 */
		@RequestMapping(path = "/delSessionAttributes")
		public String delSessionAttributes(SessionStatus status){
			System.out.println("delSessionAttributes....");
			status.setComplete();
			return "success";
		}
	}

6 响应数据和结果视图

6.1 返回值分类

6.1.1 返回字符串

Controller方法返回字符串可以指定逻辑视图的名称,根据视图解析器解析为物理视图的地址。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <a href="returnValue/testString">testString</a>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>入门成功</h3>

    ${user.uName}
    ${user.birthDay}
</body>
</html>
package com.pikaqiu.controller;

import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Date;

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 21:00
 **/
@Controller
@RequestMapping("/returnValue")
public class ReturnValueController {
	@RequestMapping("/testString")
	public String testString(Model model){
		System.out.println("testString方法执行了");
		// 模拟从数据库中查询user对象
		User user = new User();
		user.setuName("haha");
		user.setuAge(23);
		user.setBirthDay(new Date());
        //  底层会存储到request域对象中
		model.addAttribute("user", user);
		return "success";
	}
}

6.1.2 返回值是void

① 如果控制器的方法返回值编写成void,执行程序报404的异常,默认查找JSP页面没有找到。 
		默认会跳转到@RequestMapping(value="/initUpdate") initUpdate的页面。 
② 可以使用请求转发或者重定向跳转到指定的页面

请求转发、重定向和直接响应

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <a href="returnValue/testVoid">testVoid</a>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>请求转发</h3>
</body>
</html>
package com.pikaqiu.controller;

import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Date;

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 21:00
 **/
@Controller
@RequestMapping("/returnValue")
public class ReturnValueController {
	/**
	 * 请求转发
	 */
	@RequestMapping("/testVoid")
	public void testVoid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("testVoid方法执行了");
		// 1. 请求转发
		//request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response);
		// 2. 重定向
		//response.sendRedirect(request.getContextPath() + "/response.jsp");

		// 设置中文乱码
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");

		// 3. 直接会进行响应
		response.getWriter().print("你好");
		return;
	}
}

6.1.3 返回值是ModelAndView对象

ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图

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

package com.pikaqiu.controller;

import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 21:00
 **/
@Controller
@RequestMapping("/returnValue")
public class ReturnValueController {
	/**
	 * 返回值是 ModelAndView
	 */
	@RequestMapping("/testModelAndView")
	public ModelAndView testModelAndView(){
		System.out.println("testModelAndView方法执行了");
		// 创建ModelAndView对象
		ModelAndView modelAndView = new ModelAndView();
		// 模拟从数据库中查询User对象
		User user = new User();
		user.setuName("haha");
		user.setuAge(23);
		user.setBirthDay(new Date());
		// 把user对象存储到mv对象中,也会把user对象存入到request对象
		modelAndView.addObject("user", user);
		// 跳转到哪个页面
		modelAndView.setViewName("success");
		return modelAndView;
	}
}

6.2 SpringMVC框架提供的转发和重定向

6.2.1 forward请求转发

controller 方法在提供了 String 类型的返回值之后,默认就是请求转发。也可以写成如下方式:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <a href="returnValue/testForward">testForward</a>
</body>
</html>
package com.pikaqiu.controller;

import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 21:00
 **/
@Controller
@RequestMapping("/returnValue")
public class ReturnValueController {
	@RequestMapping("/testForward")
	public String testForward(){
		System.out.println("testForward方法执行了");
		// 请求转发
		return "forward:/WEB-INF/pages/success.jsp";
	}
}

6.2.2 redirect重定向

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <a href="returnValue/testRedirect">testRedirect</a>
</body>
</html>
package com.pikaqiu.controller;

import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 21:00
 **/
@Controller
@RequestMapping("/returnValue")
public class ReturnValueController {
	@RequestMapping("/testRedirect")
	public String testRedirect(){
		System.out.println("testRedirect方法执行了");
		// 重定向
		return "redirect:/response.jsp";
	}
}

6.3 ResponseBody响应json数据

DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置

  • mvc:resources标签配置不过滤
  • location元素表示webapp目录下的包下的所有文件
  • mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!--开启注解扫描-->
    <context:component-scan base-package="com.pikaqiu"></context:component-scan>

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

    <!--配置自定义类型转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.pikaqiu.util.StringToDateConverter"></bean>
            </set>
        </property>
    </bean>

    <!--前端控制器,哪些静态资源不拦截-->
    <mvc:resources mapping="/css/**" location="/css/"/>
    <mvc:resources mapping="/images/**" location="/images/"/>
    <mvc:resources mapping="/js/**" location="/js/" />

    <!--开启SpringMVC框架注解的支持-->
    <!--会自动注册RequestMappingHandlerMapping与RequestMappingHandlerAdapter两个Bean-->
    <mvc:annotation-driven conversion-service="conversionService"/>
</beans>

@RequestBody注解用于将 Controller 的方法返回的对象,通过 HttpMessageConverter 接口转换为指定格式的数据如:json,xml 等,通过 Response 响应给客户端。

  • 使用@RequestBody获取请求体数据
  • 使用@RequestBody注解把json的字符串转换成JavaBean的对象
  • 使用@ResponseBody注解把JavaBean对象转换成json字符串,直接响应
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script src="js/jquery.min.js"></script>
    <script>
        //页面加载,绑定单击事件
        $(function () {
            $("#btn").click(function(){
                // alert("hello btn");
                // 发送ajax请求
                $.ajax({
                    // 编写json格式,设置属性和值
                    url:"user/testAjax",
                    contentType:"application/json;charset=UTF-8",
                    data:'{"username":"hehe", "password":"123", "age":"30"}',
                    dataType:"json",
                    type:"post",
                    success:function (data) {
                        // data服务器端响应的json的数据,进行解析
                        alert(data);
                        alert(data.username);
                        alert(data.password);
                    }
                })
            });
        });
     </script>
</head>
<body>
        <button id="btn">发送ajax的请求</button>
</body>
</html>

json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.9.0</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.9.0</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-annotations</artifactId>
  <version>2.9.0</version>
</dependency>
package com.pikaqiu.controller;

import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * @description: TODO 类描述
 * @date: 2022/3/26 21:00
 **/
@Controller
@RequestMapping("/returnValue")
public class ReturnValueController {
	/**
	 * 模拟异步请求响应
	 */
	public @ResponseBody User testAjax(@RequestBody User user){
		System.out.println("testAjax方法执行了");
		// 客户端发送ajax请求,传的是json字符串,后端把json字符串封装到user对象中
		System.out.println(user);
		// 做响应后,模拟查询数据库
		user.setuName("lisi");
		user.setuAge(66);
		// 作响应,@ResponseBody会将user对象转成json格式
		return user;
	}
}

7 SpringMVC实现文件上传

7.1 文件上传的必要前提

  • form 表单的 enctype 取值必须是:multipart/form-data

    (默认值是:application/x-www-form-urlencoded) enctype:是表单请求正文的类型

  • method 属性取值必须是 Post

  • 提供一个文件选择域

7.2 传统文件上传方法

导入文件的jar包

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.4</version>
</dependency>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
        <h3>文件上传</h3>

        <form action="user/testFileUpload" method="post" enctype="multipart/form-data">
            选择文件:<input type="file" name="upload" /><br/>
            <input type="submit" value="上传"/>
        </form>
</body>
</html>
package com.pikaqiu.controller;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.List;
import java.util.UUID;

/**
 * @description: TODO 类描述
 * @date: 2022/3/27 16:21
 **/
@Controller
@RequestMapping("/file")
public class FileUploadController {
	@RequestMapping("/testFileUpload")
	public String testFileUpload(HttpServletRequest request) throws Exception {
		System.out.println("文件上传");
		// 使用功能fileupload组件完成文件上传
		// 上传的位置
		String path = request.getSession().getServletContext().getRealPath("/uploads/");
		File file = new File(path);
		if(!file.exists()){
			// 创建该文件夹
			file.mkdirs();
		}
		// 实现步骤
		// 1、创建DiskFileItemFactory对象,设置缓冲区大小和临时文件目录
		// 2、使用DiskFileItemFactory 对象创建ServletFileUpload对象,并设置上传文件的大小限制。
		// 3、调用ServletFileUpload.parseRequest方法解析request对象,得到一个保存了所有上传内容的List对象。
		// 4、对list进行迭代,每迭代一个FileItem对象,调用其isFormField方法判断是否是上传文件
		//    True 为普通表单字段,则调用getFieldName、getString方法得到字段名和字段值
		//    False 为上传文件

		// 解析request对象,获取上传文件项
		DiskFileItemFactory factory = new DiskFileItemFactory();
		// 创建一个上传工具,指定使用缓存区与临时文件存储位置
		ServletFileUpload upload = new ServletFileUpload(factory);
		// 解析request
		// 它是用于解析request对象,得到所有上传项.每一个FileItem就相当于一个上传项
		List<FileItem> fileItems = upload.parseRequest(request);
		// 遍历
		for(FileItem item:fileItems){
			// 进行判断,当前item是否是上传文件对象
			if(item.isFormField()){
				// true,说明是普通表单相
			}else{
				// 说明是上传文件项
				// 获取上传文件的名称
				String filename = item.getName();
				// 把文件的名称设置为唯一值,uuid
				String uuid = UUID.randomUUID().toString().replace("-", "");
				filename = uuid + "_" + filename;
				// 完成文件上传
				item.write(new File(path, filename));
				item.delete();
			}
		}
		return "success";
	}
}

7.3 SpringMVC传统方式文件上传

SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件,要求变量名称必须和表单file标签的 name属性名称相同。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>文件上传</h3>
    <form action="file/testFileUploadBySpringMVC" method="post" enctype="multipart/form-data">
        选择文件:<input type="file" name="upload"><br/>
        <input type="submit" value="上传">
    </form>
</body>
</html>

springmvc.xml中配置文件解析器对象

<!-- 配置文件解析器对象,要求id名称必须是multipartResolver -->
<bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="10485760"/>
</bean>

注意:id名称必须是multipartResolver, 选择文件: 和 MultipartFile upload中的 upload 保持一致

package com.pikaqiu.controller;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

/**
 * @description: TODO 类描述
 * @date: 2022/3/27 16:21
 **/
@Controller
@RequestMapping("/file")
public class FileUploadController {
	/**
	 * SpringMVC文件上传
	 */
	@RequestMapping("/testFileUploadBySpringMVC")
	public String testFileUploadBySpringMVC(HttpServletRequest request, MultipartFile upload) throws Exception {
		System.out.println("springMVC文件上传");
		// 使用功能fileupload组件完成文件上传
		// 上传的位置
		String path = request.getSession().getServletContext().getRealPath("/uploads/");
		// System.out.println(path);
		// 判断,该路径是否存在
		File file = new File(path);
		if(!file.exists()){
			// 创建该文件夹
			file.mkdirs();
		}
		// 获取到上传文件的名称
		String fileName = upload.getOriginalFilename();
		String uuid = UUID.randomUUID().toString().replace("-", "");
		// 把文件的名称唯一化
		fileName = uuid + "-" + fileName;
		// 完成文件上传
		upload.transferTo(new File(path, fileName));
		return "success";
	}
}

7.4 SpringMVC跨服务器方式文件上传

导入开发需要的jar包

<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-core</artifactId>
  <version>1.18.1</version>
</dependency>
<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-client</artifactId>
  <version>1.18.1</version>
</dependency>

参考:

  1. https://www.cnblogs.com/ysocean/p/7375405.html
  2. https://tyshawnlee.blog.csdn.net/article/details/79169148
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值