Vue ElementUI Axios 前后端案例(day03) 之 Axios

前置知识

AJAX

前置知识

答疑

问:我们是否可以这么理解,发送url请求就是服务器之间建立连接,tcp三次握手之后 其中与服务器进行数据交换:通过AJAX可以给服务器发送请求 就是连接建立以后 我们发送我们的浏览器数据 就是所谓的发送url请求

newbing:是的,您的理解是正确的。在使用AJAX技术时,发送URL请求就是在服务器之间建立连接,通过TCP三次握手来完成。连接建立后,我们可以通过AJAX向服务器发送请求并交换数据。这就是所谓的发送URL请求。当然,这里我们仅讨论在AJAX技术中的情况,不涉及其他技术。

gpt:部分理解是正确的,但是还需要补充几点:

  1. 发送 URL 请求并不是建立连接的过程,而是向服务器请求数据的过程。建立连接是在发送请求之前进行的,通过 TCP 三次握手确立连接。

  2. 在 AJAX 技术中,我们不仅可以发送 URL 请求,还可以发送其他类型的请求,比如 JSON、XML 等格式的数据。

  3. AJAX 技术实现了异步通信,即客户端可以在不刷新页面的情况下与服务器进行数据交换。这是 AJAX 技术最重要的特点之一。

  4. AJAX 技术并不是一种新的技术,而是一种组合性的技术,包括 HTML、CSS、JavaScript、XMLHttpRequest 等多个技术的结合。因此,在使用 AJAX 技术时,需要掌握多种技术的使用方法。

那么建立连接凭什么在url请求之前?

gpt:在 HTTP 协议中,客户端和服务器之间建立连接的过程是通过 TCP 协议实现的,而不是通过 HTTP 协议实现的。在建立连接之前,客户端和服务器需要进行三次握手,以确保双方能够正常通信。三次握手的过程如下:

  1. 客户端向服务器发送一个 SYN 报文,表示要建立连接,并指定一个初始序列号。

  2. 服务器收到 SYN 报文后,向客户端发送一个 SYN/ACK 报文,表示服务器已经收到客户端的请求,并同意建立连接。

  3. 客户端收到 SYN/ACK 报文后,向服务器发送一个 ACK 报文,表示客户端已经收到服务器的响应,并同意建立连接。

只有在建立了 TCP 连接之后,客户端才能向服务器发送 HTTP 请求,包括 URL 请求。因此,建立连接必须在 URL 请求之前完成。

问:也就是说输入url 先建立tcp 链接 再 发送http请求?
gpt:是的,输入 URL 后,浏览器首先会解析 URL 地址,得到主机名和端口号等信息,然后通过 DNS 解析获取服务器的 IP 地址。接下来,浏览器会通过 TCP 协议与服务器建立连接,建立连接的过程需要进行三次握手。只有在建立了 TCP 连接之后,浏览器才能向服务器发送 HTTP 请求,包括 URL 请求。因此,输入 URL 的过程中,先建立 TCP 连接,再发送 HTTP 请求。

问:那也就是说ajax 只帮助我们收集了客户端的数据并发送到客户端的通信组件,至于服务器通信组件和客户端通信组件如何建立连接和传输数据的过程,我们程序员并不需要关心是吗?

问:那也就是说ajax 只帮助我们收集了客户端的数据并发送到客户端的通信组件,至于服务器通信组件和客户端通信组件如何建立连接和传输数据的过程,我们程序员并不需要关心是吗?

newbing:是的,您说得对。AJAX技术只负责收集客户端数据并将其发送到客户端的通信组件。至于服务器通信组件和客户端通信组件之间如何建立连接和传输数据,这些过程都是由底层协议(如TCP)自动完成的,程序员并不需要关心这些细节。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- import CSS -->
    <link rel="stylesheet" href="https://unpkg.zhimg.com/element-ui/lib/theme-chalk/index.css">
</head>

