【SpringMVC的视图】

SpringMVC的视图

一、SpringMVC中的视图是View接口,视图的作用渲染数据,将模型Model中的数据展示给用户
二、SpringMVC视图的种类很多,默认有转发视图和重定向视图
三、当工程引入jstl的依赖,转发视图会自动转换为JstlView
四、若使用的视图技术为Thymeleaf,在SpringMVC的配置文件中配置了Thymeleaf的视图解析器,由此视图解析器解析之后所得到的是ThymeleafView

ThymeleafView

当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被SpringMVC配置文件中所配置的视图解析器解析,视图名称拼接视图前缀和视图后缀所得到的最终路径,会通过转发的方式实现跳转

@RequestMapping("/testThymeleafView")
public String testThymeleafView(){
	return "success";
}

转发视图

一、当前我们访问的很多页面是不满足Thymeleaf视图解析器的,比如在实现转发时,我们要访问的页面或者我们要转发的资源就不符合Thymeleaf视图解析器的规则。
二、SpringMVC中默认的转发视图是InternalResourceView
三、SpringMVC中创建转发视图的情况:当控制器方法中所设置的视图名称以forward:为前缀时,创建InternalResourceView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀forward:去掉,剩余部分作为最终路径通过转发的方式实现跳转,例如forward:/forward:/employee

@RequestMapping("/testForward")
public String testForward(){
	return "forward:/testThymeleafView";// 转发到上面那个请求:forward:要转发到的资源的路径
}

四、解析return "forward:/testThymeleafView";会创建两次视图,首先将前缀forward:去掉,剩余的部分/testThymeleafView通过转发访问,这个过程会创建转发视图InternalResourceView,但是因为/testThymeleafView也是一个请求,所以当找到/testThymeleafView的请求映射testThymeleafView方法时,还会再创建一个ThymeleafView

重定向视图

一、SpringMVC中默认的重定向视图是RedirectView
二、当控制器方法中所设置的视图名称以redirect:为前缀时,创建RedirectView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀redirect:去掉,剩余部分作为最终路径通过重定向的方式实现跳转,例如redirect:/redirect:/employee

@RequestMapping("/testRedirect")
public String testRedirect(){
	return "redirect:/testThymeleafView";// 重定向到上面那个请求:redirect:要重定向到的资源的路径
}

三、重定向视图在解析时,会先将redirect:前缀去掉,然后会判断剩余部分是否以/开头,若是则会自动拼接上下文路径
四、重定向可以改变地址栏中的地址,相当于浏览器再次发送请求去访问,像我们某个操作成功后,如操作成功、删除成功之后和原来的请求就没有关系了,这就需要重定向跳转,如果用转发的话会保留上一次请求路径
五、转发与重定向的区别:

  1. 转发是一次请求(这个一次请求指的是浏览器发送了一次请求),第一次时浏览器发送请求,第二次请求发生在服务器内部,所以地址栏还是浏览器发送请求的那个地址,地址栏中的地址不变
  2. 重定向是两次请求,第一次访问servlet,第二次访问重定向的地址,地址栏中的地址会变为重定向的地址
  3. 转发可以获取请求域中的数据,重定向不可以,因为重定向是两次请求,两次请求对应两个request对象,而转发是一次请求,用到的request对象是同一个。(注意:能否获取域对象中的数据,主要看你使用的对象是不是同一个)
  4. 转发可以访问WEB-INF中的资源,重定向不可以,因为WEB-INF中的资源具有安全性、隐藏性,只能通过服务器内部来访问,不能通过浏览器来访问
  5. 转发不能跨域,重定向可以,因为转发是发生在服务器内部的,只能访问服务器内部资源,重定向是浏览器发送了两次请求,通过浏览器可以访问任何资源,比如从我们的项目中重定向到百度,

视图控制器view-controller

一、视图控制器view-controller是springMVC配置文件的一个标签,用于实现请求地址与视图之间的映射关系,之前我们写了一个请求映射:

@RequestMapping("/testThymeleafView")
public String testThymeleafView(){
	return "success";
}

