跨域
什么跨域:
AJAX 跨域访问是用户访问A网站时所产生的对B网站的跨域访问请求均提交到A网站的指定页面
由于安全方面的原因, 客户端js使用xmlhttprequest只能用来向来源网站发送请求,比如在www.readlog.cn下去请求test.readlog.cn的数据,都是不行的
解决方法:
一:请求头解决
请求端
<%-- Created by IntelliJ IDEA. User: wish Date: 2020/2/6 Time: 16:08 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>模拟跨域_请求头解决</title> <script type="text/javascript" src="js/jquery-1.8.3.min.js"></script> <script> $(function(){ $("#button").click(function () { //获取到文本框的值 var username=$("#username").val(); //发送Ajax请求www.a.com的A工程 $.ajax({ url:"http://www.two.com:8080/HeadAServlet", data:{"userName":username}, type:"POST", success:function (result) { alert(result); }, error:function () { alert('系统错误~') } }); }); }); </script> </head> <body> <input type="text" name="username" id="username"/> <br/> <input type="button" id="button" value="请求"/> </body> </html>
响应端
package com.wish; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/HeadAServlet") public class HeadAServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //設置請求頭 resp.setHeader("Access-Control-Allow-Origin", "*"); //获取数据 String userName =req.getParameter("userName"); System.out.println("接受的数据:"+userName); resp.setContentType("text/html;charset=utf-8"); resp.getWriter().write("服务器正确接收到数据"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } }
二:JSONP解决
请求端
<%-- Created by IntelliJ IDEA. User: wish Date: 2020/2/6 Time: 16:08 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>模拟跨域_JSONP解决</title> <script type="text/javascript" src="js/jquery-1.8.3.min.js"></script> <script> $(function(){ $("#button").click(function () { //获取到文本框的值 var username=$("#username").val(); //发送Ajax请求www.a.com的A工程 $.ajax({ url:"http://www.two.com:8080/JSONPServlet?userName="+username+"", type:"GET", jsonp:"jsonpCallBack", //回调函数 dataType:"JSONP", success:function (result) { alert(result); }, error:function () { alert('系统错误~') } }); }); }); </script> </head> <body> <input type="text" name="username" id="username"/> <br/> <input type="button" id="button" value="请求"/> </body> </html>
响应端
package com.wish; import com.alibaba.fastjson.JSON; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/JSONPServlet") public class JSONPServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取数据 resp.setContentType("text/html;charset=utf-8"); String userName =req.getParameter("userName"); System.out.println("接受的数据:"+userName); //接受Ajax传递的数据 String jsonpCallBack = req.getParameter("jsonpCallBack"); System.out.println("jsonpCallBack:"+jsonpCallBack); String success = JSON.toJSONString("服务器正确接收到数据"); //响应结果,数据必须为JSON格式 resp.getWriter().write(jsonpCallBack+"("+success+")"); } }
三:HTTPClient解决
请求端
页面
<%-- Created by IntelliJ IDEA. User: wish Date: 2020/2/6 Time: 16:11 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>模拟跨域_HTTPClient解决</title> <script type="text/javascript" src="js/jquery-1.8.3.min.js"></script> <script> $(function () { $("#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('系统错误~') } }); }); }) </script> </head> <body> <input type="text" name="username" id="username"/> <br/> <input type="button" id="button" value="请求"/> </body> </html>
后台
package com.wish; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/BServlet") public class BServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //内部通过HTTPClient进行转发 //构建一个连接 CloseableHttpClient client = HttpClients.createDefault(); //构建请求 HttpGet get=new HttpGet("http://www.two.com:8080/HTTPClientServlet?userName="+request.getParameter("username")); //发送请求 CloseableHttpResponse httpResponse = client.execute(get); //获取返回结果 String result = EntityUtils.toString(httpResponse.getEntity()); //将A工程响应结果给页面 response.getWriter().write(result); } }
响应端
package com.wish; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/HTTPClientServlet") public class HTTPClientServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取数据 resp.setContentType("text/html;charset=utf-8"); String userName =req.getParameter("userName"); System.out.println("接受的数据:"+userName); resp.setContentType("text/html;charset=utf-8"); resp.getWriter().write("服务器正确接收到数据"); } }
表单重复提交
什么是表单的重复提交
在表单提交到一个Servlet ,而Servlet 又通过请求转发的方式响应一个JSP(HTML) 页面, 这个时候地址栏显示的是Servlet的路劲,
在刷新页面,这个时候会造成表单的重复提交。
在响应页面没有到达时候重复点击“提交按钮”,会造成表单的重复提交。
你在响应页面时候点击返回,在点击提交按钮的时候,会造成表单的重复提交。
解决方法
页面
<%-- Created by IntelliJ IDEA. User: wish Date: 2020/2/6 Time: 16:08 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <script type="text/javascript" src="js/jquery-1.8.3.min.js"></script> <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> </head> <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> </html>
生成前台的Token令牌
package com.wish; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.UUID; @WebServlet("/TokenServlet") public class TokenServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } 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); } }
后台服务
package com.wish; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/FormServlet") public class FormServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } 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.setContentType("text/html;charset=utf-8"); //返回数据 response.getWriter().write("success"); } }