Spring Boot+Vue前后端分离开发09-----Form表单

7 篇文章 0 订阅

标签 : Java Vue Sring JPA ELementUI
作者 : Maxchen
版本 : V1.0.0
日期 : 2020/3/7



1. Vue开发——Form表单前端

此次开发的Form表单功能为新增图书,具体要求如下:

  • 添加一个图书,图书包含名称和作者两个字段
  • 对添加的图书的字段进行合法性检验,既不能添加空信息,信息长度也不能过长
  • 提供两个按钮,一个按钮可以提交数据,另一个按钮重置输入

第一步:然后新增一个Component名为AddBook.vue,具体代码为:

<template>

    <!--
        :model 用于绑定表单数据对象
        :rules 用于表单验证规则
        ref 引用获取表单元素
        prop 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的
        v-model 表单数据项
    -->
    <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
        <el-form-item label="图书名称" prop="name">
            <el-input v-model="ruleForm.name"></el-input>
        </el-form-item>
        <el-form-item label="图书作者" prop="author">
            <el-input v-model="ruleForm.author"></el-input>
        </el-form-item>
        <el-form-item>
            <el-button type="primary" @click="submitForm('ruleForm')">立即创建</el-button>
            <el-button @click="resetForm('ruleForm')">重置</el-button>
        </el-form-item>
    </el-form>
</template>

<script>
    export default {
        data() {

            // 表单校验
            return {
                ruleForm: {
                    name: '',
                    author: '',
                },
                // required 控制必填/非必填
                // message 提示信息
                // trigger 触发事件
                rules: {
                    name: [
                        { required: true, message: '请输入图书名称', trigger: 'blur' },
                        { min: 1, max: 20, message: '长度在 1 到 20 个字符', trigger: 'blur' }
                    ],
                    author: [
                        { required: true, message: '请输入图书作者', trigger: 'blur' },
                        { min: 1, max: 10, message: '长度在 1 到 10 个字符', trigger: 'blur' }
                    ]
                }
            };
        },
        methods: {

            //提交表单
            submitForm(formName) {
                //_this.ruleForm获取表单数据
                const _this = this
                this.$refs[formName].validate((valid) => {
                    //参数合法,提交表单
                    if (valid) {
                        console.log(_this.ruleForm);
                        alert('校验通过!');
                    }
                    //参数不合法,控制台打印信息
                    else {
                        console.log('校验失败!');
                        return false;
                    }
                });
            },

            //重置表单
            resetForm(formName) {
                this.$refs[formName].resetFields();
            }
        }
    }
</script>

<style scoped>
</style>

model 用于绑定表单数据对象
rules 用于表单验证规则
ref 引用获取表单元素
prop 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的
v-model 表单数据项
required 控制必填/非必填
message 提示信息
trigger 触发事件

第二步:输入空参,验证下程序是否能进行合法性检验:

image.png-20.6kB

第三步:输入合法参数校验成功,进入下一阶段开发:

image.png-43.4kB

2. SpringBoot开发——Form表单接口开发

这次开发的Form表单非常简单,在数据库表book中新增一条记录,记录包含id主键、name图书名称、author作者

image.png-88.5kB

第一步:实体类Book,实体类绑定数据库表book同时绑定idnameauthor字段

package com.maxchen.springboottest.entity;

import lombok.Data;
import net.bytebuddy.dynamic.loading.InjectionClassLoader;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
@Data //getter and setter方法
public class Book {

    @Id //主键
    @GeneratedValue(strategy = GenerationType.IDENTITY) //自增主键
    private Integer id;
    private String name;
    private String author;

}

第二步:持久层BookRepository,持久层采用了jpa框架

package com.maxchen.springboottest.repository;

import com.maxchen.springboottest.entity.Book;
import org.springframework.data.jpa.repository.JpaRepository;

public interface BookRepository extends JpaRepository<Book,Integer> {

}

第三步:这里我们将BookRepository的继承关系逐层展开,不难发现我们继承的方法里面已经包含了常见的增删改查方法,因此我们这里写个代码测试一下:

image.png-23.2kB

package com.maxchen.springboottest;

import com.maxchen.springboottest.entity.Book;
import com.maxchen.springboottest.repository.BookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class SpringboottestApplicationTests {

    @Autowired
    private BookRepository bookRepository;

    @Test
    void findAll(){
        System.out.println(bookRepository.findAll());
    }

    /**
     * @Title: addBook
     * @Description: 添加一个书籍
     * @Author Maxchen
     */
    @Test
    void addBook(){
        Book book = new Book();
        book.setName("三体");
        book.setAuthor("刘慈欣");
        bookRepository.save(book);
    }

}