当我们访问路径为/testThymeleafView时,可以通过视图名称success,通过视图解析器解析来跳转到相对应的页面,这种请求映射我们会写很多,比如我们在实现添加功能时,添加成功后跳转到添加页面,这时是不需要有任何其他请求的处理,我们只需要写一个请求映射,对应一个请求路径,在他对应的控制器方法中返回视图名称即可,像这种控制器方法中不需要处理其他请求的过程时,我们可以使用view-controller标签来处理请求映射的关系,也就是说,当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理器方法使用view-controller标签进行表示,在springMVC.xml文件中配置:

<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
<mvc:view-controller path="/test_view" view-name="test_view"></mvc:view-controller>
<mvc:view-controller path="/test_rest" view-name="test_rest"></mvc:view-controller>

其中,path指定请求路径,view-name指定视图名称
二、当SpringMVC中设置任何一个view-controller时,其他控制器中的请求映射将全部失效,此时需要在SpringMVC的核心配置文件中设置开启mvc注解驱动的标签:<mvc:annotation-driven />

InternalResourceViewResolver

在springMVC.xml中配置:

<context:component-scan base-package="com.atguigu.mvc.controller"></context:component-scan>
<!-- 配置视图解析器 在JSP中,不涉及任何前缀他也是转发的效果,InternalResourceViewResolver是springMVC中默认的转发视图 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<!-- 前缀 -->
	<property name="prefix" value="/WEB-INF/templates/"></property>
	<!-- 后缀 -->
	<property name="suffix" value=".jsp"></property>
/bean>

index.jsp中代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--上面这一行是jsp指令,用来设置当前页面的信息,比如上面这行代码的意思是:
内容类型是以文本形式存在的html页面,使用UTF-8编码,JSP支持语言:Java

JSP是可以直接访问的,项目一启动,默认访问index.jsp--%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>首页</h1>
<%--${pageContext.request.contextPath}动态获取上下文对象--%>
<a href="${pageContext.request.contextPath}/success">success.jsp</a>
</body>
</html>

JspController.java中代码:

@Controller
public class JspController {
    @RequestMapping("/success")
    public String success(){
        return "success";
    }
}

RESTful

一、RESTful是一种软件架构的风格/格式,不以?传参,将所有的参数以/拼接到请求路径中
二、REST:Representational State Transfer,表现层(前端的视图页面到后端的控制层)资源状态转移。

  1. 把项目部署到服务器上之后,档期那工程中的内容在服务器上都叫资源。资源是一种看待服务器的方式,即,将服务器看作是由很多离散的资源组成。每个资源是服务器上一个可命名的抽象概念。因为资源是一个抽象的概念,所以它不仅仅能代表服务器文件系统中的一个文件、数据库中的一张表等等具体的东西,可以将资源设计的要多抽象有多抽象,只要想象力允许而且客户端应用开发者能够理解。与面向对象设计类似,资源是以名词为核心来组织的,首先关注的是名词。一个资源可以由一个或多个URI来标识。URI既是资源的名称,也是资源在Web上的地址。对某个资源感兴趣的客户端应用,可以通过资源的URI与其进行交互。
  2. 资源的状态是资源的表现形式,也就是资源的表述,比如html页面、音频、类等。资源的表述是一段对于资源在某个特定时刻的状态的描述。可以在客户端-服务器端之间转移(交换)。资源的表述可以有多种格式,例如HTML/XML/JSON/纯文本/图片/视频/音频等等。资源的表述格式可以通过协商机制来确定。请求-响应方向的表述通常使用不同的格式。
  3. 状态转移说的是:在客户端和服务器端之间转移(transfer)代表资源状态的表述,就是浏览器向服务器发送请求(请求某个资源),服务器响应这一过程。通过转移和操作资源的表述,来间接实现操作资源的目的。

三、RESTful的实现
具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。
它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE用来删除资源。
REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数,而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性。
在这里插入图片描述

RESTful模拟操作用户资源

使用RESTFul模拟用户资源的增删改查

请求路径请求方法操作
/userGET查询所有用户信息
/user/1GET根据用户id查询用户信息
/userPOST添加用户信息
/user/1DELETE删除用户信息
/userPUT修改用户信息

get和post请求

@Controller
public class UserController {
    @RequestMapping(value = "/user", method = RequestMethod.GET)
    public String getAllUser(){
        System.out.println("查询所有用户信息");
        return "success";
    }

