前后端分离

一、前后端分离

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">&emsp;&emsp;名:<input type="text" name="name" autocomplete="off" v-model="name" /><br />&emsp;户名:<input type="text" name="username" autocomplete="off" v-model="username" /><br />&emsp;&emsp;码:<input type="text" name="password" autocomplete="off" v-model="password" /><br />&emsp;&emsp;别:<input type="radio"  autocomplete="off" v-model="sex" value="1" checked="checked" /><input type="radio" autocomplete="off"  v-model="sex" value="0"/><br />&emsp;&emsp;龄:<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();
    }
}

四、操作单表的增删查改具体项目源码

源码压缩包

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值