测试发现图书数据新增成功

image.png-54.8kB

image.png-98.2kB

第四步:接下来修改Controller层BookController

package com.maxchen.springboottest.controller;

import com.maxchen.springboottest.entity.Book;
import com.maxchen.springboottest.repository.BookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/book")
public class BookController {

    @Autowired
    private BookRepository bookRepository;

    //增加图书
    @PostMapping("/save")
    public String addBook(@RequestBody Book book){
        Book result = bookRepository.save(book);
        if(result != null){
            return "success";
        }else{
            return "error";
        }
    }

}

第五步:接口写好以后,我们最后进行一次测试,如果显示了success则说明新增到数据库成功

image.png-56.8kB

image.png-135.2kB

3. SpringBoot+Vue——前后端联调

通过前面的教程我们完成了Form表单界面和Form表单接口,还有一个步骤就是联调。

第一步:修改AddBook.vue的代码

image.png-68.8kB

// POST方法调用Form表单接口,接口返回"success"则表示添加成功
axios.post('http://localhost:8181/book/save',this.ruleForm).then(function(resp){
	if(resp.data == 'success'){
		_this.$message("添加成功");
	}
})

第二步:在添加图书页面新增一条数据,最后重新查询图书即可看到新增的数据

image.png-23.8kB

image.png-53.3kB

第三步:优化应用体验

通过上述教程,我们开发了一个新增数据的功能,但实际使用中并不友好,用户在点了立即创建按钮之后需要跳转到响应的表格页,因此我们需要做一些小的改造

image.png-103.4kB

if(resp.data == 'success'){
	_this.$alert('《'+_this.ruleForm.name+'》添加成功!', '消息', {
		confirmButtonText: '确定',
		callback: action => {
			_this.$router.push('/BookManage')
		}
	})
}

第四步:前台进行测试,如果弹出添加成功窗口并且能查询到新增数据,说明开发成功!

image.png-49.8kB

image.png-36.6kB

最后贴上整体的代码

<template>

    <!--
        :model 用于绑定表单数据对象
        :rules 用于表单验证规则
        ref 引用获取表单元素
        prop 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的
        v-model 表单数据项
    -->
    <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
        <el-form-item label="图书名称" prop="name">
            <el-input v-model="ruleForm.name"></el-input>
        </el-form-item>
        <el-form-item label="图书作者" prop="author">
            <el-input v-model="ruleForm.author"></el-input>
        </el-form-item>
        <el-form-item>
            <el-button type="primary" @click="submitForm('ruleForm')">立即创建</el-button>
            <el-button @click="resetForm('ruleForm')">重置</el-button>
        </el-form-item>
    </el-form>
</template>

<script>
    export default {
        data() {

            // 表单校验
            return {
                ruleForm: {
                    name: '',
                    author: '',
                },
                // required 控制必填/非必填
                // message 提示信息
                // trigger 触发事件
                rules: {
                    name: [
                        { required: true, message: '请输入图书名称', trigger: 'blur' },
                        { min: 1, max: 20, message: '长度在 1 到 20 个字符', trigger: 'blur' }
                    ],
                    author: [
                        { required: true, message: '请输入图书作者', trigger: 'blur' },
                        { min: 1, max: 10, message: '长度在 1 到 10 个字符', trigger: 'blur' }
                    ]
                }
            };
        },
        methods: {

            //提交表单
            submitForm(formName) {
                //_this.ruleForm获取表单数据
                const _this = this
                this.$refs[formName].validate((valid) => {
                    //参数合法,提交表单
                    if (valid) {
                        // console.log(_this.ruleForm);
                        // alert('校验通过!');
                        // POST方法调用Form表单接口,接口返回"success"则表示添加成功
                        axios.post('http://localhost:8181/book/save',this.ruleForm).then(function(resp){
                            if(resp.data == 'success'){
                                _this.$alert('《'+_this.ruleForm.name+'》添加成功!', '消息', {
                                    confirmButtonText: '确定',
                                    callback: action => {
                                        _this.$router.push('/BookManage')
                                    }
                                })
                            }
                        })
                    }
                    //参数不合法,控制台打印信息
                    else {
                        console.log('校验失败!');
                        return false;
                    }
                });
            },

            //重置表单
            resetForm(formName) {
                this.$refs[formName].resetFields();
            }
        }
    }