    @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
    public String getUserById(){
        System.out.println("根据id查询用户信息");
        return "success";
    }

    @RequestMapping(value = "/user", method = RequestMethod.POST)
    public String insertUser(String username, String password){
        System.out.println("添加用户信息:"+username+","+password);
        return "success";
    }
}

前端代码:

<body>
<a th:href="@{/user}">查询所有用户信息</a><br>
<a th:href="@{/user/1}">根据id查询用户信息</a><br>
<form th:action="@{/user}" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit" value="添加"><br>
</form>

HiddenHttpMethodFilter

一、由于浏览器只支持发送get和post方式的请求,那么该如何发送put和delete请求呢?SpringMVC提供了HiddenHttpMethodFilter帮助我们将POST请求转换为DELETE或PUT请求
二、HiddenHttpMethodFilter处理put和delete请求的条件:

  1. 当前请求的请求方式必须为post
  2. 当前请求必须传输请求参数_method

满足以上条件,HiddenHttpMethodFilter过滤器就会将当前请求的请求方式转换为请求参数_method的值,因此请求参数_method的值才是最终的请求方式

<!--1. 当前请求的请求方式必须为post-->
<form th:action="@{/user}" method="post">
	<!--1. 当前请求必须传输请求参数_method,_method的值才是最终的请求方式-->
    <input type="hidden" name="_method" value="PUT">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit" value="修改"><br>
</form>

三、在web.xml中注册HiddenHttpMethodFilter:

<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filterclass>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

四、映射方法:

@RequestMapping(value = "/user", method = RequestMethod.PUT)
public String updateUser(String username, String password){
	System.out.println("修改用户信息:"+username+","+password);
	return "success";
}

五、目前为止,SpringMVC中提供了两个过滤器:CharacterEncodingFilter和HiddenHttpMethodFilter。在web.xml中注册时,必须先注册CharacterEncodingFilter,再注册HiddenHttpMethodFilter,因为在CharacterEncodingFilter中通过request.setCharacterEncoding(encoding)方法设置字符集的request.setCharacterEncoding(encoding)方法要求前面不能有任何获取请求参数的操作,而HiddenHttpMethodFilter恰恰有一个获取请求方式的操作:String paramValue = request.getParameter(this.methodParam);,他获取了参数_method,所以如果先注册HiddenHttpMethodFilter,再注册CharacterEncodingFilter,CharacterEncodingFilter会失效

RESTful案例

一、新建项目springMVC-rest,如前述搭建环境
二、搭建实体类src/main/java/com/atguigu/rest/bean

public class Employee {
    private Integer id;
    private String lastName;
    private String email;
    private Integer gender;

    public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
    public String getLastName() {return lastName;}
    public void setLastName(String lastName) {this.lastName = lastName;}
    public String getEmail() {return email;}
    public void setEmail(String email) {this.email = email;}
    public Integer getGender() {return gender;}
    public void setGender(Integer gender) {this.gender = gender;}
    public Employee(Integer id, String lastName, String email, Integer gender) {
        super();
        this.id = id;
        this.lastName = lastName;
        this.email = email;
        this.gender = gender;
    }
    public Employee() {}
}

三、准备dao模拟数据

@Repository
public class EmployeeDao {
	// 本例中我们没有service,需要从controller直接访问DAO,所以再DAO中要创建一个employees对象
    private static Map<Integer, Employee> employees = null;
    static{
        employees = new HashMap<Integer, Employee>();
        employees.put(1001, new Employee(1001, "E-AA", "aa@163.com", 1));
        employees.put(1002, new Employee(1002, "E-BB", "bb@163.com", 1));
        employees.put(1003, new Employee(1003, "E-CC", "cc@163.com", 0));
        employees.put(1004, new Employee(1004, "E-DD", "dd@163.com", 0));
        employees.put(1005, new Employee(1005, "E-EE", "ee@163.com", 1));
    }
    private static Integer initId = 1006;
    public void save(Employee employee){
        if(employee.getId() == null){
            employee.setId(initId++);
        }
        employees.put(employee.getId(), employee);
    }
    public Collection<Employee> getAll(){return employees.values();}
    public Employee get(Integer id){return employees.get(id);}
    public void delete(Integer id){employees.remove(id);}
}

