一、入门案例
像一些点赞评论功能,需要发送请求与数据库交互而不用跳转更不用牺牲整个页面重新加载,我们就可以用ajax,前端向后台发送一个http请求,然后接受返回的参数,配合jq实现局部刷新。
首先看看ajax的一个最简单的例子:
$.ajax({
url: "login/loginAjax",
data: {
username:$("input[name='username']").val(),
password:$("input[name='password']").val()
},
type: "POST",
async : false,
cache: false,
dataType: 'text',
success: function (data) {
alert(data);
},
error: function () {
alert("程序出错。。。");
}
});
url:你发送的请求
type:请求类型,这也是一个http请求,向普通表单提交,超链接一样。
cache: 是否缓存,作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取。用的少,一般是false,
data: 这里是向后台传值,注意最后一个值不要有逗号,data里的值最后 会封装成FormData对象传给后台,选填。
success: 后台返回数据后会调用这个方法,方法参数data是传过来的对象(可以任意取名)
dataType:返回值类型,最常见的就是text和json
error:请求出错调用的方法。
async: 是否异步,比如你想等success方法被调用后再执行ajax后面的语句,就要用flase,如果你想执行ajax后,后面的代码可以直接执行,等到回调成功后再执行success方法,那就用true开启异步。
如果第一次学只需要照着做就OK(后面有ssm和ssh具体例子)。
二、ssm中简单的例子
2.1、向后端传值
2.1.1 简单例子
前端页面:一个form表单里面包含两个输入框和提交按钮,给button绑定了textAjax()方法
<form>
<label>用户名</label><br>
<input id="aaa" name="username" type="text"><br>
<label>密码</label><br>
<input name="password" type="password"><br>
<input type="button" value="提交" onclick="testAjax()">
</form>
ajax:点击button后执行textAjax()方法,前端向用户发送一条请求,传入了两个参数
<script type="text/javascript">
function testAjax(){
$.ajax({
url: "login/loginAjax",
data: {
username:$("input[name='username']").val(),
password:$("input[name='password']").val()
},
type: "POST",
async : false,
cache: false,
dataType: 'text',
success: function (data) {
alert(data);
},
error: function () {
alert("程序出错。。。");
}
});
}
</script>
Controller层:ssm取到两个参数,执行业务逻辑后返回“abc”,前端执行success()回调函数,其实一般是在success这个方法里通过jq变更局部dom
@Controller
@RequestMapping("/login")
public class LoginController {
@RequestMapping("/loginAjax")
@ResponseBody
public String loginAjax(@Param("username")String username,@Param("password")String password){
System.out.println(username+"--"+password);
return "abc";
}
}
但是当表单提交的内容变多,很显然这样就不便于开发,所有ajax提供了一个更好的方法向后端传递参数
2.1.2、序列化参数
通常我们提交(使用submit button)时,会把form中的所有表格元素的name与value组成一个queryString,提交到后台。这用jQuery的方法来说,就是serialize。
前端form:为form添加有个id
<form id="form1">
<label>用户名</label><br>
<input id="aaa" name="username" type="text"><br>
<label>密码</label><br>
<input name="password" type="password"><br>
<label>性别</label><br>
<input type="radio" name="sex" value="1">男
<input type="radio" name="sex" value="0">女<br>
<%--<label>时间</label><br>
<input type="date" name="time" ><br>--%>
<input type="button" value="提交" onclick="testAjax()">
</form>
ajax: 可以看到整个表单就被序列化成了一个对象,注意form表单里的name就必须对应User类里的每一个属性(可以传User类部分属性)
function testAjax(){
var formParam = $("#form1").serialize();//序列化表格内容为字符串
$.ajax({
url: "login/loginAjax",
data: formParam,
type: "POST",
async : false,
cache: false,
dataType: 'text',
success: function (data) {
alert(data);
},
error: function () {
alert("程序出错。。。");
}
});
后台代码不变,只是方法里的参数变成了User user;如果前端表格里的值只对应User里的部分值,那么没有对应上的字段为默认值(空或0),如果前端表格传过来的值(也就是说input的name值)User没有,那就在后端方法参数里不仅加User user,还要加这个参数名。比如User里没有sex,就可以这样写
@RequestMapping("/loginAjax")
@ResponseBody
public String loginAjax(User user,String sex){
System.out.println(">>>>>>>>>>"+user.toString()+"--"+sex);
return "abc";
}
2.1.3、日期文件传递
serialize()方法无法封装日期、文件流是无法被序列化的。我们可以把数据转化成FormData类型。
首先SSM框架中文件上传一定要在SpringMVC配置文件中加入注解,maxUploadSize是最大文件上传大小
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1073741824"></property>
<property name="defaultEncoding" value="utf-8"></property>
</bean>
form代码:enctype="multipart/form-data"一定要写
<form id="form1" enctype="multipart/form-data">
<label>用户名</label><br>
<input id="aaa" name="username" type="text"><br>
<label>密码</label><br>
<input name="password" type="password"><br>
<label>性别</label><br>
<input type="radio" name="sex" value="1">男
<input type="radio" name="sex" value="0">女<br>
<label>时间</label><br>
<input type="date" name="time" ><br>
<label>文件</label><br>
<input type="file" name="file"><br>
<input type="button" value="提交" onclick="testAjax()">
</form>
ajax: contentType: false, processData: false,这两个配置一定要写,具体可以查查,如果需要添加额外参数,用form.append("key",value)添加。
<script type="text/javascript">
function testAjax(){
alert($("input[name='time']").val());
var form = new FormData($('#form1')[0]);//序列化表格内容为字符串
$.ajax({
url: "login/loginAjax",
data:form,
type: "POST",
async : false,
cache: false,
contentType: false,
processData: false,
dataType: 'text',
success: function (data) {
alert(data);
},
error: function () {
alert("程序出错。。。");
}
});
}
</script>
后端代码:文件一定要用MultipartFile
@RequestMapping("/loginAjax")
@ResponseBody
public String loginAjax(User user,MultipartFile file){
System.out.println(">>>>>>>>>>"+user.toString()+"--"+file);
return "abc";
}
User类: 注意Date一定要用注解格式化Date,Date引入的包是java.util.Date
package com.hbust.xiaoyu.bean;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
public class User{
private String username;
private String password;
private int sex;
@DateTimeFormat(pattern ="yyyy-MM-dd")
private Date time;
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 int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", sex=" + sex +
", time=" + time +
'}';
}
}
2.2、返回值
2.1返回一个对象
后端代码:@ResponseBody会自动帮你把返回值封装成json,而不会跳转页面,返回值是User
@RequestMapping("/loginAjax")
@ResponseBody
public User loginAjax(User user, MultipartFile file){
User u=new User();
u.setUsername("aaa");
u.setPassword("aaa");
u.setSex(1);
return u;
}
ajax: 这里的dataType类型是返回值类型,应该是json,返回值会封装成data参数,调用方法如下。
<script type="text/javascript">
function testAjax(){
var form = new FormData($('#form1')[0]);//序列化表格内容为字符串
$.ajax({
url: "login/loginAjax",
data:form,
type: "POST",
async : false,
cache: false,
contentType: false,
processData: false,
dataType: 'json',
success: function (data) {
console.log(data)
alert(data.username);
alert(data.password);
alert(data.sex);
},
error: function () {
alert("程序出错。。。");
}
});
}
</script>
2.1返回一个List
后端返回一个list集合,ajax遍历:
$.each(data,function(index,item){
alert(item.username);
alert(item.password);
alert(item.sex);
})
三、ssh中简单的例子
ssh和ssm几乎是没有区别的,只是ssh不要在配置文件里配置
ajax:data传值和ssm一样,前端表单也是一样,这里就不仔细说了,主要讲重点
$.ajax({
url:'login_add',
data:form
type: 'POST',
dataType: 'json',
async:false,
success: function (data) {
},
error: function () { //失败,回调函数
alert('程序异常!');
}
});
struts.xml:没有页面跳转的result!!!
<action name="Jz_*" class="cn.mrlij.action.JzAction" method="{1}">
</action>
重点在于ssh没有ResponseBody注解,不会帮你把返回值转换成json。方法返回值必须是void,这样就不会跳转。
简单看看下面的例子:
public void getByEid() throws IOException{
String realPath =ServletActionContext.getServletContext() .getRealPath("/admin/cj/img");
ServletActionContext.getResponse().setContentType("text/html;charset=utf-8");
Equipment equipment=equipmentService.selByEid(eid);
String image=equipment.getEqu_image();
/*if(image!=null&&(!image.equals(""))){
equipment.setEqu_image(realPath+"/"+image);
}*/
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.registerJsonValueProcessor(java.util.Date.class, new DateJsonValueProcessor());
jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
jsonConfig.setExcludes(new String[]{"fid"});
JSONArray json=JSONArray.fromObject(equipment,jsonConfig);
ServletActionContext.getResponse().getWriter().write(json.toString());
}
如果只想传text,不要这么麻烦,只有这样写:
ServletActionContext.getResponse().getWriter().write("asdffff");
如果传递list、或者一个对象,就这样写:代码中的user也可以为list
JSONArray json=JSONArray.fromObject(user);
ServletActionContext.getResponse().getWriter().write(json.toString());
但是返回值有Date类型转json、屏蔽外键避免外键循环、就用下面方法:
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.registerJsonValueProcessor(java.util.Date.class, new DateJsonValueProcessor());
jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
jsonConfig.setExcludes(new String[]{"fid"});
JSONArray json=JSONArray.fromObject(equipment,jsonConfig);
ServletActionContext.getResponse().getWriter().write(json.toString());
这里简单说一下为什么要屏蔽外键,一般双向关联都会有,比如类A里面有B类,B类里面有Lis<A>,或者B中有C,C中有List<A>,那么就需要屏蔽外键或者外键的外键,总之不要让他一直循环下去。举个例子:
A: Integer id;String aname;B bid;
B:Integer id;String bname;A aid;
那么封装成json就会:{'id':'0001','aname':'aaa','bid':[{id:'001','bname':'bbb','aid':[{'id':'0011','aname':'asd','bid':[{...}]},{'id':'0012','aname':'dfg','bid':[{...}]}]}]},后面就一直循环。所有你可以清除A中的bid,考虑到bname可能需要,所以可以清除A中bid中的aid。
ssh在接收值得时候也有点区别,如果返回的是一个list,那就和ssm一样遍历取值.如果返回的是对象,区别在于:
SSM:
success: function (data) {
alert(data.username);
alert(data.password);
alert(data.sex);
},
SSH:
success: function (data) {
alert(data[0].username);
alert(data[0].password);
alert(data[0].sex);
},