</script>

<style scoped>

</style>

4. SpringBoot+Vue——通过表单修改数据

第一步:新增一个修改图书的路由

{
    path: '/bookUpdate',
    name: '修改图书',
    component: () => import('../views/BookUpdate.vue')
}

第二步:图书管理表上新增一个修改按钮

<el-table-column label="操作" width="100">
	<template slot-scope="scope">
		<el-button @click="edit(scope.row)" type="text" size="small">修改</el-button>
		<el-button type="text" size="small">删除</el-button>
	</template>
</el-table-column>

image.png-63.3kB

第三步:给修改按钮绑定一个功能,点击修改按钮之后跳转到修改页面

edit(row) {
	// console.log(row);
	this.$router.push({
		path: '/bookUpdate',
		query: {
			id: row.id
		}
	})
}

image.png-33.3kB

image.png-23.9kB

第四步:修改页面需要自动填充原来待修改的数据,因此还需要增加一个按照id查询数据的接口

@GetMapping("findBookById/{id}")
Book findBookById(@PathVariable("id") Integer id){
	return bookRepository.findById(id).get();
}

第五步:接口写好之后测试一下,直到没有报错或者正常显示数据

image.png-36.9kB

第六步:修改BookUpdate.vue的component,完善修改输入框和联调接口

image.png-93.2kB

image.png-62.8kB

<template>

    <!--
        :model 用于绑定表单数据对象
        :rules 用于表单验证规则
        ref 引用获取表单元素
        prop 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的
        v-model 表单数据项
    -->
    <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
        <el-form-item label="图书编号">
            <el-input v-model="ruleForm.id" readOnly></el-input>
        </el-form-item>

        <el-form-item label="图书名称" prop="name">
            <el-input v-model="ruleForm.name"></el-input>
        </el-form-item>

        <el-form-item label="图书作者" prop="author">
            <el-input v-model="ruleForm.author"></el-input>
        </el-form-item>
        <el-form-item>
            <el-button type="primary" @click="submitForm('ruleForm')">立即修改</el-button>
            <el-button @click="resetForm('ruleForm')">重置</el-button>
        </el-form-item>
    </el-form>
</template>

<script>
    export default {
        data() {

            // 表单校验
            return {
                //表单默认填充数据,新建数据时一般这里为空,编辑数据时可以调用接口自动填充数据
                ruleForm: {
                    id: '',
                    name: '',
                    author: '',
                },
                // required 控制必填/非必填
                // message 提示信息
                // trigger 触发事件
                rules: {
                    name: [
                        { required: true, message: '请输入图书名称', trigger: 'blur' },
                        { min: 1, max: 20, message: '长度在 1 到 20 个字符', trigger: 'blur' }
                    ],
                    author: [
                        { required: true, message: '请输入图书作者', trigger: 'blur' },
                        { min: 1, max: 10, message: '长度在 1 到 10 个字符', trigger: 'blur' }
                    ]
                }
            };
        },
        methods: {

            //修改表单
            submitForm(formName) {
                //_this.ruleForm获取表单数据
                const _this = this
                this.$refs[formName].validate((valid) => {
                    //参数合法,提交表单
                    if (valid) {
                        // console.log(_this.ruleForm);
                        // alert('校验通过!');
                        // POST方法调用Form表单接口,接口返回"success"则表示添加成功
                        axios.post('http://localhost:8181/book/save',this.ruleForm).then(function(resp){
                            if(resp.data == 'success'){
                                _this.$alert('《'+_this.ruleForm.name+'》修改成功!', '消息', {
                                    confirmButtonText: '确定',
                                    callback: action => {
                                        _this.$router.push('/BookManage')
                                    }
                                })
                            }
                        })
                    }
                    //参数不合法,控制台打印信息
                    else {
                        console.log('校验失败!');
                        return false;
                    }
                });
            },

            //重置表单
            resetForm(formName) {
                this.$refs[formName].resetFields();
            }
        },

        //修改的输入框回填旧数据
        created() {
            const _this = this
            axios.get('http://localhost:8181/book/findBookById/'+this.$route.query.id).then(function(resp){
                _this.ruleForm = resp.data
            })
        }

    }
</script>

<style scoped>

</style>

第七步:测试一下修改功能

image.png-47.5kB

image.png-19.6kB

image.png-30.3kB

image.png-43kB

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值