具体功能

功能URL地址请求方式
访问首页/GET
查询全部数据/employeeGET
删除/employee/2DELETE
跳转到添加数据页面/toAddGET
执行保存/employeePOST
跳转到更新数据页面/employee/2GET
执行更新/employeePUT
访问首页

一、在springMVC.xml配置视图控制器:

<!--配置视图控制器-->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
<!--开启mvc注解驱动-->
<mvc:annotation-driven />

二、创建页面:

<body>
	<h1>首页</h1>
	<a th:href="@{/employee}">访问员工信息</a>
</body>

三、配置tomcat

查询所有员工数据

一、控制器方法

@RequestMapping(value = "/employee", method = RequestMethod.GET)
public String getEmployeeList(Model model){
	Collection<Employee> employeeList = employeeDao.getAll();
	model.addAttribute("employeeList", employeeList);
	return "employee_list";
}

二、创建employee_list.html,页面代码如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>Employee Info</title>
	<script type="text/javascript" th:src="@{/static/js/vue.js}"></script>
</head>
<body>
		<table border="1" cellpadding="0" cellspacing="0" style="text-align:
center;" id="dataTable">
			<tr>
				<th colspan="5">Employee Info</th>
			</tr>
			<tr>
				<th>id</th>
				<th>lastName</th>
				<th>email</th>
				<th>gender</th>
				<th>options(<a th:href="@{/toAdd}">add</a>)</th>
			</tr>
			<tr th:each="employee : ${employeeList}">
				<td th:text="${employee.id}"></td>
				<td th:text="${employee.lastName}"></td>
				<td th:text="${employee.email}"></td>
				<td th:text="${employee.gender}"></td>
				<td>
						<a class="deleteA" @click="deleteEmployee"
th:href="@{'/employee/'+${employee.id}}">delete</a>
					<a th:href="@{'/employee/'+${employee.id}}">update</a>
				</td>
			</tr>
		</table>
	</body>
</html>
删除

一、创建处理delete请求方式的表单

<!-- 作用:通过超链接控制表单的提交,将post请求转换为delete请求 -->
<form id="delete_form" method="post">
	<!-- HiddenHttpMethodFilter要求:必须传输_method请求参数,并且值为最终的请求方式 -->
	<input type="hidden" name="_method" value="delete"/>
</form>

二、删除超链接绑定点击事件

  1. 引入vue.js:<script type="text/javascript" th:src="@{/static/js/vue.js}"></script>
  2. 删除超链接:<a class="deleteA" @click="deleteEmployee" th:href="@{'/employee/'+${employee.id}}">delete</a>
  3. 通过vue处理点击事件
<script type="text/javascript">
	var vue = new Vue({
		el:"#dataTable",
		methods:{
			//event表示当前事件
			deleteEmployee:function (event) {
				//通过id获取表单标签
				var delete_form = document.getElementById("delete_form");
				//将触发事件的超链接的href属性为表单的action属性赋值
				delete_form.action = event.target.href;
				//提交表单
				delete_form.submit();
				//阻止超链接的默认跳转行为
				event.preventDefault();
			}
		}
	});
</script>
  1. 控制器方法
@RequestMapping(value = "/employee/{id}", method = RequestMethod.DELETE)
public String deleteEmployee(@PathVariable("id") Integer id){
	employeeDao.delete(id);
	return "redirect:/employee";
}
  1. 静态资源不会被springMVC处理,所以无法访问vue.js资源,我们需要开放对静态资源的访问,在springMVC.xml新增代码:<mvc:default-servlet-handler />。以后访问静态资源的流程:首先,静态资源会先被springMVC处理,也就是前端控制器DispatcherServlet处理,如果在控制器中找不到相对应的请求映射,就会把静态资源交给默认的servlet来处理,如果默认的servlet能找到相对应的资源,那我们就访问资源,如果找不到相对应的资源,报404
添加

