关于上篇学习链接:SpringMVC框架学习上篇
八.Json交互处理
1.什么是JSON
JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级纯文本的数据交换格式,层次结构简洁清晰,方便人和机器阅读,方便网络传输,使用广泛。
2.JSON和JavaScript的对象的区别
JSON 是 JavaScript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。
JavaScript 对象:
var obj = {a: 'Hello', b: 'World'};
JSON数据:
{"name":"张三","age":3,"sex":"男"}
3.JSON与JavaScript相互转换
将js对象转换成json字符串:
JSON.stringify();
将json字符串转换为js对象
JSON.parse();
4.实例
创建一个module,并添加Web支持,再创建一个该module的Tomcat
然后在index.jsp中创建一个JS脚本:
运行Tomcat_JSON服务器(打开开发者工具F12):
5.Jackson
Java生态圈中有很多处理JSON和XML格式化的类库, 常见的解析器:Jsonlib,Gson,fastjson,Jackson。Jackson是其中比较著名的一个,也比较方便。,Jackson相对来说比较高效,在项目中主要使用Jackson进行JSON和Java对象转换,下面通过实例来学习学习。
JsonDemo项目结构:
在pom.xml中导入Jackson的Maven:
<dependencies>
<!-- 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>
</dependencies>
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"
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
"
>
<!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 -->
<context:component-scan base-package="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>
User类:
UserController类:
@ResponseBody表示返回JSON数据(return返回的数据为JSON)
Tomcat_JSON服务器导入一下依赖文件
运行(在地址栏输入/json1):
出现乱码,通过@RequestMaping的produces设置编码为UTF-8,内容为Json
再次运行:
- JSON数据乱码的进一步优化
上面的方式每一次都要添加一条属性过于繁琐,我们可以在springmvc的配置文件上添加一段消息StringHttpMessageConverter转换配置。
步骤如下:
在springmvc-servlet.xml中,先导入MVC的头文件:
xmlns:mvc="http://www.springframework.org/schema/mvc"
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
再配置StringHttpMessageConverter:
<!--解决JSON乱码问题-->
<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属性再运行一次:
- @RestController标签的使用
在前面每一个方法前面都要加一个@ResponseBody表示返回的内容为JSON,每创建一个返回JSON的方法都要添加过于繁琐,可以在类的前面加上@RestController,这样表示该类里面所有的方法都只会返回json 字符串。
再次运行:
- 集合类型的JSON
在UserController类中新增一个json2方法,具体代码如下:
运行效果(在地址栏处输入/json2):
- 时间类型的JSON
运行效果(在地址栏处输入/json3):
上面数字是1970年1月1日到当前日期的毫秒数。
可以通过SimpleDateFormat 来自定义时间类型:
运行效果(在地址栏处输入/json4):
如果上面的操作经常使用的话我们可以封装成工具类,使用的时候调用即可:
创建一个Utils文件,并在该文件下创建一个JsonUtils类:
JsonUtils代码如下:
UserController中新增一个json5方法:
运行效果(在地址栏处输入/json5):
6.FastJson的使用
fastjson.jar是阿里开发的一款专门用于Java开发的包,可以方便的实现json对象与JavaBean对象的转换,实现JavaBean对象与json字符串的转换,实现json对象与json字符串的转换。实现json的转换方法很多,最后的实现结果都是一样的。
导入FastJson的依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>
fastjson 三个主要的类(JSONObject,JSONArray和JSON):
实例练习:
运行效果:
学习链接:
Json详解以及fastjson使用教程
九.Ajax
1.什么是Ajax
AJAX 英文全名为Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),作用是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容,是一种用于创建更好更快以及交互性更强的Web应用程序技术
例子(在搜狗搜索框中输入自己想查找的内容,下方弹出的一些相关问题,就是通过Ajax实现的):
2.Ajax可以做什么
1.注册时,输入用户名自动检测用户是否已经存在
2.登陆时,提示用户名密码错误
3.删除数据行时,将行ID发送到后台,后台在数据库中删除,数据库删除成功后,在页面DOM中将数据行也删除
...等等
3.伪造Ajax
通过前端iframe标签实现(伪造)Ajax效果。
实例1:
创建一个AjaxDemo的Module,添加Web支持:
创建一个ajax-frame.html
给AjaxDemo添加一个Tomcat服务器然后加载该Module:
运行效果:
4. jQuery.ajax
通过 jQuery提供的AJAX 方法,您能够使用 HTTP Get 和 HTTP Post 从远程服务器上请求文本、HTML、XML 或 JSON – 同时您能够把这些外部数据直接载入网页的被选元素中,jQuery Ajax本质就是 XMLHttpRequest(纯JS原生),对他进行了封装,方便调用。
jQuery.ajax配置:
jQuery.ajax(...)
部分参数:
url:请求地址
type:请求方式,GET、POST(1.9.0之后用method)
headers:请求头
data:要发送的数据
contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")
async:是否异步
timeout:设置请求超时时间(毫秒)
beforeSend:发送请求前执行的函数(全局)
complete:完成之后执行的回调函数(全局)
success:成功之后执行的回调函数(全局)
error:失败之后执行的回调函数(全局)
accepts:通过请求头发送给服务器,告诉服务器当前客户端可接受的数据类型
dataType:将服务器端返回的数据转换成指定类型
"xml": 将服务器端返回的内容转换成xml格式
"text": 将服务器端返回的内容转换成普通文本格式
"html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。
"script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式
"json": 将服务器端返回的内容转换成相应的JavaScript对象
"jsonp": JSONP 格式使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数
(1) 实例1:简单的Ajax项目
项目结构:
Web.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 注册DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 关联配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 启动级别-->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- /匹配所有,不包括jso-->
<!-- /*匹配,包括jsp-->
<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="controller"/>
<mvc:default-servlet-handler />
<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文件,并创建一个AjaxController类:
下载Jquery的JS文件:
地址:https://jquery.com/download/
新建一个statics文件然后再建一个Js文件将下载下来的jquery-3.6.0.js导入
index.jsp代码:
导入依赖文件(创建lib):
运行项目:
(2) 实例2:通过Ajax显示用户信息
创建一个pojo文件,在该文件下创建一个User类
在AjaxController类中创建ajax2方法:
创建一个jsp文件并在jsp文件中创建一个userInfo.jsp文件:
创建一个ShowUserInfo类:
运行效果:
点击获取数据:
(3) 实例3:注册提示效果
创建login.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>ajax</title>
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.6.0.js"></script>
<script>
function a1(){
$.post({
url:"${pageContext.request.contextPath}/a3",
data:{'name':$("#name").val()},
success:function (data) {
if (data.toString()=='OK'){
$("#userInfo").css("color","green");
}else {
$("#userInfo").css("color","red");
}
$("#userInfo").html(data);
}
});
}
function a2(){
$.post({
url:"${pageContext.request.contextPath}/a3",
data:{'pwd':$("#pwd").val()},
success:function (data) {
if (data.toString()=='OK'){
$("#pwdInfo").css("color","green");
}else {
$("#pwdInfo").css("color","red");
}
$("#pwdInfo").html(data);
}
});
}
</script>
</head>
<body>
<p>
用户名:<input type="text" id="name" onblur="a1()"/>
<span id="userInfo"></span>
</p>
<p>
密码:<input type="text" id="pwd" onblur="a2()"/>
<span id="pwdInfo"></span>
</p>
</body>
</html>
在AjaxController中创建ajax3方法:
ShowUserInfo类中创建toLogin方法:
运行效果:
出现乱码,在springmvc-servlet.xml中配置解决JSON乱码的配置:
<!--解决JSON乱码问题-->
<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>
再次运行:
(4) 实例4:获取baidu接口Demo
创建getBD.jsp:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>JSONP百度搜索</title>
<style>
#q{
width: 500px;
height: 30px;
border:1px solid #ddd;
line-height: 30px;
display: block;
margin: 0 auto;
padding: 0 10px;
font-size: 14px;
}
#ul{
width: 520px;
list-style: none;
margin: 0 auto;
padding: 0;
border:1px solid #ddd;
margin-top: -1px;
display: none;
}
#ul li{
line-height: 30px;
padding: 0 10px;
}
#ul li:hover{
background-color: #f60;
color: #fff;
}
</style>
<script>
// 2.步骤二
// 定义demo函数 (分析接口、数据)
function demo(data){
var Ul = document.getElementById('ul');
var html = '';
// 如果搜索数据存在 把内容添加进去
if (data.s.length) {
// 隐藏掉的ul显示出来
Ul.style.display = 'block';
// 搜索到的数据循环追加到li里
for(var i = 0;i<data.s.length;i++){
html += '<li>'+data.s[i]+'</li>';
}
// 循环的li写入ul
Ul.innerHTML = html;
}
}
// 1.步骤一
window.onload = function(){
// 获取输入框和ul
var Q = document.getElementById('q');
var Ul = document.getElementById('ul');
// 事件鼠标抬起时候
Q.onkeyup = function(){
// 如果输入框不等于空
if (this.value != '') {
// ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆JSONPz重点☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
// 创建标签
var script = document.createElement('script');
//给定要跨域的地址 赋值给src
//这里是要请求的跨域的地址 我写的是百度搜索的跨域地址
script.src = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd='+this.value+'&cb=demo';
// 将组合好的带src的script标签追加到body里
document.body.appendChild(script);
}
}
}
</script>
</head>
<body>
<input type="text" id="q" />
<ul id="ul">
</ul>
</body>
</html>
在ShowUserInfo中创建toBD方法:
运行效果:
十.拦截器
1.拦截器
- 什么是拦截器
搜狗百科:
java里的拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。在AOP(Aspect-OrientedProgramming)中拦截器用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。
- 拦截器和过滤器的区别
过滤器可以简单理解为“取你所想取
”,忽视掉那些你不想要的东西;拦截器可以简单理解为“拒你所想拒
”,关心你想要拒绝掉哪些东西,比如一个BBS论坛上拦截掉敏感词汇。
2.实例1:自定义拦截器(只需要拦截类实现HandlerInterceptor接口)
新增一个Module,并添加Web支持,再给该Module增加一个Tomcat:
项目结构:
Tomcat(不要忘了导入lib文件):
web.xml配置:
springmvc-servlet.xml配置(拦截器需要配置!):关于这个<mvc:mapping path="/**"/>表签的path,如果值为"/路径1/*",表示拦截路径1下的子路径,但是不包括该路径下的某个路径的子路径,"/路径1/**"才是拦截路径1下的所有路径及其子路径,"/**"表示拦截包括路径及其子路径
controller文件下的InterceptorController.Java:
Interceptor文件下的MyInterceptor.Java:
hello.jsp:
运行效果:
3.实例2:验证用户是否登录 (认证用户)
实现思路:
前端:登入界面,让用户填入账号密码然后点击登入,用户点击登入后将登入的信息存入到session中去,然后跳转到登入成功页面,其他非登入界面通过拦截器判断用户是否登入如果已经登入放行,如果没有登入拦截。
项目结构:
增加login.jsp
增加success.jsp:
修改index.jsp内容:
创建一个LoginInterceptor的拦截器类:
重要代码:
完整代码:
public class LoginInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
// 如果是登陆页面则放行
System.out.println("uri: " + request.getRequestURI());
if (request.getRequestURI().contains("login")) {
return true;
}
HttpSession session = request.getSession();
// 如果用户已登陆也放行
if(session.getAttribute("user") != null) {
return true;
}
// 用户没有登陆跳转到登陆页面
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
return false;
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
增加一个UserController类:
运行效果:
点击登入:
输入账号密码,并点击提交:
在地址栏处输入(localhost:8085/user/jumpSuccess)并跳转:
点击注销,并在地址栏处再输入(localhost:8085/user/jumpSuccess)并跳转:
会发现返回的是登入页面!
十一.文件上传下载
1.准备工作
【0】【0】
文件上传是项目开发中最常见的功能之一 ,springMVC可以很好的支持文件上传,但是SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver。【1】【1】
前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器;
对表单中的 enctype 属性做个详细的说明:
- application/x-www=form-urlencoded:默认方式,只处理表单域中的 value
属性值,采用这种编码方式的表单会将表单域中的值处理成 URL 编码方式。 - multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
- text/plain:除了把空格转换为 "+" 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。
<form action="" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit">
</form>
【2】【2】
一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应。在2003年,Apache Software Foundation发布了开源的Commons FileUpload组件,其很快成为Servlet/JSP程序员上传文件的最佳选择。
- Servlet3.0规范已经提供方法来处理文件上传,但这种上传需要在Servlet中完成。
- 而Spring MVC则提供了更简单的封装。
- Spring MVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolver实现的。
- Spring MVC使用Apache Commons FileUpload技术实现了一个MultipartResolver实现类:CommonsMultipartResolver。因此,SpringMVC的文件上传还需要依赖Apache Commons FileUpload的组件。
2.文件上传
(1) 实例1(文件上传)
创建一个Module,导入Web框架支持,并创建对应Tomcat:
在pom.xml中导入Maven:
<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<!--servlet-api导入高版本的-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
为Module创建Tomcat(加载依赖lib)
web.xml配置:
springmvc-servlet.xml配置:文件上传配置的bean的id必须为multipartResolver!
FileController.java代码:
CommonsMultipartFile 的 常用方法:
- String getOriginalFilename():获取上传文件的原名
- InputStream getInputStream():获取文件流
- void transferTo(File dest):将上传文件保存到一个目录文件中
index.jsp代码:
运行效果:
点击游览,选择devcpp.exe点击打开
然后点击upload进行上传:
(2) 实例2(采用file.Transto 来保存上传的文件)
在FileController中创建fileUpload2方法
index.jsp:
运行效果:
3.文件下载
文件下载步骤:
1、设置 response 响应头
2、读取文件 -- InputStream
3、写出文件 -- OutputStream
4、执行操作
5、关闭流 (先开后关)
实例:
创建statics文件,并将1.jpg图片放入:
在Index.jsp中,添加下载链接:
在FileController中新增downloads方法
运行效果: