最近在学习使用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数据库索引(默认为0)
spring.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);
//实现序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
//实现序列化和反序列化redis的value值,默认使用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