1.介绍
环境:SpringBoot+Dubbo+Zookeeper
图片服务器:fastDFS
数据库:Mysql
2.环境搭建
需在linux上搭建Tomcat(为了访问zookeeper)、zookeeper、dubbo、fastDFS。
tomcat下载:https://tomcat.apache.org/
JDK下载:https://www.oracle.com/technetwork/java/javase/archive-139210.html
zookeeper下载:https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/
dubbo下载https://github.com/apache/dubbo/tree/2.5.x
这些请先自行搜索下!
安装教程后续会整理!
3.项目搭建
-
创建一个Maven工程(空壳)
-
分别创建api、basic、service、web四个模块
- api下创建avatar-api模块
- basic下创建common、entity、mapper
- service下创建SpringBoot项目avatar-service
- web下创建SpringBoot项目
结构如下:
-
模块导入
- avatar-api的pom.xml中分别导入common、entity、mapper模块
- 在avatart-service的pom.xml中导入common、entity、mapper、api模块
- avatar-background的pom.xml导入api模块。
数据库:
创建数据库表,因为是demo,所以这边只创建一张user表。
4.代码编写
一、编写共有接口
公共的mapper接口(增删改查)
public interface IBaseMapper<T> {
int deleteByPrimaryKey(Integer id);
int insert(T record);
int insertSelective(T record);
T selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(T record);
int updateByPrimaryKey(T record);
}
公共的service接口
public interface IBaseService<T> {
int deleteByPrimaryKey(Integer id);
int insert(T record);
int insertSelective(T record);
T selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(T record);
int updateByPrimaryKey(T record);
}
实现公共的service接口,并增加虚方法getBaseMapper()用来获取要操作的mapper对象。
public abstract class BaseServiceImp<T> implements IBaseService<T> {
public abstract IBaseMapper<T> getBaseMapper();
public int deleteByPrimaryKey(Integer id) {
return getBaseMapper().deleteByPrimaryKey(id);
}
public int insert(T record) {
return getBaseMapper().insert(record);
}
public int insertSelective(T record) {
return getBaseMapper().insertSelective(record);
}
public T selectByPrimaryKey(Integer id) {
return getBaseMapper().selectByPrimaryKey(id); }
public int updateByPrimaryKeySelective(T record) {
return getBaseMapper().updateByPrimaryKeySelective(record);
}
public int updateByPrimaryKey(T record) {
return getBaseMapper().updateByPrimaryKey(record);
}
}
二、编写entity模块
返回结果对象
package com.cm.avatar.pojo;
import java.io.Serializable;
public class ResultBean implements Serializable {
private Integer statusCode;
private String url;
private String msg;
public Integer getStatusCode() {
return statusCode;
}
public void setStatusCode(Integer statusCode) {
this.statusCode = statusCode;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
User的实体类
package com.cm.avatar.pojo;
import java.io.Serializable;
public class User implements Serializable {
private Integer id;
private String userName;
private String userImage;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName == null ? null : userName.trim();
}
public String getUserImage() {
return userImage;
}
public void setUserImage(String userImage) {
this.userImage = userImage == null ? null : userImage.trim();
}
}
三、编写mapper模块
UserMapper接口(其实这里只需要更新与查询操作,这边用mybatis-generator生成的)
package com.cm.avatar.mapper;
import com.cm.avatar.pojo.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper extends IBaseMapper<User>{
int deleteByPrimaryKey(Integer id);
int insert(User record);
int insertSelective(User record);
User selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(User record);
int updateByPrimaryKey(User record);
}
UserMapper.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cm.avatar.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.cm.avatar.pojo.User">
<id column="ID" jdbcType="INTEGER" property="id" />
<result column="user_name" jdbcType="VARCHAR" property="userName" />
<result column="user_image" jdbcType="VARCHAR" property="userImage" />
</resultMap>
<sql id="Base_Column_List">
ID, user_name, user_image
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from user
where ID = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from user
where ID = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.cm.avatar.pojo.User">
insert into user (ID, user_name, user_image
)
values (#{id,jdbcType=INTEGER}, #{userName,jdbcType=VARCHAR}, #{userImage,jdbcType=VARCHAR}
)
</insert>
<insert id="insertSelective" parameterType="com.cm.avatar.pojo.User">
insert into user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
ID,
</if>
<if test="userName != null">
user_name,
</if>
<if test="userImage != null">
user_image,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=INTEGER},
</if>
<if test="userName != null">
#{userName,jdbcType=VARCHAR},
</if>
<if test="userImage != null">
#{userImage,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.cm.avatar.pojo.User">
update user
<set>
<if test="userName != null">
user_name = #{userName,jdbcType=VARCHAR},
</if>
<if test="userImage != null">
user_image = #{userImage,jdbcType=VARCHAR},
</if>
</set>
where ID = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.cm.avatar.pojo.User">
update user
set user_name = #{userName,jdbcType=VARCHAR},
user_image = #{userImage,jdbcType=VARCHAR}
where ID = #{id,jdbcType=INTEGER}
</update>
</mapper>
四、编写api模块
package com.cm.avatar.api;
import com.cm.avatar.mapper.IBaseService;
import com.cm.avatar.pojo.ResultBean;
import com.cm.avatar.pojo.User;
public interface IUserService extends IBaseService<User> {
/**
* 修改头像
* @param id 用户id
* @param url 头像对应的地址
* @return
*/
ResultBean changeAvatar(String id, String url);
}
五、编写service模块
实现共有接口以及继承抽象类并实现getBaseMapper()方法。
注:这边的@Service注解是dubbo包下的注解。
package com.cm.avatar.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.cm.avatar.api.IUserService;
import com.cm.avatar.mapper.BaseServiceImp;
import com.cm.avatar.mapper.IBaseMapper;
import com.cm.avatar.mapper.UserMapper;
import com.cm.avatar.pojo.ResultBean;
import com.cm.avatar.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Service
public class UserService extends BaseServiceImp<User> implements IUserService {
@Autowired
private UserMapper userMapper;
@Override
public IBaseMapper<User> getBaseMapper() {
return userMapper;
}
@Override
public ResultBean changeAvatar(String id, String url) {
ResultBean resultBean = new ResultBean();
User user = new User();
user.setId(Integer.parseInt(id));
user.setUserImage(url);
int i = userMapper.updateByPrimaryKeySelective(user);
if (i == 1) {
resultBean.setStatusCode(200);
resultBean.setUrl(url);
return resultBean;
} else {
resultBean.setStatusCode(500);
resultBean.setMsg("未知错误");
return resultBean;
}
}
}
appication.yml
server:
port: 8080
dubbo:
application:
name: avatar-service
registry:
protocol: zookeeper
address: 192.168.1.14:2181
protocol:
port: 28801
spring:
datasource:
username: root
url: jdbc:mysql://localhost:3306/dubbo?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
当我们写好启动后,可以在zookeeper上(将zk打包放入tomcat)看到有name为avatar-service的提供者,代表服务发布成功
六、编写web模块
UserController:
注:如果是dubbo的服务注入时要用@Reference注解
package com.cm.avatar.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.cm.avatar.api.IUserService;
import com.cm.avatar.pojo.ResultBean;
import com.cm.avatar.pojo.User;
import com.cm.avatar.utils.UploadUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@Controller
@RequestMapping("user")
public class UserController {
@Reference
private IUserService userService;
@Value("${base-address}")
private String address;
@Autowired
UploadUtils uploadUtils;
@GetMapping("/get")
public String getAll(Model model) {
User user = userService.selectByPrimaryKey(1);
user.setUserImage(address + user.getUserImage());
model.addAttribute("user", user);
return "user/index";
}
@RequestMapping(value = "/upload/{Id}", method = RequestMethod.POST)
@ResponseBody
public ResultBean getAll(@RequestParam MultipartFile file, @PathVariable("Id") String id) {
System.out.println("进入了controller");
ResultBean upload = uploadUtils.upload(file);
if (upload.getStatusCode() == 200) {
System.out.println(upload.getUrl());
return userService.changeAvatar(id, upload.getUrl());
} else {
return upload;
}
}
}
编写上传工具类:
package com.cm.avatar.utils;
import com.cm.avatar.pojo.ResultBean;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@Component
public class UploadUtils {
@Autowired
private FastFileStorageClient fastFileStorageClient;
public ResultBean upload(MultipartFile file) {
//System.out.println("开始上传----");
ResultBean resultBean = new ResultBean();
String fileName = file.getOriginalFilename();
String substring = fileName.substring(fileName.lastIndexOf(".") + 1);
try {
StorePath storePath = fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(), substring, null);
resultBean.setStatusCode(200);
resultBean.setUrl(storePath.getGroup() + "/" + storePath.getPath());
return resultBean;
} catch (IOException e) {
e.printStackTrace();
resultBean.setStatusCode(500);
resultBean.setMsg("上传文件时发生错误");
return resultBean;
}
}
}
导入uploadifive.css与uploadifive.js与jquery.js
编写页面(简略)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>头像更改</title>
<script src="../../js/jquery.min.js"></script>
<script src="../../js/jquery.uploadifive.js"></script>
<link type="text/css" rel="styleSheet" href="../../css/uploadifive.css" />
</head>
<body>
<div style="text-align:center;margin:0 auto">
<h1 th:text="${user.userName}"></h1>
<img th:src="${user.userImage}" width="200" height="200" style="border:1px dashed #000">
<input type="file" id="image" name="file" class="uploadifive-button">
</div>
<script>
$('#image').uploadifive({
'uploadScript': '/user/upload/[[${user.Id}]]',
'buttonText': '更改头像',
'fileObjName': 'file',
'onUploadComplete': function (file,response) {
var json = JSON.parse(response);
if (json.statusCode == 200) {
$.ajax({
url: "/user/delete/?url=[[${user.userImage}]]",
type: 'DELETE',
success: function (data) {
window.location.replace("/user/get");
}
});
} else {
alert(json.msg)
}
}
})
</script>
</body>
</html>
5.成果展示
点击更改头像按钮进行更改,同时更新到页面
若文章有误,请读者指出,万分感谢!
若对您有帮忙请点个赞!手动笔芯~