JavaWeb学习笔记八:Ajax学习,使用Ajax引擎访问服务器,以及Servlet技术中乱码问题的再梳理

1. JavaWeb学习笔记八:Ajax学习

1.1. 同步和异步理解

  • 同步:一般出现在进程和线程里面,比如一个进程需要需要另一个进程的数据才能继续执行,那么该进程只能等待另一个进程执行完后才能执行,这就是同步,在网页上的现象有:点击一个连接后只有该连接响应了才能点击其他链接。
  • 异步:异步和同步相反,就是该进程不需要等待另一个进程执行完,你可以继续执行其他事项,在网页上的现象有:当点击一个连接后,你不需要等待响应,你还可以点击其他连接。网页不会因为没有响应请求而卡死。

1.2. Ajax在web工程中充当的角色

  • Ajax在web工程中充当中间人的角色,比如用户提交一个连接,并没有直接提交给浏览器,而是提交给了Ajax引擎,Ajax引擎再提交给浏览器,在这里充当了一个中介角色,这样做的好处就是实现了异步操作 ,用户提交连接后可以不必等待响应,可以再点击其他链接。Ajax通常被叫做异步访问,也被叫做局部刷新

1.3. 由js实现Ajax的创建

  • 用js实现Ajax需要5个步骤:

第一: 创建Ajax引擎对象----所有操作都是通过引擎对象的。

第二: 绑定监听—监听服务器是否已经返回相应数据。

第三: 绑定地址。

第四: 发送请求。

第五: 接收相应数据。

1.3.1. 创建Ajax引擎对象
function fn1(){
    //1.创建ajax引擎对象----- 所有的操作都是通过引擎对象
    var xmlHttp =new XMLHttpRequest();
    //2.绑定监听----监听服务器是否已经返回相应的数据
    xmlHttp.onreadystatechange=function(){
        if(xmlHttp.readyState==4&&xmlHttp.status==200){
             //5.接收相应数据
        	 var res=xmlHttp.responseText;
       		 alert(res);
        }

    }
    //3.绑定地址,true表示异步,false表示同步操作
    xmlHttp.open("GET","/WEB/ajaxServlet",true)//4.发送请求
    xmlHttp.send();
}
1.3.2. 不使用Ajax访问服务器和使用Ajax访问服务器的区别

JavaWeb学习笔记八:Ajax学习,使用Ajax引擎访问服务器,以及Servlet技术中乱码问题的再梳理

1.3.3. 乱码问题再理解
  1. 参考文章:乱码原因与解决
  2. Tomcat服务器的默认解码方式是“ISO-8859-1"标准,因为和计算机最基础的表示单位一致,又因为是单字节编码,造成很多协议默认使用该编码。
  3. 一般jsp提交的数据是通过UTF-8编码集来编码的,当提交到tomcat服务器时,Tomcat服务器的解码是通过ISO-8859-1默认编码集来解码,由于ISO8859-1的编码集合UTF-8的编码集很多不同,就会出现乱码。也就是说通过request.getParamater()获取的汉字会变成乱码。要想解决这个乱码就要改变获取值的解码格式,先把request获取的值用ISO8859-1编码,再用UTF-8字符集解码。就解决了问题。
  4. post提交表单解决方法:
request.setCharacterEncoding("UTF-8");
  • 用着一句就行了,因为post提交是一种二进制形式提交的。就缺少一个字符集。
  1. 用get的提交方式:
username=new String(username.getBytes("ISO-8859-1"),"UTF-8");
  • 用String类的编解码方式
  1. 对于响应,需要设置两个参数,一个是服务器输出时用什么编码,浏览器解析用什么编码。
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");

1.4. 由JQuery实现Ajax异步校验

  • 使用JQuery实现get异步访问服务器端
function fn1(){
    //get异步访问
    $.get(
    	"xxxx",//url地址
        {"name":"张三","age":25},
        function(data){
            //执行成功后函数回调
            alert(data.name);
        },
        "json"
    );
}
  • 使用JQuery实现post异步访问服务器
function fn2(){
    //post异步访问
    $.post(
    "xxxx",//url地址
    {"name":"李四","age":25}, //请求参数
    function(data){ //执行成功后的回调函数
        alert(data.name);
    },
     "json"
	);
}
  • 使用JQuery实现Ajax异步访问服务器
function fn3(){
    $.ajax({
       url:"xxxxx",
       async:true,//是否异步
       type:"post",//提交类型
       data:{"name":"tom","age":18},
       success:function(data){
            alert(data.name);
        },
        error.function(){
        alert("请求失败")},
    dataType:"json"//数据类型   
    });
}

