通过上面的学习我们知道,默认情况下无论是Spring MVC还是SpringBoot返回的都是现在都是前后端分离的,后端只需要进行返回数据给前端数据即可
1)向浏览器返回一个HTML界面
请求参数的数据类型Contnt-Type:text/html;charset=utf-8
@RequestMapping("/CSS") @ResponseBody public String GetHTML(String name) { return "<h1>你好"+name+"</h1>"; }
2.给浏览器返回一个JSON格式的数据:
浏览器上面输入:localhost:8080/JS?name=李佳伟
{"currentTime":"2022-07-17T12:30:34.76","name":"李佳伟"}@RequestMapping("/JS") @ResponseBody public Object GetJson(String name) { HashMap<String,Object> map=new HashMap<>(); map.put("name",name); map.put("currentTime", LocalDateTime.now()); return map; }
@Controller public class UserController { @RequestMapping("/Java100") @ResponseBody public void run(String username,String password,Integer ClassID,Integer UserID,HttpServletResponse resp) throws IOException { ObjectMapper objectMapper=new ObjectMapper(); User user=new User(); user.setUserID(UserID); user.setClassID(ClassID); user.setUsername(username); user.setPassword(password); resp.setContentType("application/json;charset=utf-8"); String html= objectMapper.writeValueAsString(user); resp.getWriter().write(html); } }
实现一个简单的计数器:
注意后端最好要针对前端的参数要做一个参数校验,因为如果前端传递过来参数如果是null,那么最终两个null值是不可以进行相加的;
1)上面我们使用form表单给服务器发送一个GET请求的时候,我们使用Fidder抓包的结果是:自定义的参数放到了URLquerystring里面:
2)当我们使用form表单发送一个POST请求的时候:请求的数据直接放在body里面了
现在我们进行修改一下博客系统的登录的前端页面:
1)小技巧:ctrl+a进行全选,然后ctrl+c进行复制,然后在进行点击SpringBoot项目里面的resource目录下的static目录,在按下crtl+v进行粘贴;
2)jquery.getJSON("请求的地址url",{请求的参数},function(data,status){},请求成功之后的回调函数);
前端代码:通过AJAX发送HTTP请求:
有时候前端代码修改之后不会生效,我们只需要把target目录直接进行删除,重新启动程序
1)注意我们一定要在方法体内部获取UserName和Password的控件,获取控件里面的内容;
2)注意括号的范围不要写错,看看下面Spring自动判空的一些类;
3)因为在之前不同的浏览器是由不同的浏览器厂商去写的,不同的浏览器厂商引擎可能是不一样的,微软设计的是IE,火狐浏览器,搜狗浏览器,也就是说自己可以设计自己的一个JS行为,所以说在早期的时候,你写的JS代码在谷歌可以运营,在火狐底下可以运行,但是在IE浏览器上不可以运行,因为不同的开发厂商有自己的行为,可以不遵循一些设计规范,不同的浏览器会写不同的JS代码;
4)jQuery本身又是一个门面模式,底层可以有不同的实现,不同的厂商可能会有不同的实现,用户的代码写jQuery代码的时候只是写一份,然后jQuery()会根据底层浏览器的不同,因为他是可以拿到浏览器的一个标识的,那么我会按照底层浏览器标识的不同从而生成不同的代码,但是对于用户是啥也感知不到的,用户在写代码的时候只需要会JQuery的代码就可以,兼容性只是有我们的JQuery()来进行自适应的,但是后来浏览器都遵循了一定的规范;
我们可以自动在JS代码中写一个mysub()函数,来执行我们自动写的一部分逻辑
public static boolean hasLength(@Nullable String str) { return str != null && !str.isEmpty(); }
let button=document.querySelector("#submit"); button.onclick=function() { //1先拿到用户名和密码控件iput1和input2都是id属性 var username=jQuery("#input1"); var password=jQuery("#input2"); console.log(username.val()); console.log(password.val()); //jQuery里面填写的是id属性,我们可以通过username.val可以得到输入框里面的内容 // 2进行非空校验 if(jQuery.trim(username.val())=="") { alert("请先输入用户名"); username.focus();//光标设置到用户名输入框 return; } if(jQuery.trim(username.val())=="") { alert("请先输入密码"); username.focus(); return; } // 3发送ajax请求和后端进行交互 jQuery.getJSON("/login", {"username":jQuery.trim(username.val()), "password":jQuery.trim(password.val()),//trim方法就是去掉里面的空格 },function(data){ if(data!=null&&data.succ==200) { console.log("后端接口访问成功"); if(data.state==1) { alert("登陆成功"); }else{ alert(data.message); } }else{ console.log("后端接口访问失败"+data.succ); } }); //第一个参数表示请求的地址,第二个参数表示请求的参数,第三个参数表示服务器端返回的一个回调函数 }
或者通过这种方式给后端发送AJAX:
<input type="text" id="username"><div>用户名</div> <input type="text" id="password"><div>密码</div> <input type="button" value="开始进行登陆" id="Dclick">
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script> <body> <script> let button=document.querySelector("#Dclick"); button.onclick=function(){ var username=jQuery("#username"); var password=jQuery("#password"); console.log(username.val()); console.log(password.val()); if(jQuery.trim(username.val())==""){ alert("请输入用户名"); username.focus(); return; } if(jQuery.trim(password.val())==""){ alert("请输入密码"); password.focus(); return; } jQuery.ajax({ url:"hello", type:"POST", data:{ "username":username.val(), "password":password.val() }, success:function(result,status){ console.log(result); console.log(status); } }); }
后端代码:
@Controller public class UserController{ @RequestMapping("/hello") @ResponseBody public HashMap<String,Object> Login(String username,String password){ HashMap<String,Object> result=new HashMap<>(); int state=200;//这个表示如果state=200表示访问这个方法是成功的 int data=-1;//最终我们要在前端进行参数校验,data=1说明登录成功,data=-1说明登录失败 String message=""; if(StringUtils.hasLength(username)&&StringUtils.hasLength(password)){ //此时发现username不为空,password不为空,况且username和password都等于特定的值,那么说明登陆成功 if(username.equals("李佳伟")&&password.equals("12503487")){ //说明用户名密码匹配登陆成功 data=1; message="登陆成功"; }else{ //说明用户名密码不匹配,登陆失败 message="用户名或者密码失败"; } }else{ //说明前端传递的username或者password等于空 message="前段传递的用户名或者密码为空"; } result.put("state",state); result.put("data",data); result.put("message",message); return result; } }
1)我们可以进行打断点进行调试,比如说咱们输入了用户名和密码之后,点击提交,就会自动来到断点位置,来到了结果;
2)我们可以在Watch里面输入我们要观察的值比如说我输入了一个data就会显示data具体的值
3)我们还可以点击Watch:输入JSON.parse(result),JSON.stringfy(result),就可以把result转化成JSON格式的数据,前提必须是我们输入用户名和密码点击提交之后获取到返回相应的数据,回调函数返回的是一个字符串之后,才可以把返回的数据转化成JSON格式的字符串,contentType:application/json;charset=utf-8;
JSON.stringify 方法用于将 JavaScript 值转换为 JSON 字符串,一般回调函数data传输回来的值是一个JSON格式的字符串;
JSON.parse() 方法将JSON数据转换为 JavaScript 对象;
1)application/x-www-urlencoded username="aaa"&password="bbb" 2)application/json;charset=utf-8 data:JSON.stringfy({"username":username,"password":password});
1)假设前端给后端传递的格式数据是application/json;charset=utf-8,只写JSON.stringify,键值对字符串还是不可以的,必须要指定前端向后端传递的格式的数据是什么也就是说必须要写上ContentType,一定要指定ContentType和JSON.stringfy操作把JSON格式对象转化成JSON格式的字符串的操作一个不能少;
2)后端代码框架:
2.1)先看看用户名和密码是否为空,不为空在进行下一步,判断一下用户名和密码是否匹配,匹配登陆成功,不匹配登陆失败;
2.2)如果为空直接登陆失败:
这里面要注意一个问题在Spring里面通过resp.setContentType进行设置是不会进行生效的:
前端代码: let button=document.querySelector("#submit"); let username=document.querySelector("#input1"); let password=document.querySelector("#input2"); button.onclick=function(){ // console.log(username.value); // console.log(password.value); if(username.value==""||password.value=="") { alert("当前的用户名或者密码是空"); return; } $.ajax({ type:"GET", url:"login?"+"username="+username.value+"&password="+password.value, success:function(data,status) { console.log(data); console.log(status); } }); } 后端代码: @Controller public class UserController { @RequestMapping(value="/login",produces = "text/html;charset=utf-8") @ResponseBody public String start(String username, String password, HttpServletResponse resp) throws IOException { return "<h1>"+username+""+password+"</h1>"; } @RequestMapping("/cat") @ResponseBody public String start(String username,String password) { return username+password; } }
SpringMVC中Controller处理response.setContentType() - 知乎
总结:想要ajax发送JSON格式的数据,上面写的JSON格式的数据两者缺一不可
请求转发和请求重定向
1)return不光可以返回一个视图,还可以实现跳转,跳转的方式有两种:请求转发和请求重定向,既然是实现跳转,那么返回的就是一个页面,就不能加上@ResponseBody注解;
2)forward是请求转发:是服务器干的,一次请求;
服务器返回的格式的数据就是text/html;charset=utf-8,返回的就是一个完整的HTML
3)redirect是请求重定向:是客户端自己干的,客户端进行了两次HTTP请求,客户端第一次来到服务器这里的时候,服务器会返回一个302响应,并告知服务器你来错地方了,下次你去我所指定的地方吧;
//4这是请求重定向: @Controller public class UserController3 { @RequestMapping("/redriect") public String start(){ return "redirect:/blog.html"; } } //resp.sendRedirect("/blog.html");
//1请求转发: @Controller public class UserController2 { @RequestMapping("/forward") public String run(){ return "forward:/blog.html"; } } //2请求转发 @Controller public class UserController2 { @RequestMapping("/forward2") public void start(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.getRequestDispatcher("/blog.html").forward(req,resp); } } //3.请求转发: @Controller public class UserController2 { @RequestMapping("/forward2") public String start(){ return "/Text.html"; } }
请求转发和请求重定向之间有什么区别?
1)请求转发:这是发生在服务器的内部,当我们的服务器端收到客户端的请求的时候,会先将请求转发给目标地址,再将目标地址返回的结果转发给客户端,电脑搜索栏里面的URL地址是不会发生改变的,浏览器啥也不用干,是服务器的行为;
2)请求重定向:让浏览器重新请求另一个地址,服务器端将请求重新定义到要访问的地址上面,URL地址会发生改变(浏览器自己要干活)(和直接访问服务器地址是一样的);
3)使用请求转发有可能外部资源时会丢失的,是会访问不到的,但是请求重定向是直接重定向到URL地址了,所以请求重定向和直接访问目标地址的效果是一模一样的,所以是不会存在外部资源丢失的情况,如果说请求转发的资源和转发的页面不在同一个目录下,就会造成外部资源不可以进行访问,目录模式只有一级,样式直接丢失了;
如果你的请求转发的路径是一级路径,但是最终的url地址是二级路径,资源是一级目录的资源文件就会丢失,目录层级不一样,就很有可能造成资源丢失;
4)数据共享不同:请求转发只需要进行一次请求,但是请求重定向是多次请求,因为我们的请求转发是服务器端进行实现的因此在整个交互过程中使用的都是同一个HttpServletRequest和一个HttpServletResponse对象,因此在整个请求的过程中,请求和返回的数据是共享的,5)但是请求重定向是客户端发送起的两次完全不一样的请求,所以两次请求的数据是不同的
请求转发的地址最终就是第一个服务器端的地址,请求重定向地址会发生改变
@Controller
@RequestMapping("/User")
public class TextController {
@RequestMapping("/Java")
public String forward(HttpServletResponse resp) throws IOException {
// resp.sendRedirect("blog3.html");
return "forward:/blog3.html";
}
@RequestMapping("CC")
public String preforward()
{
return "redirect:/blog3.html";
}
}
1)补充一个组合注解:@RestController=@Controller+@ResponseBody;
2)@ResponseBody返回的值如果是字符串会转换成text/html,如果返回的是对象那么会转换成application/json返回给前端;
3)@ResponseBody可以用来修饰方法或者用来修饰类,修饰类表示类中的所有方法都会返回html或者json,而不是视图;
4)Lombok项目是一个java库,它可以自动插入到编辑器和构建工具中,增强java的性能,不要再写另一个getter或equals方法,只要有一个注释,你的类就有一个功能齐全的构建器,自动记录变量等等;