<body>
    <div id="msg">

    </div>
    <!-- 引入组件库 -->
    <!-- 引入组件库 -->
    <script src="js/vue.js"></script>
    <script src="https://unpkg.zhimg.com/axios@1.3.5/dist/axios.min.js"></script>
    <!-- 引入这个库之后 相当于axios对象已经被创建 -->
    <script>
        //处理get请求
        //then请求完成之后做的事情 所以可以参数写接收的结果 response和error都是服务器端响应的内容
        //catch请求出错干什么
        axios.get("./data/form-data.json", {
            params: {
                param1: "hello",
                param2: "Axios",
            }
        }).then(function (response) {
            let data = response.data;

            //等号右边的data是指json对象的msg
            document.querySelector("#msg").innerHTML = data.msg;
            // document.getElementById("msg").innerHTML=data.msg;
            console.log(response);
        })
            .catch(function (error) {
                console.log(error);
            });
    </script>
</body>

</html>

相当于 axios.get(“./data/form-data.json”, {
params: {
param1: “hello”,
param2: “Axios”,
}
}) 发送了get请求后面更了两个参数param1和param2
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- import CSS -->
    <link rel="stylesheet" href="https://unpkg.zhimg.com/element-ui/lib/theme-chalk/index.css">
</head>

<body>
    <div id="app">
        <el-form :inline="true" :model="searchForm">
            <el-form-item label="栏目名称"> 
                <el-input placeholder="栏目名称" size="small" v-model="searchForm.name"></el-input>
            </el-form-item>
            
            <el-form-item >
                <el-button size="small" @click="search">搜索</el-button>
            </el-form-item>
        </el-form>

        <el-button type="primary" size="small" @click="add">新增</el-button>
       <!-- 这里:data属性 是用来显示数据的  tabledata则绑定值 在每一行中 prop这是这行数据的键 每一个键对应一个值 name:10001,desc:"新闻",name:"娱乐新闻"-->
        <el-table :data="tableData">
            <el-table-column prop="name" label="栏目名称">
            </el-table-column>
            <el-table-column prop="desc" label="栏目描述">
            </el-table-column>
            <el-table-column fixed="right" label="操作">
                <!-- 可以表示项目名称和项目描述下的那一行数据 -->
                <template slot-scope="rowData">
                    <el-button type="primary" size="small" @click="edit(rowData.row)">编辑</el-button>
                    <el-button type="danger" size="small" @click="del(rowData.row.id)">删除</el-button>
                   
                </template>
            </el-table-column>
        </el-table>

        <el-pagination 

            prev-text="上一页"
            next-text="下一页"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="current"
            :page-sizes="[10, 20, 30, 40]" 
            :page-size="size" 
            :total="total"
            layout="total, sizes, prev, pager, next, jumper" 
            >
        </el-pagination>

        <!-- :visible.sync  表示是否显示对话框 这里面的属性值dialogFormVisible 来控制是否显示对话框-->
        <el-dialog title="新增栏目" :visible.sync="dialogFormVisible" width="30%">
            <el-form label-position="left" label-width="80px" :model="formData">
                <el-form-item label="栏目名称">
                    <el-input v-model="formData.name"></el-input>
                </el-form-item>
                <el-form-item label="栏目描述">
                    <el-input v-model="formData.desc"></el-input>
                </el-form-item>
            </el-form>
            <div slot="footer" >
                <el-button @click="dialogFormVisible = false" size="small">取 消</el-button>
                <el-button type="primary" @click="save" size="small">确 定</el-button>
            </div>
        </el-dialog>
    </div>
    <!-- 引入组件库 -->
    <script src="js/vue.js"></script>
    <script src="https://unpkg.zhimg.com/element-ui/lib/index.js"></script>
    <script src="https://unpkg.zhimg.com/axios@1.3.5/dist/axios.min.js"></script>
    <script>
        let vm=new Vue({
            el: '#app',
            data() {
                return {
                    current: 1,
                    size: 10,
                    total: 35,
                    dialogFormVisible: false,
                    tableData: [],
                    formData :{
                        id: '',
                        name: '',
                        desc: '',
                    },
                    searchForm :{
                        name: '',

                    }
                }
            },
            created() {
                axios.get('./data/column-data.json')
                    .then(response => {
                        this.tableData=response.data;
                    })
                    .catch(err => {
                        console.error(err); 
                    })
            },
            methods: {
                search: function(){
                    
                },
                add: function () {
                    this.dialogFormVisible = true;
                },
                edit: function(row){
                   // console.log(row);
                    this.dialogFormVisible = true;   
                //    this.formData =row;
                    this.formData.name =row.name;
                    this.formData.desc =row.desc;
                },
                save: function(){
                    //1.提交到到后台
                    //2.上对话框隐藏
                    this.dialogFormVisible = false;
                },
                del: function(id){
                    console.log(id);
                    // 这里是this是vm对象 只是elementui将this对象的功能进行继承一样扩展
                    this.$confirm('确认删除, 是否继续?', '提示', {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning'
                    }).then(() => {
                        this.$message({
                            type: 'success',
                            showClose: true,
                            message: '删除成功!',
                            // onClose: function(){
                            //     alert()
                            // }
                        });
                    }).catch(() => {
                        this.$message({
                            type: 'info',
                            message: '已取消删除'
                        });
                    });
                },
                //一页显示的数据条数发生改变的时候触发
                handleSizeChange: function(){
                    console.log("handleSizeChange")
                },
                //页码发送改变的时候触发
                handleCurrentChange: function(){
                    console.log("handleCurrentChange")
                }
            },

        })
    </script>
