HTTP(“跨域问题”和“防止表单重复提交”)
一.跨域问题
  能够正常请求,但是没有办法获取到响应结果
		解决方案一:设置请求头,在请求的资源中设置Access-Control-Allow-Origin请求头
			//3.设置请求头
			response.setHeader("Access-Control-Allow-Origin", "*");
		
解决方案二:.JSONP解决跨域问题
			普通的跨域访问问题,浏览器会进行拦截,凡是src属性的都不会拦截
			ajax:http://www.a.com:8080/a/AServlet
			
			JSONP实现原理:动态加载<script>标签,利用src属性进行服务器资源的访问,但是只支持Get请求
				1.在我们的Ajax请求当中,需要以JSONP方式请求(通过jquery手段,动态生成sript)
		
					jsonp:"代表的时前台传给后台,后台再传递给你    jsonpCallBack"
				
				2.再AJAX请求当中需要将返回的数据格式指定为jsonp
					
					dataType:"JSONP"
				3.JSONP需要以Get请求发送  ?username=zhangsan
				
				
				4.后台需要做的事情:
					1.正常接收数据        
					 
					2.返回数据
						
						前台传递过来的jsonp需要原路返回
String jsonp=request.getP("jsonpCallBack");
						需要将返回的数据转换为JSON   success
						
						response.getWirter.write(jsonp+"("+返回的数据+")");
				
				
				解决方案:
					修改Ajax请求:
						$("#button").click(function () {
							//获取到文本框的值
							var username=$("#username").val();
							//发送Ajax请求www.a.com的A工程
							$.ajax({
								url:"http://www.a.com:8080/a/AServlet?username="+username,
								type:"GET",
								jsonp:"jsonpCallBack",      //回调函数
								dataType:"JSONP",
								success:function (result) {
									alert(result);
								},
								error:function () {
									alert('系统错误~')
								}
							});
						});
					
					更改后台请求,需要将JSONP原路返回
						protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
							//1.接受数据
							String username=request.getParameter("username");
							System.out.println("接受的数据:"+username);
							//接受Ajax传递的数据
							String jsonpCallBack = request.getParameter("jsonpCallBack");
							System.out.println("jsonpCallBack:"+jsonpCallBack);
							String success = JSON.toJSONString("success");
							//2.响应结果,数据必须为JSON格式
							response.getWriter().write(jsonpCallBack+"("+success+")");
							//3.设置请求头
							/*response.setHeader("Access-Control-Allow-Origin", "*");*/
						}
		三.使用HTTPClient解决:就是不通过浏览器发送请求
			B工程的页面发送的Ajax没有办法请求到A工程,因为浏览器会拦截,走后台,后台通过HTTPClient请求请求到A工程,获取到响应结果
			
			
			1.B工程的Bindex.jsp页面请求到B工程的Servlet
				$("#button").click(function () {
					//获取到文本框的值
					var username=$("#username").val();
					//发送Ajax请求www.a.com的A工程
					$.ajax({
						url:"BServlet?username="+username,
						type:"GET",
						success:function (result) {
							alert(result);
						},
						error:function () {
							alert('系统错误~')
						}
					});
				});
			2.B工程的BServlet去模拟HTTP请求到A工程
				protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
					//内部通过HTTPClient进行转发
					//构建一个连接
					CloseableHttpClient client = HttpClients.createDefault();
					//构建请求
					HttpGet get=new HttpGet("http://www.a.com:8080/a/AServlet?username="+request.getParameter("username"));
					//发送请求
					CloseableHttpResponse httpResponse = client.execute(get);
					//获取返回结果
					String result = EntityUtils.toString(httpResponse.getEntity());
					//将A工程响应结果给页面
					response.getWriter().write(result);
				}
			3.A工程处理请求
				protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
					//1.接受数据
					String username=request.getParameter("username");
					System.out.println("接受的数据:"+username);
					//2.响应结果
					response.getWriter().write("success");
					
					
				}
			
二.防止表单重复提交
		1.网络延迟,再网络延迟时间内,频繁的提交表单
			只能提交一次,监控表单的提交事件,通过一个boolean类型的变量来区分已经点击过还是没有点击,如果已经点击过,表单就不提交,没有点击过再提交
			
		
		
		2.重新加载或者后退页面
			思路如下:在我访问登录页面的时候,创建一个   Token令牌(当作一个标识) ,保存到session当中,然后再表单提交的时候将令牌一起提交
			后台Servlet去判断session当中的令牌和表单提交的令牌是否相等,如果相等代表正常提交(session清空),如果不相等,代表非正常提交
			
			
			Form.jsp页面
				<body>
					<form action="FormServlet" onsubmit="return formSubmit()" method="post">
						<input type="hidden" id="hiddenToken" name="formToken"/>
						<input type="text" name="username"/>
						<input type="submit" value="提交"/>
					</form>
				</body>
				
				
				<script type="text/javascript">
					//创建一个变量   false代表没有点击过,true代表已经点击过
					var flag=false;
					function formSubmit() {
						if(!flag){      //取反值为false
							flag=true;
							return true;
						}else {
							return false;
						}
					}
					$(function () {
						//生成令牌
						$.ajax({
							url:"TokenServlet",
							type:"POST",
							success:function (token) {
								$("#hiddenToken").val(token);
							}
						})
					})
				</script>
			
			TokenServlet:
				protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
					//生成令牌
					String token = UUID.randomUUID().toString();
					//令牌保存到session当中
					request.getSession().setAttribute("sessionToken",token);
					//响应
					response.getWriter().write(token);
				}
				
			FormServlet:
				protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
					//验证令牌
					//获取页面提交的隐藏域数据
					String formToken = request.getParameter("formToken");
					//获取Session中的Token
					String sessionToken = (String)request.getSession().getAttribute("sessionToken");
					//如果页面中获取的和session中不一致,代表已经提交过了,不要重复提交
					if(!formToken.equals(sessionToken)){
						response.getWriter().write("不要重复提交~");
						return;
					}
					//接收数据
					String username = request.getParameter("username");
					System.out.println("接收的数据为:"+username);
					//必须将token清空,不然永远是一致的
					request.getSession().removeAttribute("sessionToken");
					try {
						//模拟网络延迟
						Thread.sleep(300);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					//返回数据
					response.getWriter().write("success");
				}
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号