文章目录
一、前后端分离
1. 前端发送Jquery的ajax请求到后端,得到后端的动态数据
(1)出现一个跨域的问题
- 要了解跨域,先要知道同源策略。
- 同源策略是由 Netscape 公司提出的一个著名的安全策略,所有支持 JavaScript 的浏览器都会使用这个策略。
- 所谓同源是指:协议,域名,端口 全部相同。
- 浏览器从一个域名的网页去请求另一个域名的资源时,协议,域名,端口任意不同,都会出现跨域问题。
- 现实工作开发中经常会有跨域的情况。因为公司会有很多项目,也会有很多子域名,各个项目或者网站之间需要相互调用对方的资源,所以跨域请求是避免不了的
- 浏览器从一个域名的网页去请求另一个域名的资源时,协议,域名,端口任意不同,都会出现跨域问题。
(2)在springboot开发中的解决方案
(一)通过注解 @CrossOrigin 来实现跨域
- 在Spring Boot 中给我们提供了一个注解 @CrossOrigin 来实现跨域,
- 这个注解可以实现方法级别的细粒度的跨域控制。
- 我们可以在类或者方法添加该注解,如果在类上添加该注解,该类下的所有接口都可以通过跨域访问,
- 如果在方法上添加注解,那么仅仅只限于加注解的方法可以访问。
(二)通过实现WebMvcConfigurer接口,并实现addCorsMappings方法
@Component
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")//配置可以被跨域的路径,可以任意配置,可以具体到直接请求路径。
// .allowedOrigins("*")//springboot2.4.0之后版本被allowedOriginPatterns("*")替换
.allowedOriginPatterns("*")//允许所有的请求域名访问我们的跨域资源,可以固定单条或者多条内容,如:"http://www.baidu.com",只有百度可以访问我们的跨域资源。
.allowCredentials(true)//响应头表示是否可以将对请求的响应暴露给页面。返回true则可以,其他值均不可以
.allowedMethods("*")//允许输入参数的请求方法访问该跨域资源服务器,如:POST、GET、PUT、OPTIONS、DELETE等。
.allowedHeaders("*")//允许所有的请求header访问,可以自定义设置任意请求头信息,如:"X-AUTH-TOKEN"
.maxAge(3600 * 24);//配置客户端缓存预检请求的响应的时间(以秒为单位)。默认设置为1800秒(30分钟)。
}
}
(3)前后端分离动态交互案列
(一)前端Jquery的ajax请求后端
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/jquery-1.7.2.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
$(function() {
$.ajax({
url: "http://localhost:8080/queryByPage",
type: "get",
data: {
pageNum: 1,
pageSize: 2
},
dataType: "json",
success: function(result) {
var array = result.data;
$.each(array, function(index, item) {
var row =
`<tr>
<td>${item.id}</td>
<td>${item.name}</td>
<td>${item.username}</td>
<td>${item.password}</td>
<td>${item.sex}</td>
<td>${item.age}</td>
<td>${item.birthday}</td>
<td>${item.createTime}</td>
<td>
<a href="">修改</a>
|
<a href="">删除</a>
</td>
</tr>`;
$("#userTable").append(row);
});
}
})
})
</script>
</head>
<body>
<table border="1" cellspacing="" cellpadding="" id="userTable">
<tr>
<th>编号</th>
<th>姓名</th>
<th>用户名</th>
<th>密码</th>
<th>性别</th>
<th>年龄</th>
<th>出生日期</th>
<th>创建时间</th>
<th>操作</th>
</tr>
<!-- <tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr> -->
</table>
</body>
</html>
后端响应前端代码(主要是请求到控制层的接口(增删查改操作数据库)调用,进行数据响应)
@RestController
//支持客户端跨域请求,*指的是所有的来源都允许访问,也可以指定具体的客户端来源地址
@CrossOrigin(origins = "*")
public class UserController {
@Autowired
private UserService userService;
@ApiOperation(value = "新增用户",notes = "新增用户")
@PostMapping("/add")
public Result add(@RequestBody User user){
if(userService.add(user)>0){
return ResultResponse.success();
}else{
return ResultResponse.error(ResultEnum.INSERT_ERROR);
}
}
@ApiOperation(value = "根据编号删除用户",notes = "根据编号删除用户")
@ApiImplicitParam(value = "用户编号",name = "id")
@PostMapping("/delete")
public Result delete(Integer id){
if(userService.delete(id)>0){
return ResultResponse.success();
}else{
return ResultResponse.error(ResultEnum.DELETE_ERROR);
}
}
@ApiOperation(value = "修改用户",notes = "修改用户")
@PostMapping("/update")
public Result update(@RequestBody User user){
if(userService.update(user)>0){
return ResultResponse.success();
}else{
return ResultResponse.error(ResultEnum.UPDATE_ERROR);
}
}
@ApiOperation(value = "根据编号查询用户",notes = "根据编号查询用户")
@ApiImplicitParam(value = "用户编号",name = "id")
@GetMapping("/queryById")
public Result queryById(Integer id){
User user = userService.queryById(id);
return ResultResponse.success(user);
}
@ApiOperation(value = "分页查询用户",notes = "分页查询用户")
@ApiImplicitParams({
@ApiImplicitParam(value = "当前页码",name = "pageNum"),
@ApiImplicitParam(value = "每页记录数",name = "pageSize")
})
@GetMapping("/queryByPage")
public Result queryByPage(@RequestParam("pageNum") Integer pageNum, @RequestParam("pageSize") Integer pageSize){
List<User> users = userService.queryByPage(pageNum, pageSize);
return ResultResponse.success(users);
}
}
(二)前端Vue的axios形式请求后端
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script src="js/axios.min.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css">
table{
width: 50%;
text-align: center;
border-collapse: collapse;
}
</style>
</head>
<body>
<div id="app">
姓  名:<input type="text" name="name" autocomplete="off" v-model="name" /><br />
用 户名:<input type="text" name="username" autocomplete="off" v-model="username" /><br />
密  码:<input type="text" name="password" autocomplete="off" v-model="password" /><br />
性  别:<input type="radio" autocomplete="off" v-model="sex" value="1" checked="checked" />男
<input type="radio" autocomplete="off" v-model="sex" value="0"/>女
<br />
年  龄:<input type="text" name="age" autocomplete="off" v-model="age" /><br />
出生日期:<input type="text" name="birthday" autocomplete="off" v-model="birthday" /><br />
<!-- 创建时间:<input type="text" name="createTime" autocomplete="off" v-model="createTime" /><br /> -->
<input type="button" value="添加" @click="add"/><br />
<table border="1" cellspacing="" cellpadding="" id="userTable">
<tr>
<th>编号</th>
<th>姓名</th>
<th>用户名</th>
<th>密码</th>
<th>性别</th>
<th>年龄</th>
<th>出生日期</th>
<th>创建时间</th>
<th>操作</th>
</tr>
<tr v-for="user in list" :key="user.id">
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.username}}</td>
<td>{{user.password}}</td>
<td>{{user.sex}}</td>
<td>{{user.age}}</td>
<td>{{user.birthday}}</td>
<td>{{user.createTime}}</td>
<td>
<a href="">修改</a>
|
<a href="">删除</a>
</td>
</tr>
</table>
</div>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
user:{
name:"",
username:"",
password:"",
sex:"",
age:"",
birthday:""
},
name:"",
username:"",
password:"",
sex:"",
age:"",
birthday:"",
list:[]
},
methods:{
queryByPage(pageNum,pageSize){
var that=this;
axios.get("http://localhost:8080/queryByPage",{params:{pageNum,pageSize}})//get方式中,后面的传参数是要写成json格式形式,不能省略json对象
.then(function(result){//成功回调
console.log(result.data);
that.list=result.data.data;
}).catch(function(error){//失败回调
console.log(error);
});
},
add(){
axios.post("http://localhost:8080/add",{
/*get方式中,后面的传参数是要写成json格式形式,能省略json对象,其时{name:this.name,
username:this.username,
password:this.password,
sex:this.sex,
age:this.age,
birthday:this.birthday}是data:{name:this.name,
username:this.username,
password:this.password,
sex:this.sex,
age:this.age,
birthday:this.birthday}形式的*/
name:this.name,
username:this.username,
password:this.password,
sex:this.sex,
age:this.age,
birthday:this.birthday
})
.then(res=>{
console.log(res.data.msg);
this.queryByPage(1,50);
}).catch(error=>{
console.log(error);
});
}
// add(){
// axios.post("http://localhost:8080/add",that.user)
// .then(res=>{
// console.log(res.data.msg);
// }).catch(error=>{
// console.log(error);
// });
// }
},
created() {
// var that=this;
// axios.get("http://localhost:8080/queryByPage",{params:{pageNum:1,pageSize:10}})
// .then(function(result){//成功回调
// console.log(result.data);
// that.list=result.data.data;
// }).catch(function(error){//失败回调
// console.log(error);
// });
this.queryByPage(1,20);
}
});
</script>
</body>
</html>
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
二、使用可视化界面Swagger2+springboot的接口测试工具
1.添加poml依赖
<!--api可视化文档生成工具依赖包-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
2.添加一个Swagger配置类
@Configuration
@EnableSwagger2//开启使用Swagger2接口生成
public class Swagger2Config {
//api接口包扫描路径
public static final String SWAGGER_SCAN_BASE_PACKAGE = "com.entor.controller";
public static final String VERSION = "1.0.0";
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage(SWAGGER_SCAN_BASE_PACKAGE))//扫描指定包下的请求地址暴露给Swagger来展现
.paths(PathSelectors.any()) // 可以根据url路径设置哪些请求加入文档,忽略哪些请求
.build()
.directModelSubstitute(Timestamp.class, Date.class);//类型映射
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("系统后台接口服务") //设置文档的标题
.description("用户服务 API 接口文档") // 设置文档的描述
.version(VERSION) // 设置文档的版本信息-> 1.0.0 Version information
.contact(new Contact("张三","http://www.entor.com.cn","zhangsan@163.com"))
.termsOfServiceUrl("http://www.entor.com.cn") // 设置文档的License信息->1.3 License information
.build();
}
}
三、使用可视化界面Swagger2+knife4j+springboot的接口测试工具
1.添加poml依赖
<!--swagger2ui增强版knife4j,页面更好看-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-ui</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2.添加一个Swagger配置类
@Configuration
@EnableSwagger2//开启使用Swagger2接口生成
public class Swagger2Config {
//api接口包扫描路径
public static final String SWAGGER_SCAN_BASE_PACKAGE = "com.entor.controller";
public static final String VERSION = "1.0.0";
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage(SWAGGER_SCAN_BASE_PACKAGE))//扫描指定包下的请求地址暴露给Swagger来展现
.paths(PathSelectors.any()) // 可以根据url路径设置哪些请求加入文档,忽略哪些请求
.build()
.directModelSubstitute(Timestamp.class, Date.class);//类型映射
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("系统后台接口服务") //设置文档的标题
.description("用户服务 API 接口文档") // 设置文档的描述
.version(VERSION) // 设置文档的版本信息-> 1.0.0 Version information
.contact(new Contact("张三","http://www.entor.com.cn","zhangsan@163.com"))
.termsOfServiceUrl("http://www.entor.com.cn") // 设置文档的License信息->1.3 License information
.build();
}
}