</body>

</html>

在这里插入图片描述
在这里插入图片描述
表格和表单.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- import CSS -->
    <link rel="stylesheet" href="https://unpkg.zhimg.com/element-ui/lib/theme-chalk/index.css">
</head>

<body>
    <div id="app">
        <el-form :inline="true" :model="searchForm">
            <el-form-item label="栏目名称">
                <el-input placeholder="栏目名称" size="small" v-model="searchForm.name"></el-input>
            </el-form-item>

            <el-form-item>
                <el-button size="small" @click="search">搜索</el-button>
            </el-form-item>
        </el-form>

        <el-button type="primary" size="small" @click="add">新增</el-button>
        <!-- 这里:data属性 是用来显示数据的  tabledata则绑定值 在每一行中 prop这是这行数据的键 每一个键对应一个值 name:10001,desc:"新闻",name:"娱乐新闻"-->
        <el-table :data="tableData">
            <el-table-column prop="name" label="栏目名称">
            </el-table-column>
            <el-table-column prop="desc" label="栏目描述">
            </el-table-column>
            <el-table-column fixed="right" label="操作">
                <!-- 可以表示项目名称和项目描述下的那一行数据 -->
                <template slot-scope="rowData">
                    <el-button type="primary" size="small" @click="edit(rowData.row)">编辑</el-button>
                    <el-button type="danger" size="small" @click="del(rowData.row.id)">删除</el-button>

                </template>
            </el-table-column>
        </el-table>

        <el-pagination prev-text="上一页" next-text="下一页" @size-change="handleSizeChange"
            @current-change="handleCurrentChange" :current-page="current" :page-sizes="[5,10, 20, 30, 40]"
            :page-size="size" :total="total" layout="total, sizes, prev, pager, next, jumper">
        </el-pagination>

        <!-- :visible.sync  表示是否显示对话框 这里面的属性值dialogFormVisible 来控制是否显示对话框-->
        <el-dialog title="栏目" :visible.sync="dialogFormVisible" width="30%">
            <el-form label-position="left" label-width="80px" :model="formData">
                <el-form-item label="栏目名称">
                    <el-input v-model="formData.name"></el-input>
                </el-form-item>
                <el-form-item label="栏目描述">
                    <el-input v-model="formData.desc"></el-input>
                </el-form-item>
            </el-form>
            <div slot="footer">
                <el-button @click="dialogFormVisible = false" size="small">取 消</el-button>
                <el-button type="primary" @click="save" size="small">确 定</el-button>
            </div>
        </el-dialog>
    </div>
    <!-- 引入组件库 -->
    <script src="js/vue.js"></script>
    <script src="https://unpkg.zhimg.com/element-ui/lib/index.js"></script>
    <script src="https://unpkg.zhimg.com/axios@1.3.5/dist/axios.min.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data() {
                return {
                    current: 1,
                    size: 10,
                    total: 35,
                    dialogFormVisible: false,
                    tableData: [],
                    formData: {
                        id: '',
                        name: '',
                        desc: '',
                    },
                    searchForm: {
                        name: '',

                    }
                }
            },
            created() {
                this.loadData();
            },
            methods: {
                loadData: function () {
                    axios.get('./data/column-data.json', {
                        params: {
                            current: this.current,
                            size: this.size,
                            total: this.total,
                            name: this.searchForm.name
                        }
                    })
                        .then(response => {
                            this.tableData = response.data.record;
                            this.current = response.data.current;
                            this.size = response.data.size;
                            this.total = response.data.total;
                        })
                        .catch(err => {
                            console.error(err);
                        })
                },
                search: function () {
                    //alert();
                    this.loadData();
                    // this.current = 1;
                },
                add: function () {
                    this.dialogFormVisible = true;
                    this.formData.id = '';
                    this.formData.name = '';
                    this.formData.desc = '';

                },
                edit: function (row) {
                    // console.log(row);
                    this.dialogFormVisible = true;
                    this.formData.id = row.id;
                    this.formData.name = row.name;
                    this.formData.desc = row.desc;
                },
                //新增或编辑的逻辑栏目数据
                save: function () {
                    //1.提交到到后台
                    //2.上对话框隐藏
                    this.dialogFormVisible = false;
                    this.$message({
                        type: 'success',

                        message: '新增成功!',
                        // onClose: function(){
                        //     alert()
                        // }
                    });
                    //重新加载后台数据
                    this.loadData();
                },
                del: function (id) {
                    console.log(id);
                    // 这里是this是vm对象 只是elementui将this对象的功能进行继承一样扩展
                    this.$confirm('确认删除, 是否继续?', '提示', {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning'
                    }).then(() => {
                        this.$message({
                            type: 'success',
                            showClose: true,
                            message: '删除成功!',
                            // onClose: function(){
                            //     alert()
                            // }            
                        });
                        //重新加载后台数据
                        this.loadData();
                    }).catch(() => {
                        this.$message({
                            type: 'info',
                            message: '已取消删除'
                        });
                    });
                },
                //一页显示的数据条数发生改变的时候触发
                handleSizeChange: function (pageSize) {
                    // console.log(pageSize);
                    this.size = pageSize;
                    this.loadData();
                },
                //页码发送改变的时候触发
                handleCurrentChange: function (pageNum) {
                    //console.log(pageNum);
                    this.current = pageNum;
                    this.loadData();
                }
            },

        })
    </script>