2. 案例一:用ajax引擎访问服务器实现搜索框显示

  1. 前端页面创建搜索显示框
<input id="search" type="text" class="form-control" placeholder="Search" "searchWord(this)">
<div id="showDiv" style="display:none; position:absolute;z-index:1000;background:#fff; width:179px;border:1px solid #ccc;"></div>
<!-- display:none表示不显示出来-->
  1. 用JQuery实现服务器请求
function searchWord(obj){
	//1、获得输入框的输入的内容
    var word = $(obj).val();//注意JQuery和js有些不同,
    //2、根据输入框的内容去数据库中模糊查询---List<Product>
    var content = "";
    $.post(//使用post提交方式访问服务器
        "${pageContext.request.contextPath}/searchWord",
        {"word":word},
        function(data){
            //3、将返回的商品的名称 现在showDiv中					
            if(data.length>0){
                for(var i=0;i<data.length;i++){
                    content+="<div style='padding:5px;cursor:pointer' 'clickFn(this)' 'overFn(this)' 'outFn(this)'>"+data[i]+"</div>";
                }
                $("#showDiv").html(content);
                $("#showDiv").css("display","block");
            }
        },
        "json"
    );	
}
function overFn(obj){
    $(obj).css("background","#DBEAF9");
}
function outFn(obj){
    $(obj).css("background","#fff");
}

function clickFn(obj){
    $("#search").val($(obj).html());
    $("#showDiv").css("display","none");
}
  • obj代表的是鼠标选中的对象。
  1. 后端web层Servlet代码实现调用,json的封装。
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1.获取关键字
		String word=request.getParameter("word");
		//2.查询该关键字的所有商品
		ProductService service=new ProductService();
		List<Object> productList=null;
		try {
			productList=service.findProductByWord(word);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//使用json的转换工具将对象或集合转成json格式的字符串。
		Gson gson=new Gson();
		//封装jison
		String json=gson.toJson(productList);
		System.out.println(json);
		response.setContentType("text/html;charset=UTF-8");
		//服务器将其传递到ajax引擎里面
		response.getWriter().write(json);
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}
  • 注意这里面用了Gson一个google做的工具,用于将获取的值封装成json
  1. dao层实现数据库查询操作
public List<Object> findProductByWord(String word) throws SQLException {
QueryRunner runner=new QueryRunner(DataSourceUtils.getDataSource());
String sql="select * from product where pname like ? limit 0,8";
List<Object> query=runner.query(sql, new ColumnListHandler("pname"),"%"+word+"%");
return query;
}
  • 模糊查询,ColumnListHandler用户返回一个列的值。

3. 案例二:利用Ajax访问服务器,实现注册校验功能

  1. 利用id绑定用户名,利用span标签可以输入html。
<input type="text" class="form-control" id="username" placeholder="请输入用户名">
<span id="usernameInfo"></span>
  1. 用jQuery写post访问服务器
//页面加载完成就执行
	$(function(){
		//为输入框绑定事件
		$("#username").blur(function(){
			//1. 失去焦点获得输入框内容
			var usernameInput=$(this).val();
			//2.去服务端校验该用户名是否存在----ajax
			$.post(
				"${pageContext.request.contextPath}/checkUsername",
				{"username":usernameInput},
				function(data){
					var isExist=data.isExist;
					var usernameInfo="";
					if(isExist){
						usernameInfo="该用户名已经存在"
						$("#usernameInfo").css("color","red");
					}else{
						usernameInfo="该用户可以使用";
						$("#usernameInfo").css("color","green")
					}
					$("#usernameInfo").html(usernameInfo);
				},
				"json"
				);
		});
	});
  1. 后端web层主要是获取ajax提交的参数,然后到数据库查找该参数是否存在。
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//获取要校验的用户名
		String username=request.getParameter("username");
		//传递username到service层
		boolean isExist=false;
		UserService service=new UserService();
		try {
			isExist=service.checkUsername(username);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		response.getWriter().write("{\"isExist\":"+isExist+"}");
	}
  1. dao层用来查询数据库
public Long checkUsername(String username) throws SQLException {
    QueryRunner runner=new QueryRunner(DataSourceUtils.getDataSource());
    String sql="select count(*) from user where username=?";
    Long query=(Long) runner.query(sql, new ScalarHandler(), username);
    return query;
}
  • 这个为什么要返回Long型,我也不清楚。都这样写。有些博客上说,ScalarHandler()虽然返回的是Object型,不过他本身就是Long型。