Spring Boot专栏八:与前端的交互,以及注解的解释(二)


因为作者本人技术太差,没法完成全栈的任务,只写后端,前端都是和别人合作的(以后给大家推荐前端大神),因此本专栏只能作为教学用,没法真的实现一个真正的大的完善的系统。但是虽然如此,我还是要讲一下怎么与前端交互,大家了解了之后可以找人合作,或者自己学习前端的技术。

RequestMethod

这是之前留下的坑,位置在专栏五讲注解的时候,在Controller层中的RequestMapping里。当时留下这个坑,是因为我们一直在用@RequestParam传递参数。当使用这个注解时,我们应该使用
@RequestMapping(value=“xxx”, method={RequestMethod.GET}),其中花括号可以去掉;
或者,就将RequestMapping改为GetMapping:
@GetMapping(value=“xxx”)

但是我们上一节专栏里,讲了我们和前端传输信息时,都要通过字符串把类包裹起来,进行传输。这样的话,用RequestParam也可以,但比较麻烦(我没有尝试过,朋友们有经验的话可以替我补充)。这时候可以用上RequestBody,这样能够通过类来传输信息。大家体会一下Param和Body的区别。
有关于RequestBody的知识我们放到下面一小节来讲。首先来说一下RequestParam和RequestBody对应的RequestMethod方法,可以参考大佬的博客:获取接口请求中的参数(@PathVariable,@RequestParam,@RequestBody)
我个人没有尝试过这些组合,我在我的项目里,都是让前端的大神伙伴通过POST方法传给我一个类或字符串,同时我使用RequestBody来接收该信息。所以,我在RequestMethod的选择上,都是只选择POST,也就是写成:
@RequestMapping(value=“xxx”, method={RequestMethod.POST}),其中花括号可以去掉
或者将RequestMapping改为PostMapping:
@PostMapping(value=“xxx”)

但是,如果某个方法是没有输入的,比如我们要查询所有用户的信息,这是没有输入的,那么这个时候只写POST是错的,还要加上GET.
另外,我在实践中还发现,如果前端不传输入,同时我们的RequestMethod只写GET,也会莫名报错,传递不了信息。
这太乱了,还好Spring Boot还留了一招,那就是只写@RequestMapping(value=“xxx”),不写关于method的信息,那么Spring Boot是同时支持RequestMethod.POST和RequestMethod.GET的,那这样既偷懒,又解决了问题。不过我们还是要了解上述RequestMethod的相关知识的,偷懒不一定不好,只是要用对地方,后面我们也有偷懒的地方,一起看下去吧。

RequestBody

前面我们已经提到了,用@RequestBody注解代替@RequestParam注解,这样可以从前端接收一个类或字符串。

输入的是一个类

这种方便的传输,要感谢JSON字符串。我们在上一节专栏中看到了JSON把一个类包裹起来,变成了一个字符串。
那么后端接收到了一个字符串,又怎么把它转化为对应的类呢?下面我以账户登录的例子,来展示一下如何写:

首先,可以在方法的参数中直接写明类,即:

public String login(@RequestBody User user_str) {

但这样不保险,万一我们把类写错了,都不知道为什么输入不进来。更保险的方法如下:

@RequestMapping(value = "/login")
public String login(@RequestBody String user_str) {
	User user = JSON.parseObject(user_str, User.class);
	String user_name = user.get_user_name();
	String user_password = user.get_user_password();
	return "用户名为:"+user_name+",用户密码为:"+user_password;
}

输入的是一个字符串,怎么都不会错,我们甚至可以让字符串输出一下,看看前端传过来的是什么样的字符串。
其中,user_str是由@RequestBody注解的,可以让前端直接返回一个类的JSON化的字符串格式了。(可惜的是我们没法演示了)
只要数据对得上,我们就能通过JSON.parseObject方法来将user_str根据User类来转化为user对象。由于登录任务,只需填写用户名和密码,所以user对象中只有user_name属性和user_password属性,那么在User类中也要有一个只根据user_name属性和user_password属性构造类的构造方法。
我们可以继续写一点功能,比如验证是否能够成功登录:

@RequestMapping(value = "/login")
public String login(@RequestBody String user_str) {
	User user = JSON.parseObject(user_str, User.class);
	String user_name = user.get_user_name();
	String user_password = user.get_user_password();
	if (userService.find_user_name_if_exists(user_name) == 0) {
		return "该用户名不存在!";
	}
	if (!userService.select_user_password_by_user_name(user_name).equals(user_password)) {
		return "账号密码错误!";
	}
	return "登录成功!用户名为:"+user_name+",用户密码为:"+user_password;
}

Service, Dao层的代码我就不写了,留给大家当作业,大家可以去github中查阅代码,链接在博客最下方。
大家如果尝试不了,可以将RequestBody先替换成RequestParam,POST替换成GET,实参也改一下。我们尝试新功能,可以将就一些。

输入的是一个基本数据类型或包装类

输入不一定是一个复杂的类,可能只是一个基本数据类型或包装类,那么这个时候,JSON.parseObject的参数就要改变了:
假设输入的是一个整型数据:

int num = JSON.parseObject(num_str, Integer.class);
Integer num = JSON.parseObject(num_str, Integer.class);

使用基本数据类型或包装类来接收都是可以的。double, char等同理。

输入的是一个列表或数组

在这里我们还是不要用数组,而是用列表来接收。其道理和mybatis的返回值用列表一样。以一个User类的列表为例,此处代码这样写:

List<User> user_list = JSON.parseArray(user_list_str, User.class);

相比于输入一个类,只改动了JSON的方法,将parseObject改为parseArray.
如果输入的是整型列表,也类似:

List<Integer> num_list = JSON.parseArray(num_list_str, Integer.class);

输入的是一个普通字符串

哈哈哈,这个就不成问题了,传过来的是字符串,那就正好啊。

ResponseBody

输入既然是字符串形式了,那么输出自然也是以字符串形式返回给前端。这就用到了@ResponseBody注解,大家从Request和Response的区别中也能懂它们作用于输入还是输出吧。
具体而言,该注解用于将Controller方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
当我们平时返回输出一个"success"时,@ResponseBody的作用不大。但是当我们要返回一个类(包括列表),或者普通基本数据类型时,它就有用了。我们之前已经使用JSON.toJSONString方法改写了“显示所有用户的所有信息”功能,令其以字符串形式返回类。我们在它的方法前加上@ResponseBody注解,这样就完成了和前端的交互:

@RequestMapping(value = "/show_user_all")
@ResponseBody
public String show_user_all() {
	List<User> result = userService.show_user_all();
	int len = result.size();
	System.out.println("共查询到"+len+"条记录");
	for (int i = 0;i < len;i++) {
		User user = result.get(i);
		String user_name = user.get_user_name();
		String user_password = user.get_user_password();
		String register_time = user.get_register_time();
		String login_time = user.get_login_time();
		System.out.println("第"+(i+1)+"条记录的用户名为"+user_name+",密码为"+user_password+",注册时间为"+register_time+",最后一次的登录时间为"+login_time);
	}
	return JSON.toJSONString(result);
}

以后我们的每个方法上都带着@ResponseBody注解,这样就能更好地与前端交互。

既然,也有偷懒的方法,就是将@ResponseBody注解到类前面,这样每个方法都能以Http格式向前端返回信息——不管是JSON格式的类或基本数据类型,还是普通的字符串,都能有效高效(更准确地说是偷懒)地进行。也就是:

@RestController
@RequestMapping("/user")
@ResponseBody
public class UserController {
	// 具体方法
}

Spring Boot解决前后端跨域问题——CrossOrigin

我们知道,一个项目的前后端一般是分开开发的,一般是在同一个局域网中,但是不同电脑。这样的话,前后端连接还是会有问题,这叫做“跨域问题”。解决这个问题需要前后端共同配合,在后端主要是加上@CrossOrigin注解。

然后……就结束了。是的,就这么简单,我们后端解决跨域问题只需要加一个@CrossOrigin注解,而且可以加在Controller类前,不必加在每个具体方法前。相比于前端各种配置api,写我们后端的ip和接口,嘿嘿,我们后端太轻松了。
其实可以细挖一下这个注解。它有两个重要的参数,第一个是origins,可以写上我们本地的ip和port,即只暴露某一个port给别的电脑访问。因为现在我们的port设置的是默认的8080,由于大家都知道默认的port是8080,所以可能不安全,会被窃听,但如果修改了这个port,修改完之后可以只将这个接口偷偷告诉你的前端,这样就保险了。不过因为origins默认是对所有端口开放的,所以我们的小项目可以不修改port,只需要自己了解这个参数能够限制接口就行了。
第二个参数是maxAge,表示响应的缓存持续时间的最大时间,单位为秒,但是默认情况下是无限大。这个也是为了安全考虑设置的参数,不过我们目前不用搭理,到公司了听领导的需要就行。

@CrossOringin也是可以用来偷懒的,我们直接加在UserController类前就好:

@RestController
@RequestMapping("/user")
@ResponseBody
@CrossOrigin
public class UserController {
	// 具体方法
}

本节专栏的内容到此结束,为了方便大家拷贝代码,我已经将我的项目放到了github上,项目地址为https://github.com/DTSSDUTDeepLearning/Spring-Boot-Dante,有需求的朋友们自行前往下载。

谢谢大家的阅读。

专栏第九节已经更新啦,传送门:Spring Boot专栏九:最简单的商城系统项目的第一步——规划项目

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值