</body>

</html>

column.json

{
    "current": 1,
    "size": 5,
    "total": 38,
    "record": [
        {
            "id": "1001",
            "name": "新闻",
            "desc": "娱乐新闻"
        },
        {
            "id": "1002",
            "name": "新闻",
            "desc": "娱乐新闻"
        },
        {
            "id": "1003",
            "name": "国际",
            "desc": "国际新闻"
        }
    ]
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的 Spring Boot Security + Vue前后端分离登录接口示例: 1. 后端实现 首先,我们需要创建一个 Spring Boot 项目,并添加以下依赖: ```xml <dependencies> <!-- Spring Boot Security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- Spring Boot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring Boot JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- MySQL Connector --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- JSON Web Token --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> </dependencies> ``` 接下来,我们需要创建一个 User 实体类和 UserRepository 接口,用于管理用户信息。这里我们使用 MySQL 数据库作为数据存储。 ```java @Entity @Table(name = "users") public class User implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, unique = true) private String username; @Column(nullable = false) private String password; @Override public Collection<? extends GrantedAuthority> getAuthorities() { return Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")); } @Override public String getPassword() { return password; } @Override public String getUsername() { return username; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } } public interface UserRepository extends JpaRepository<User, Long> { User findByUsername(String username); } ``` 然后,我们需要创建一个 Security 配置类,用于配置 Spring Security。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserRepository userRepository; @Autowired private JwtTokenProvider jwtTokenProvider; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(username -> userRepository.findByUsername(username)) .passwordEncoder(passwordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/api/auth/**").permitAll() .anyRequest().authenticated() .and() .apply(new JwtConfigurer(jwtTokenProvider)); } } ``` 这个配置类中,我们使用了 BCryptPasswordEncoder 作为密码加密方式,并且使用了自定义的 UserDetailsService 来获取用户信息。此外,我们还配置了一些请求的权限,其中 /api/auth/** 接口是登录接口,我们允许所有人访问。 最后,我们需要创建一个 JwtTokenProvider 类,用于生成和验证 JSON Web Token。 ```java @Component public class JwtTokenProvider { private static final String SECRET_KEY = "my-secret-key"; private static final long EXPIRATION_TIME = 86400000L; // 1 day public String generateToken(User user) { Date now = new Date(); Date expiration = new Date(now.getTime() + EXPIRATION_TIME); return Jwts.builder() .setSubject(user.getUsername()) .setIssuedAt(now) .setExpiration(expiration) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } public Authentication getAuthentication(String token) { UserDetails userDetails = new UserDetailsService() { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUsername(username); if (user == null) { throw new UsernameNotFoundException("User not found"); } return user; } }.loadUserByUsername(getUsername(token)); return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); } public boolean validateToken(String token) { try { Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token); return true; } catch (JwtException | IllegalArgumentException e) { return false; } } public String getUsername(String token) { return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getSubject(); } } ``` 在这个类中,我们定义了一个 SECRET_KEY 和 EXPIRATION_TIME 常量,分别用于生成 JSON Web Token 和设置 Token 的有效期。generateToken() 方法用于生成 Token,getAuthentication() 方法用于根据 Token 获取用户认证信息,validateToken() 方法用于验证 Token 的有效性,getUsername() 方法用于获取 Token 中的用户名。 最后,我们需要创建一个 JwtConfigurer 类,用于配置 Spring Security 的过滤器链。 ```java public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { private JwtTokenProvider jwtTokenProvider; public JwtConfigurer(JwtTokenProvider jwtTokenProvider) { this.jwtTokenProvider = jwtTokenProvider; } @Override public void configure(HttpSecurity http) throws Exception { JwtTokenFilter customFilter = new JwtTokenFilter(jwtTokenProvider); http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); } } ``` 这个类中,我们创建了一个 JwtTokenFilter 过滤器,并将其添加到 Spring Security 的过滤器链中。 2. 前端实现 在前端,我们使用 Vue 框架来实现登录页面。首先,我们需要安装 axios 库,用于发送 HTTP 请求。 ```bash npm install --save axios ``` 然后,我们创建一个 Login.vue 组件,在其中添加一个表单,用于输入用户名和密码。 ```html <template> <div class="login"> <h1>Login</h1> <form> <div class="form-group"> <label for="username">Username:</label> <input type="text" class="form-control" id="username" v-model="username"> </div> <div class="form-group"> <label for="password">Password:</label> <input type="password" class="form-control" id="password" v-model="password"> </div> <button type="submit" class="btn btn-primary" @click.prevent="login">Submit</button> </form> </div> </template> <script> import axios from 'axios'; export default { name: 'Login', data() { return { username: '', password: '' }; }, methods: { login() { axios.post('/api/auth/login', { username: this.username, password: this.password }).then(response => { localStorage.setItem('access_token', response.data.token); this.$router.push('/'); }).catch(error => { console.error(error); }); } } }; </script> ``` 在这个组件中,我们使用axios 库来发送 POST 请求到 /api/auth/login 接口,并在登录成功后将 Token 存储到 localStorage 中,然后跳转到首页。 3. 完整示例 完整的代码示例可以在以下链接中找到: https://github.com/zhangxu-s/springboot-vue-login-example

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值