一、点击页面的add,会实现跳转到添加页面:<th>options(<a th:href="@{/toAdd}">add</a>)</th>
二、因为跳转到添加页面不用做其他处理,所以直接在springMVC.xml中配置视图控制器:<mvc:view-controller path="/toAdd" view-name="employee_add"></mvc:view-controller>
三、创建添加数据的页面employee_add.html,代码如下:

<body>
<form th:action="@{/employee}" method="post">
    lastName:<input type="text" name="lastName"><br>
    email:<input type="text" name="email"><br>
    gender:<input type="radio" name="gender" value="1">male
    <input type="radio" name="gender" value="0">female<br>
    <input type="submit" value="add"><br>
</form>
</body>

四、执行保存,控制器中的方法:

@RequestMapping(value = "/employee", method = RequestMethod.POST)
public String addEmployee(Employee employee){
	employeeDao.save(employee);
    return "redirect:/employee";
}
修改

一、点击页面的update,会实现跳转到更新数据页面:<a th:href="@{'/employee/'+${employee.id}}">update</a>,更新数据页面需要回显信息,所以需要取出数据保存在域中,然后在页面从域中取出数据并展示出来
二、查询数据并将数据保存在域中

@RequestMapping(value = "/employee/{id}", method = RequestMethod.GET)
public String getEmployeeById(@PathVariable("id") Integer id, Model model){
	Employee employee = employeeDao.get(id);
	model.addAttribute("employee", employee);
	return "employee_update";
}

三、创建更新页面employee_update.html,在页面中回显数据:

<body>
	<form th:action="@{/employee}" method="post">
		<input type="hidden" name="_method" value="put">
		<input type="hidden" name="id" th:value="${employee.id}">
		lastName:<input type="text" name="lastName" th:value="${employee.lastName}">
		<br>
		email:<input type="text" name="email" th:value="${employee.email}">
		<br>
		<!--
		th:field="${employee.gender}"可用于单选框或复选框的回显
		若单选框的value和employee.gender的值一致,则添加checked="checked"属性
		-->
		gender:<input type="radio" name="gender" value="1" th:field="${employee.gender}">male
		<input type="radio" name="gender" value="0" th:field="${employee.gender}">female<br>
		<input type="submit" value="update"><br>
	</form>
</body>

四、执行修改:

@RequestMapping(value = "/employee", method = RequestMethod.PUT)
public String updateEmployee(Employee employee){
	employeeDao.save(employee);
	return "redirect:/employee";
}

处理静态资源的过程

HttpMessageConverter

一、HttpMessageConverter,报文信息转换器,将浏览器发送过来的请求报文转换为Java对象,或将Java对象转换为响应报文,便于浏览器接收
二、HttpMessageConverter提供了两个注解和两个类型:

  1. @RequestBody:用于将请求报文转换为Java对象
  2. @ResponseBody:将Java对象转换为响应报文
  3. RequestEntity:可以接收整个请求报文,既可以接收请求头,又可以接收请求体
  4. ResponseEntity:加了他之后,可以转换为响应报文

三、新建项目springMVC-demo4

@RequestBody

一、@RequestBody可以获取请求体,需要在控制器方法设置一个形参,使用@RequestBody进行标识,当前请求的请求体就会为当前注解所标识的形参赋值
二、发送请求:

<form th:action="@{/testRequestBody}" method="post">
	用户名:<input type="text" name="username"><br>
	密码:<input type="password" name="password"><br>
	<input type="submit">
</form>

三、服务器接收到请求,请求体会保存在requestBody参数中:

@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String requestBody){
	System.out.println("requestBody:"+requestBody);// requestBody:username=admin&password=123456
	return "success";
}

RequestEntity

RequestEntity封装请求报文的一种类型,需要在控制器方法的形参中设置该类型的形参,当前请求的请求报文就会赋值给该形参,可以通过getHeaders()获取请求头信息,通过getBody()获取请求体信息

@RequestMapping("/testRequestEntity")
public String testRequestEntity(RequestEntity<String> requestEntity){
	System.out.println("requestHeader:"+requestEntity.getHeaders());
	System.out.println("requestBody:"+requestEntity.getBody());
	return "success";
}
// 输出结果: requestHeader:[host:"localhost:8080", connection:"keep-alive", content-length:"27",cache-control:"max-age=0", sec-ch-ua:"" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"", sec-ch-ua-mobile:"?0", upgrade-insecure-requests:"1", origin:"http://localhost:8080", user-agent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/90.0.4430.93 Safari/537.36"] requestBody:username=admin&password=123

