最近在学习使用vuejs 然后结合之前学的知识来完成这么一个增删改查的小项目,页面预览


1 初始化一个spring boot 项目 这里注意spring boot的版本要选1.X.X

1 pom.xml 文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.ryz.cn</groupId>
   <artifactId>springbootvuemvc</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>springbootvuemvc</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.1.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
      <thymeleaf-layout-dialect.version>2.0.5</thymeleaf-layout-dialect.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-data-jpa</artifactId>
         <version>1.5.9.RELEASE</version>
      </dependency>

      <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <version>5.1.44</version>
      </dependency>

      <dependency>
         <groupId>com.googlecode.log4jdbc</groupId>
         <artifactId>log4jdbc</artifactId>
         <version>1.2</version>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-devtools</artifactId>
         <optional>true</optional>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-redis</artifactId>
         <version>1.3.2.RELEASE</version>
      </dependency>
      
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>

         </plugin>
      </plugins>
   </build>


</project>
1.1主要依赖的是
spring-boot-starter-data-jpa 为了做持久化对象
mysql-connector-java  MySQL驱动
spring-boot-starter-thymeleaf yml模板
spring-boot-starter-redis  redis缓存

2 配置项目参数,具体的属性看注释吧

application.properties

spring.application.name=sh 
# server.servlet.context-path=/sh
server.context-path=/sh
server.port=8081

# 数据源配置
spring.datasource.url=jdbc:log4jdbc:mysql://localhost:3306/test2
spring.datasource.username=root
spring.datasource.password=157123
spring.datasource.driverClassName = net.sf.log4jdbc.DriverSpy
spring.jpa.database = MYSQL
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql = true
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

# 定位模板的目录
spring.mvc.view.prefix=classpath:/templates/
# 给返回的页面添加后缀名
spring.mvc.view.suffix=.html

spring.thymeleaf.cache=false
#热部署生效
spring.devtools.restart.enabled: true

# REDIS (RedisProperties)
# Redis数据库索引(默认为0spring.redis.database=0 
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379 
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8 
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1 
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8 
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0 
# 连接超时时间(毫秒)
spring.redis.timeout=0

mode: LEGACYHTML5

2.1 这里 server.servlet.context-path 的配置根据spring boot版本的不同不一样,如果你在开发时发现不生效,随便百度一下就知道啦

3 controller 层代码

@Controller
@RequestMapping("/user")
public class UserController {
    @Autowired
    UserService userService;

    @RequestMapping(value="/getUserById",method = RequestMethod.GET)
    @ResponseBody
    public User getUserById(@RequestParam String id){
        System.out.println("hello user");
        User u = userService.findUserById(id);
        System.out.println(u);
        return u;
    }
    @RequestMapping(value="/foundAll",method = RequestMethod.GET)
    public String getUserById(Model model){
        System.out.println("hello user");
        List<User> users = userService.findAll();
        System.out.println(users);
        model.addAttribute("Users", users );
        return "index";
    }

    @RequestMapping(value="/getUsers",method = RequestMethod.GET)
    @ResponseBody
    public Object getUserById(){
        List<User> users = userService.findAll();
        return users;
    }

    @RequestMapping(value="/getUserByOneId",method = RequestMethod.GET)
    @ResponseBody
    public Object getUserByOneId(@RequestParam String id){
        User user = userService.findById(id);
        return user;
    }

    @RequestMapping(value="/deleteById",method = RequestMethod.GET)
    @ResponseBody
    public Object deleteById(@RequestParam String id){
        int count = userService.deleteById(id);
        return count;
    }

    @RequestMapping(value="/init",method = RequestMethod.GET)
    @ResponseBody
    public String init(){
        userService.init();
        return "SUCCESS";
    }

    @RequestMapping(value="/findMy",method = RequestMethod.GET)
    @ResponseBody
    public String findMy(String id){

        return userService.findName(id);
    }

    @RequestMapping(value="/addOne",method = RequestMethod.POST)
    @ResponseBody
    public void addOne(@RequestBody User user){

        userService.save(user);
    }
}

4 实体对象 User

@Entity
@Table(name = "user")
public class User implements Serializable{

    private String id;
    private String name;
    private Integer age;

    public User(){}
    public User(String id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Id
    @Column(name = "id")
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
    @Column(name = "name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    @Column(name = "age")
    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
4.1 注意这里的实体类一定要实现序列化接口,不然没有办法做缓存,否则可以不实现
5 Server层代码
 
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public List<User> findAll(){
        return userRepository.findAll();
    }
    @Transactional(rollbackFor = Exception.class)
    public void save(User user){
        if("".equals(user.getId())){
            user.setId(String.valueOf(System.currentTimeMillis()));
        }
        userRepository.save(user);
    }

    @Transactional(rollbackFor = Exception.class)
    public void init(){
        userRepository.save(new User("20","ryz201",20));
        userRepository.save(new User("21","ryz211",20));
        userRepository.save(new User("22","ryz221",20));
        userRepository.save(new User("22","ryz222",20));
        userRepository.save(new User("23","ryz231",20));
    }

    public User findUserById(String id){
        return userRepository.findUserById(id);
    }
    // 给该查询方法增加缓存
    //@Cacheable(value="user", keyGenerator = "keyGenerator")
    @Cacheable(value="user", key = "#id")
    public User findById(String id){
        return userRepository.findUserById(id);
    }
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value="user",key = "#id" )
    public int deleteById(String id){
        return userRepository.deleteById(id);
    }

    public String findName(String id){
        return userRepository.findName(id);
    }
}
5.1 这里需要注意redis缓存的注解写法
@Cacheable(value="user", key = "#id") value指的是缓存域,key是 就是数据的key 呗,
可以值一种自定义的规则,也可以是直接用入参作为key
@CacheEvict(value="user",key = "#id" ) 是根据key在value域中清除缓存 
6 UserRepository类
@Repository
@Table(name="user")
public interface UserRepository extends CrudRepository<User,Long>{

    public User findUserById(String id);

    @Override
    List<User> findAll();

    User findByName(String name);

    int deleteById(String id);

    @Query("select u.name from User u where u.id= ?1")
    String findName(String id);
}

6.1

继承的 CrudRepository 类以及帮我们实现了一些常用的方法,比如findByXX ,XX与实体类中的属性对应

7 启动类

@ComponentScan(basePackages="com.ryz.cn.springbootvuemvc")
@EntityScan(basePackages="com.ryz.cn.springbootvuemvc.pojo")
@EnableJpaRepositories(basePackages="com.ryz.cn.springbootvuemvc.repository")
@SpringBootApplication
@EnableCaching
public class SpringbootvuemvcApplication {

   public static void main(String[] args) {
      SpringApplication.run(SpringbootvuemvcApplication.class, args);
   }
}

7.1 注意实体类的扫描路径@EntityScan(basePackages="com.ryz.cn.springbootvuemvc.pojo")@EnableCaching 开启缓存

8 redis配置类

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }
    @Bean
    public CacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        // cacheManager.setCacheNames(Arrays.asList("users", "emptyUsers"));
        cacheManager.setUsePrefix(true);
        // Number of seconds before expiration. Defaults to unlimited (0)
        cacheManager.setDefaultExpiration(1800L);
        return cacheManager;
    }

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory){

        RedisTemplate<Object, Object> template=new RedisTemplate<Object, Object>();

        template.setConnectionFactory(connectionFactory);
        //实现序列化和反序列化rediskey        template.setKeySerializer(new StringRedisSerializer());
        //实现序列化和反序列化redisvalue,默认使用JdkSerializationRedisSerializer
        //template.setValueSerializer(new RedisObjectSerializer());
        //template.setValueSerializer();
        return template;

    }

}
8.1 这里主要方法,
keyGenerator()  键的生成规则,自定义规则

cacheManager() 缓存管理器,这里 
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
需要注意下,根据不同的redis版本不同,构造方法一不一样,我遇到了很多坑

9 在resources 下面的templates 下创建index.html文件,结合了vuejs 和 Element ui 代码如下
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>用户管理</title>
    <link rel="stylesheet" href="//cdn.bootcss.com/element-ui/1.1.2/theme-default/index.css">
    <script src="//cdn.bootcss.com/vue/2.1.8/vue.min.js"></script>
    <script src="//cdn.bootcss.com/element-ui/1.1.2/index.js"></script>
    <script src="//cdn.bootcss.com/vue-resource/1.0.3/vue-resource.min.js"></script>

</head>
<body>
<div id="vm">

    <el-row :gutter="20">
        <el-col :span="6">
            <div class="grid-content bg-purple">
                <el-input
                        placeholder="请输入姓名查询"
                        v-model="searchName"
                        clearable>
                </el-input>
            </div>
        </el-col>

        <el-col :span="6">
            <div class="grid-content bg-purple">
                <el-button type="primary" icon="el-icon-search" v-on:click="search()">搜索</el-button>

            </div>
        </el-col>
        <el-col :span="6">
            <div class="grid-content bg-purple">
                <el-form :model="user">
                    <el-form-item label="姓名" :label-width="formLabelWidth">
                        <el-input v-model="user.name" auto-complete="off"></el-input>
                    </el-form-item>
                    <el-form-item label="年龄" :label-width="formLabelWidth">
                        <el-input-number v-model="user.age"  :min="1" :max="120" label="输入年龄"></el-input-number>
                    </el-form-item>
                </el-form>
            </div>
        </el-col>
        <el-col :span="6">
            <div class="grid-content bg-purple">
                <el-button type="success" @click="addNew()">新增用户</el-button>
            </div>
        </el-col>
    </el-row>

    <el-table
            :data="tableData"
            stripe
            style="width: 100%">
        <el-table-column
                prop="id"
                label="ID"
                width="180">
        </el-table-column>
        <el-table-column
                prop="name"
                label="姓名"
                width="180">
        </el-table-column>
        <el-table-column
                prop="age"
                label="年龄">
        </el-table-column>
        <el-table-column
                inline-template
                fixed="right"
                label="操作"
                width="200">
            <div>
                <el-button v-on:click="editH(row)" type="text" size="small">编辑</el-button>
                <el-button v-on:click="deleteH(row)" type="text" size="small">删除</el-button>
            </div>


        </el-table-column>
    </el-table>
</div>

<script>
    Vue.http.options.emulateHTTP = true;
    var vm = new Vue({
        el: '#vm',
        data: {
            tableData: [],
            searchName: '',
            searchId:'',
            dialogFormVisible: false,
            user:{id:"",name:'',age:''},
            formLabelWidth: '120px',
        },
        methods:{
            getData:function(){
                this.$http.get("/sh/user/getUsers")
                    .then(function (response) {
                    console.log(response);
                        this.tableData = response.body;
                    })
                    .catch(function (response) { console.error(response); });
            },
            search:function(){
                if(this.searchName==''){
                    return;
                }
                this.$http.get("/sh/user/getUserByOneId",{params: {id:this.searchId}})
                    .then(function (response) {
                        console.log(response);
                        this.tableData = [];
                        if(response.body!=''){
                            this.tableData.push(response.body);
                        }
                    })
                    .catch(function (response) { console.error(response); });
            },
            deleteH:function(row){
                    this.$confirm('此操作将永久删除该'+row+', 是否继续?', '提示', {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning'
                    }).then(() => {
                        this.$http.get("/sh/user/deleteById",{params: {id:row.id}})
                            .then(function (response) {
                                this.$message({
                                    type: 'success',
                                    message: '删除成功!'
                                });
                                this.getData();
                            })
                            .catch(function (response) { console.error(response); });


                    }).catch(() => {
                        this.$message({
                            type: 'info',
                            message: '已取消删除'
                        });
                    });

                console.log(row);

            },
            addNew:function(){
                this.$http.post("/sh/user/addOne",this.user)
                    .then(function (response) {
                        this.$message({
                            type: 'success',
                            message: '添加成功!'
                        });
                        this.getData();
                        this.user.id = '';
                    })
                    .catch(function (response) { console.error(response); });
            },
            editH:function(row){
                this.user = row;
            }

        },
        mounted: function () {
            this.getData();
        },
        watch:{
            searchName(nv,ov){
                for(var i=0;i<this.tableData.length;i++){
                    if(this.tableData[i].name == nv){
                        this.searchId = this.tableData[i].id;
                    }
                }

            }
        }

    })
</script>
</body>
</html>
10 数据库user表DDL
CREATE TABLE `user` (
  `id` varchar(255) NOT NULL,
  `name` varchar(10) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

11 页面展示:


删除用户


12 看一下在查询用户后的缓存


13 总结

本着练习的心态,做完了这个小demo,其实有很多没有完善,比如不能把js和css 都写在一个html文件中,最好分开来,Element ui 真的很强大,只是用了其中的冰山一角,业务太简单了,没有结合消息中间件和其他的项目通信。demo实在太简单了,没啥说的,只做学习吧。

14 github 地址: https://github.com/ryz-13997318136/springbootvuemvc.git

Logo

前往低代码交流专区

更多推荐