HttpServletResponse响应数据

通过控制器处理请求时,对浏览器的请求进行响应有两种方式:响应浏览器一个完整的页面,实现页面跳转,即转发和重定向;响应浏览器数据,以前我们使用HttpServletResponse响应数据:

@RequestMapping("/testResponse")
public void testResponse(HttpServletResponse response) throws IOException {
	response.getWriter().print("hello,response");
	// print中的内容直接作为响应报文的响应体响应到浏览器中,响应体是什么我们在浏览器中看到的就是什么
}

结果:浏览器页面显示hello,response

@ResponseBody

@ResponseBody用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体响应到浏览器

@RequestMapping("/testResponseBody")
@ResponseBody
public String testResponseBody(){
	return "success";// 加了@ResponseBody注解,这个success就不再是视图名称了,而是响应体内容
}

结果:浏览器页面显示success

SpringMVC处理json

一、我们上一节响应到浏览器的是个普通字符串,所以可以将响应内容直接在浏览器中展示,如果我响应的是一个对象呢,那么需要将对象转换成JSON对象,然后响应JSON对象,JSON是前后端数据交互的一种格式。新建一个对象src/main/java/com/atguigu/mvc/bean/User.java

public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private String sex;
    public User(Integer id, String username, String password, Integer age, String sex) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
        this.sex = sex;
    }
    public User() {}
    public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
    public String getUsername() {return username;}
    public void setUsername(String username) {this.username = username;}
    public String getPassword() {return password;}
    public void setPassword(String password) {this.password = password;}
    public Integer getAge() {return age;}
    public void setAge(Integer age) {this.age = age;}
    public String getSex() {return sex;}
    public void setSex(String sex) {this.sex = sex;}
}

二、@ResponseBody处理json的步骤:

  1. POM.xml中导入jackson的依赖
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>2.12.1</version>
</dependency>
  1. 在SpringMVC的核心配置文件springMVC.xml中开启mvc的注解驱动:<mvc:annotation-driven />。此时在HandlerAdaptor中会自动装配一个消息转换器:MappingJackson2HttpMessageConverter,可以将响应到浏览器的Java对象转换为Json格式的字符串
  2. 在处理器方法上使用@ResponseBody注解进行标识,并将Java对象直接作为控制器方法的返回值返回,就会自动转换为Json格式的字符串
@RequestMapping("/testResponseUser")
@ResponseBody
public User testResponseUser(){
	return new User(1001,"admin","1",23,"男");
}

浏览器的页面中展示的结果:{"id":1001,"username":"admin","password":"123456","age":23,"sex":"男"}

SpringMVC处理ajax

一、Ajax的特点:不刷新页面与服务器进行交互,所以不能用转发和重定向,只能用响应浏览器数据
二、点击后发送ajax请求:

<div id="app">
	<a th:href="@{/testAjax}" @click="testAjax">testAjax</a><br>
</div>
<script type="text/javascript" th:src="@{/static/js/vue.js}"></script>
<script type="text/javascript" th:src="@{/static/js/axios.min.js}"></script>
<script type="text/javascript">
	var vue = new Vue({
		el:"#app",
		methods:{
			testAjax:function (event) {
				axios({
					method:"post",
					url:event.target.href,
					params:{
						username:"admin",
						password:"1"
					}
				}).then(function (response) {
				alert(response.data);
			});
			event.preventDefault();
		}
	}
});
</script>

三、控制器中的方法

@RequestMapping("/testAjax")
@ResponseBody
public String testAjax(String username, String password){
	System.out.println("username:"+username+",password:"+password);
	return "hello,ajax";
}

@RestController注解

@RestController注解是springMVC提供的一个复合注解,标识在控制器的类上,就相当于为类添加了@Controller注解,并且为其中的每个方法添加了@ResponseBody注解

ResponseEntity

ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文

文件上传和下载

下载

使用ResponseEntity实现下载文件的功能:

  1. 点击页面链接进行下载:<a th:href="@{/testDown}">下载1.jpg</a><br>
  2. 映射文件:
@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
	// ResponseEntity<byte[]>表示响应到浏览器的响应报文
    //获取ServletContext对象,ServletContext对象表示我们当前的整个工程
    ServletContext servletContext = session.getServletContext();
    //获取服务器中文件的真实路径
    // getRealPath()获取当前服务器的部署路径,就是我们这个工程部署到tomcat服务器上的路径
    // getRealPath("/static/img/1.jpg")获取文件/static/img/1.jpg在服务器的路径
    String realPath = servletContext.getRealPath("/static/img/1.jpg");
    System.out.println(realPath);
    //创建输入流,文件不管上传还是下载,都是一个复制的过程,复制过程:先读再写
    InputStream is = new FileInputStream(realPath);
    //创建字节数组
    // is.available()获取当前输入流所对应的文件的所有字节数
    byte[] bytes = new byte[is.available()];
    //将流读到字节数组中
    is.read(bytes);// 这行代码执行完毕后,数组中存放的是文件所对应的所有字节,那么我将数组响应到浏览器,就是我要下载的文件
    // 将要响应的数据转换成ResponseEntity<byte[]>结构
    //创建HttpHeaders对象设置响应头信息
    MultiValueMap<String, String> headers = new HttpHeaders();
    //设置要下载方式以及下载文件的名字,除了1.jpg是下载的文件名,可以改,其他都是固定写法不能改
    // filename=为下载的文件设置的默认名
    headers.add("Content-Disposition", "attachment;filename=1.jpg");
    //设置响应状态码
    HttpStatus statusCode = HttpStatus.OK;
    //创建ResponseEntity对象
    // bytes当前我们要下载的文件的所有字节,即响应体
    ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
    //关闭输入流
    is.close();
    return responseEntity;
}

上传

一、在pom.xml中添加依赖:

<dependency>
	<groupId>commons-fileupload</groupId>
	<artifactId>commons-fileupload</artifactId>
	<version>1.3.1</version>
</dependency>

二、文件上传要求form表单的请求方式必须为post,并且添加属性enctype="multipart/form-data"

<!--enctype默认值为:application/x-www-form-urlencoded,表示以key=value&key=value的形式传输数据到服务器
enctype="multipart/form-data"表示以二进制形式传输数据到服务器
-->
<form th:action="@{/testUp}" method="post" enctype="multipart/form-data">
    头像:<input type="file" name="photo"><br>
    <input type="submit" value="上传">
</form>

三、SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息,包括我们要进行的操作和我们要上传的文件。上传的文件不能直接转换成MultipartFile对象,需要在SpringMVC的配置文件springMVC.xml中配置文件上传解析器,将上传的文件封装为MultipartFile:<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
四、控制器方法如下,为了防止文件重命名,上传的文件保存在服务器中都使用UUID作为文件名

	@RequestMapping("/testUp")
    public String testUp(MultipartFile photo, HttpSession session) throws IOException {
        // photo.getName():获取当前表单元素的name属性值
        String fileName = photo.getOriginalFilename();//获取上传的文件的文件名
        //获取上传的文件的后缀名
        // fileName.lastIndexOf("."):获取文件名的后缀名前面的.所在索引
        // fileName.substring(索引):截取索引后面的内容并返回
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        //将UUID作为文件名
        // UUID.randomUUID().toString():随机生成一个UUID
        // 生成的UUID有-,replaceAll("-",""):将所有的-都删了
        String uuid = UUID.randomUUID().toString().replaceAll("-","");
        //将uuid和后缀名拼接后的结果作为最终的文件名
        fileName = uuid + suffixName;
        //把上传的文件保存到(上传到)服务器中photo目录下,通过ServletContext获取服务器中photo目录的路径
        ServletContext servletContext = session.getServletContext();
        String photoPath = servletContext.getRealPath("photo");
        File file = new File(photoPath);
        //判断photoPath所对应路径是否存在
        if(!file.exists()){
            //若不存在,则创建目录
            file.mkdir();
        }
        // File.separator文件分隔符
        String finalPath = photoPath + File.separator + fileName;
        //上传文件:photo.transferTo(要上传的地址);
        photo.transferTo(new File(finalPath));
        return "success";
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值