今天就做这个,做完了之后仔细记录一下微服务运维,另外准备买一个华为服务器,下定决心了

工程结构划分

我们采用的是微服务的架构,我们现在已经有四个应用工程,随着项目越来越大,代码的可重用性和可维护性就会变得越来越难,所以尽早对工程结构进行合理的规划,对项目前期的开发,后端的扩展和维护都非常重要。
经过重新规划,我们的工程结构如下:

  • hc-common : 公共代码模块, 主要设置一些工具类
  • hc-core:核心业务代码模块,主要封装公共业务模块
  • hc-admin:后端服务层
  • hc-dao:后端交互层
  • hc-pom:聚合模块,仅为简化打包,一键执行打包所有模块

hc-common

1.新建hc-common模块

因为是主要存储工具类,新建util目录

微服务的模块化设计与常用模块设计,实现业务类,工具类,DAO ,Service,Controller分离_mysql


2.根据工具需要导入pom.xml

主要是本地截帧,阿里云OSS服务以及Spring Security

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--集成阿里云OSS服务-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.8.0</version>
</dependency>
<!--集成fastjson依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<!--JAVACV 截帧-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>4.0.2-1.4.3</version>
</dependency>

3.设计application.yml模块

因为是一个工具类,就不用写了

4.集成工具类具体工具

  • 显示图片视频,以及视频截帧工具
package cn.hcnet2006.common.util;

import cn.hcnet2006.common.http.HttpResult;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;

public class ImageAndVideoUtils {

public static void findImgName(String imgUrl, MultipartFile multipartFile)throws IOException {

//获得文件所在目录
File folder = new File(imgUrl);
//添加目录
if(!folder.isDirectory()){
folder.mkdirs();
}
try{
//转移加载文件
multipartFile.transferTo(folder);

}catch (Exception e){
e.printStackTrace();
}
}

public static String showImage(String imageUrl, HttpServletResponse response
)throws IOException{
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
response.setHeader("Pragma", "no-cache");
response.setContentType("image/jpeg");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
File file = new File(imageUrl);
BufferedImage bi = ImageIO.read(new FileInputStream(file));
ServletOutputStream out = response.getOutputStream();
ImageIO.write(bi,"jpg",out);
try{
out.flush();
}finally {
out.close();
}
return null;
}
/**
* 捕捉图片第一帧
* @throws Exception
*/
public static void fetchFrame(String videoUrl,String imgUrl)throws Exception{
//

FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(videoUrl);
Java2DFrameConverter converter = new Java2DFrameConverter();
frameGrabber.start();
//解码长度
int length = frameGrabber.getLengthInFrames();
//时间
int i = 0;
Frame frame = null;
while(i < length){
//过滤前五帧,避免出现全黑的图片
frame = frameGrabber.grabFrame();
if(i > 10 && (frame.image != null)){
break;
}
i ++;
}
// Frame frame = frameGrabber.grabFrame();
BufferedImage bufferedImage = converter.convert(frame);
//照片保存文件夹
File targetFile = new File(imgUrl);
//文件夹不存在就新建
if(!targetFile.isDirectory()){
targetFile.mkdirs();
}
//写入文件夹,以jpg图片格式
ImageIO.write(bufferedImage, "jpg", targetFile);
//停止转化为帧
frameGrabber.stop();
}

public static String showVideo( String videoUrl,HttpServletResponse response)throws IOException{
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
response.setHeader("Pragma", "no-cache");
response.setContentType("video/mp4");
FileInputStream fis = null;
OutputStream os = null ;
File file = new File(videoUrl);
fis = new FileInputStream(file);
int size = fis.available(); // 得到文件大小
byte data[] = new byte[size];
fis.read(data); // 读数据
fis.close();
fis = null;
response.setContentType("video/mp4"); // 设置返回的文件类型
os = response.getOutputStream();
os.write(data);
try{
os.flush();
}finally {
os.close();
}
return null;
}
}
  • 阿里云OSS工具
package cn.hcnet2006.common.util;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.CreateBucketRequest;
import com.aliyun.oss.model.PutObjectResult;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* OSS文件上传
*/
public class OSSUtils {
@Autowired
//private static OSSConstant ossConstant;
static String bucketName = "hcnet2006-file-apk";

static String accessKeyId = "LTAI4FnpucSRxxxx5AX";

static String accessKeySecret = "yuYPUaWjxxxxxLdC";

static String endpoint = "oss-cn-shenzhen.aliyuncs.com";
//private static OSS ossClient ;
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
public static String upload(File file,String apkName){
OSS ossClient = new OSSClientBuilder().build(endpoint,accessKeyId,
accessKeySecret);

System.out.println("进入OSS工具");

if(file == null){
return null;
}
String dateStr = sdf.format(new Date());


try{
//容器不存在就创建
if(!ossClient.doesBucketExist(bucketName)){
ossClient.createBucket(bucketName);
CreateBucketRequest cbr = new
CreateBucketRequest(bucketName);
cbr.setCannedACL(
CannedAccessControlList.Private
);
ossClient.createBucket(cbr);
}
//上传文件

InputStream is = new FileInputStream(file);
PutObjectResult result = ossClient.putObject(bucketName,apkName,file);
//System.out.println(result.getRequestId());
// String uri = result.getResponse().getUri();
// 设置这个文件地址的有效时间
Date expiration = new Date(new Date().getTime() + 3600l * 1000 * 24 * 365 * 10);

String url = ossClient.generatePresignedUrl(bucketName, apkName, expiration).toString();

System.out.println("object:"+apkName+"存入成功");
System.out.println("上传路径:"+url);
url = url.substring(0,url.indexOf("?"));
return url;
}catch (OSSException oe){
oe.printStackTrace();
}catch (ClientException | FileNotFoundException ce){
ce.printStackTrace();
}finally{
ossClient.shutdown();
}
return null;
}
  • 密码加密工具
package cn.hcnet2006.common.util;


import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class PassWordEncoderUtils {
private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
public static String BCryptPassword(String password){
return encoder.encode(password);
}
public static boolean matches(CharSequence rawPassword, String encodedPassword){
return encoder.matches(rawPassword,encodedPassword);
}
}
  • 代码映射工具
package cn.hcnet2006.common.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
* 反射相关辅助方法
* @author Louis
* @date Aug 19, 2018
*/
public class ReflectionUtils {


/**
* 根据方法名调用指定对象的方法
* @param object 要调用方法的对象
* @param method 要调用的方法名
* @param args 参数对象数组
* @return
*/
public static Object invoke(Object object, String method, Object... args) {
Object result = null;
Class<? extends Object> clazz = object.getClass();
System.out.println("class:"+clazz.getName());
System.out.println("method:"+method);
System.out.println("args:"+args.toString());
Method queryMethod = getMethod(clazz, method, args);
if(queryMethod != null) {
try {
result = queryMethod.invoke(object, args);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} else {
System.out.println("method is null");
try {
throw new NoSuchMethodException(clazz.getName() + " 类中没有找到 " + method + " 方法。");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
return result;
}

/**
* 根据方法名和参数对象查找方法
* @param clazz
* @param name
* @param args 参数实例数据
* @return
*/
public static Method getMethod(Class<? extends Object> clazz, String name, Object[] args) {
Method queryMethod = null;
System.out.println("the method we are find");
System.out.println("see all method");
Method[] methods = clazz.getMethods();
for(Method method:methods) {
System.out.println("method:"+method.getName());
if(method.getName().equals(name)) {
Class<?>[] parameterTypes = method.getParameterTypes();
System.out.println("the ards length we are find is:"+args.length);
System.out.println("the ards length will be compared:"+parameterTypes.length);

if(parameterTypes.length == args.length) {
boolean isSameMethod = true;
for(int i=0; i<parameterTypes.length; i++) {
Object arg = args[i];
if(arg == null) {
arg = "";
}
System.out.println("type of the method we are find:"+args[i].getClass().toString());
System.out.println("type of the method will be compared:"+parameterTypes[i].toString());
if(!parameterTypes[i].equals(args[i].getClass())) {
isSameMethod = false;
System.out.println("类型不一样");
}
}
if(isSameMethod) {
queryMethod = method;
break ;
}
}
}
}
return queryMethod;
}
}
  • 存储工具
package cn.hcnet2006.common.util;

import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

public class StroageUtil {
public static String store(MultipartFile file) throws IOException {
String url = "/usr/local/spring/"+ file.getOriginalFilename();
File folder = new File(url);
if (!folder.isDirectory()){
folder.mkdirs();
}
file.transferTo(folder);
return url;
}
}
  1. 删除启动类和测试类

hc-core模块

1.新建hc-common模块
hc-core模块主要是集成Http交互格式的封装,业务基类封装和分页工具封装,全局异常封装,代码生成器封装,富文本编辑器封装等

微服务的模块化设计与常用模块设计,实现业务类,工具类,DAO ,Service,Controller分离_mysql_02


2.设置pom.xml文件

<!--添加hc-common依赖-->
<dependency>
<groupId>cn.hcnet2006.common</groupId>
<artifactId>hc-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--添加MyBatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot</artifactId>
<version>2.1.1</version>
</dependency>
<!--添加MyBatis生成器-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
<!--MYBatis分页查询-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.13</version>
</dependency>
<!--MYSQL驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<!--Druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
<!--集成swagger2文档-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>

这里集成hc-common依赖
3.设置application.yml

#server:
# port: 8211 #应用端口
spring:
application:
name: hc-core #应用名
cloud:
consul: #服务发现
host: 127.0.0.1
port: 8500
discovery:
service-name: ${spring.application.name}
enabled: true
servlet: #上传配置
multipart:
enabled: true
file-size-threshold: 0
max-file-size: 1000MB
max-request-size: 1000MB
resolve-lazily: false
datasource: #数据库配置
name: druidDataSource
type: com.alibaba.druid.pool.DruidDataSource
druid:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///hc_official_website_1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
filters: stat, wall, config
initial-size: 1
max-active: 100
max-wait: 60000
min-idle: 1
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: select 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true
max-open-prepared-statements: 50
max-pool-prepared-statement-per-connection-size: 20
filter:
wall:
config:
multi-statement-allow: true #允许一次批量更新操作,会导致SQL注入

mybatis: #Mybaytis映射文件位置
mapper-locations: classpath:/mappers/*Mapper.xml
configuration:
aggressive-lazy-loading: false #当参数设置为false时,对任意延迟属性的调用都将按需加载

4.具体业务封装

  1. 设置pom.xml文件
  • 全局异常
public class UserLoginException extends RuntimeException{
public UserLoginException(String message) {
super(message);
}
}
  • HTTP交互格式封装
package cn.hcnet2006.core.http;

/**
* HTTP结果封装
* @author Louis
* @date Jan 12, 2019
*/
public class HttpResult {

private int code = 200;
private String msg;
private Object data;

public static HttpResult error() {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
}

public static HttpResult error(String msg) {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
}

public static HttpResult error(int code, String msg) {
HttpResult r = new HttpResult();
r.setCode(code);
r.setMsg(msg);
return r;
}

public static HttpResult ok(String msg) {
HttpResult r = new HttpResult();
r.setMsg(msg);
return r;
}

public static HttpResult ok(Object data) {
HttpResult r = new HttpResult();
r.setData(data);
return r;
}

public static HttpResult ok() {
return new HttpResult();
}

public int getCode() {
return code;
}

public void setCode(int code) {
this.code = code;
}

public String getMsg() {
return msg;
}

public void setMsg(String msg) {
this.msg = msg;
}

public Object getData() {
return data;
}

public void setData(Object data) {
this.data = data;
}

}
package cn.hcnet2006.core.http;

public interface HttpStatus {

// --- 1xx Informational ---

/** {@code 100 Continue} (HTTP/1.1 - RFC 2616) */
public static final int SC_CONTINUE = 100;
/** {@code 101 Switching Protocols} (HTTP/1.1 - RFC 2616)*/
public static final int SC_SWITCHING_PROTOCOLS = 101;
/** {@code 102 Processing} (WebDAV - RFC 2518) */
public static final int SC_PROCESSING = 102;

// --- 2xx Success ---

/** {@code 200 OK} (HTTP/1.0 - RFC 1945) */
public static final int SC_OK = 200;
/** {@code 201 Created} (HTTP/1.0 - RFC 1945) */
public static final int SC_CREATED = 201;
/** {@code 202 Accepted} (HTTP/1.0 - RFC 1945) */
public static final int SC_ACCEPTED = 202;
/** {@code 203 Non Authoritative Information} (HTTP/1.1 - RFC 2616) */
public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;
/** {@code 204 No Content} (HTTP/1.0 - RFC 1945) */
public static final int SC_NO_CONTENT = 204;
/** {@code 205 Reset Content} (HTTP/1.1 - RFC 2616) */
public static final int SC_RESET_CONTENT = 205;
/** {@code 206 Partial Content} (HTTP/1.1 - RFC 2616) */
public static final int SC_PARTIAL_CONTENT = 206;
/**
* {@code 207 Multi-Status} (WebDAV - RFC 2518)
* or
* {@code 207 Partial Update OK} (HTTP/1.1 - draft-ietf-http-v11-spec-rev-01?)
*/
public static final int SC_MULTI_STATUS = 207;

// --- 3xx Redirection ---

/** {@code 300 Mutliple Choices} (HTTP/1.1 - RFC 2616) */
public static final int SC_MULTIPLE_CHOICES = 300;
/** {@code 301 Moved Permanently} (HTTP/1.0 - RFC 1945) */
public static final int SC_MOVED_PERMANENTLY = 301;
/** {@code 302 Moved Temporarily} (Sometimes {@code Found}) (HTTP/1.0 - RFC 1945) */
public static final int SC_MOVED_TEMPORARILY = 302;
/** {@code 303 See Other} (HTTP/1.1 - RFC 2616) */
public static final int SC_SEE_OTHER = 303;
/** {@code 304 Not Modified} (HTTP/1.0 - RFC 1945) */
public static final int SC_NOT_MODIFIED = 304;
/** {@code 305 Use Proxy} (HTTP/1.1 - RFC 2616) */
public static final int SC_USE_PROXY = 305;
/** {@code 307 Temporary Redirect} (HTTP/1.1 - RFC 2616) */
public static final int SC_TEMPORARY_REDIRECT = 307;

// --- 4xx Client Error ---

/** {@code 400 Bad Request} (HTTP/1.1 - RFC 2616) */
public static final int SC_BAD_REQUEST = 400;
/** {@code 401 Unauthorized} (HTTP/1.0 - RFC 1945) */
public static final int SC_UNAUTHORIZED = 401;
/** {@code 402 Payment Required} (HTTP/1.1 - RFC 2616) */
public static final int SC_PAYMENT_REQUIRED = 402;
/** {@code 403 Forbidden} (HTTP/1.0 - RFC 1945) */
public static final int SC_FORBIDDEN = 403;
/** {@code 404 Not Found} (HTTP/1.0 - RFC 1945) */
public static final int SC_NOT_FOUND = 404;
/** {@code 405 Method Not Allowed} (HTTP/1.1 - RFC 2616) */
public static final int SC_METHOD_NOT_ALLOWED = 405;
/** {@code 406 Not Acceptable} (HTTP/1.1 - RFC 2616) */
public static final int SC_NOT_ACCEPTABLE = 406;
/** {@code 407 Proxy Authentication Required} (HTTP/1.1 - RFC 2616)*/
public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
/** {@code 408 Request Timeout} (HTTP/1.1 - RFC 2616) */
public static final int SC_REQUEST_TIMEOUT = 408;
/** {@code 409 Conflict} (HTTP/1.1 - RFC 2616) */
public static final int SC_CONFLICT = 409;
/** {@code 410 Gone} (HTTP/1.1 - RFC 2616) */
public static final int SC_GONE = 410;
/** {@code 411 Length Required} (HTTP/1.1 - RFC 2616) */
public static final int SC_LENGTH_REQUIRED = 411;
/** {@code 412 Precondition Failed} (HTTP/1.1 - RFC 2616) */
public static final int SC_PRECONDITION_FAILED = 412;
/** {@code 413 Request Entity Too Large} (HTTP/1.1 - RFC 2616) */
public static final int SC_REQUEST_TOO_LONG = 413;
/** {@code 414 Request-URI Too Long} (HTTP/1.1 - RFC 2616) */
public static final int SC_REQUEST_URI_TOO_LONG = 414;
/** {@code 415 Unsupported Media Type} (HTTP/1.1 - RFC 2616) */
public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;
/** {@code 416 Requested Range Not Satisfiable} (HTTP/1.1 - RFC 2616) */
public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
/** {@code 417 Expectation Failed} (HTTP/1.1 - RFC 2616) */
public static final int SC_EXPECTATION_FAILED = 417;

/**
* Static constant for a 418 error.
* {@code 418 Unprocessable Entity} (WebDAV drafts?)
* or {@code 418 Reauthentication Required} (HTTP/1.1 drafts?)
*/
// not used
// public static final int SC_UNPROCESSABLE_ENTITY = 418;

/**
* Static constant for a 419 error.
* {@code 419 Insufficient Space on Resource}
* (WebDAV - draft-ietf-webdav-protocol-05?)
* or {@code 419 Proxy Reauthentication Required}
* (HTTP/1.1 drafts?)
*/
public static final int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419;
/**
* Static constant for a 420 error.
* {@code 420 Method Failure}
* (WebDAV - draft-ietf-webdav-protocol-05?)
*/
public static final int SC_METHOD_FAILURE = 420;
/** {@code 422 Unprocessable Entity} (WebDAV - RFC 2518) */
public static final int SC_UNPROCESSABLE_ENTITY = 422;
/** {@code 423 Locked} (WebDAV - RFC 2518) */
public static final int SC_LOCKED = 423;
/** {@code 424 Failed Dependency} (WebDAV - RFC 2518) */
public static final int SC_FAILED_DEPENDENCY = 424;

// --- 5xx Server Error ---

/** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */
public static final int SC_INTERNAL_SERVER_ERROR = 500;
/** {@code 501 Not Implemented} (HTTP/1.0 - RFC 1945) */
public static final int SC_NOT_IMPLEMENTED = 501;
/** {@code 502 Bad Gateway} (HTTP/1.0 - RFC 1945) */
public static final int SC_BAD_GATEWAY = 502;
/** {@code 503 Service Unavailable} (HTTP/1.0 - RFC 1945) */
public static final int SC_SERVICE_UNAVAILABLE = 503;
/** {@code 504 Gateway Timeout} (HTTP/1.1 - RFC 2616) */
public static final int SC_GATEWAY_TIMEOUT = 504;
/** {@code 505 HTTP Version Not Supported} (HTTP/1.1 - RFC 2616) */
public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

/** {@code 507 Insufficient Storage} (WebDAV - RFC 2518) */
public static final int SC_INSUFFICIENT_STORAGE = 507;

}
  • 业务基类封装
package cn.hcnet2006.core.service;



import cn.hcnet2006.core.page.PageRequest;
import cn.hcnet2006.core.page.PageResult;

import java.util.List;

/**
* 通用CURD 接口
* @param <T>
*/
public interface CurdService<T> {
/**
* 保存操作
* @param record
* @return
*/
int save(T record);

/**
* 删除操作
* @param record
* @return
*/
int delete(T record);

/**
* 批量删除操作
* @param records
* @return
*/
int delete(List<T> records);

/**
* 根据ID查询
* @param id
* @return
*/
T findById(Long id);

/**
* 分页查询
* @param pageRequest
* @return
*/
PageResult findPage(PageRequest pageRequest);

/**
* 修改操作
* @param record
* @return
*/
int update(T record);

/**
* 批量修改操作
* @param records
* @return
*/
int update(List<T> records);

}
  • 分页工具封装
package cn.hcnet2006.core.page;


import cn.hcnet2006.common.util.ReflectionUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import java.util.List;

/**
* MyBatis 分页查询助手
* @author Louis
* @date Jan 12, 2019
*/
public class MybatisPageHelper {

public static final String findPage = "findPage";

/**
* 分页查询, 约定查询方法名为 “findPage”
* @param pageRequest 分页请求
* @param mapper Dao对象,MyBatis的 Mapper
* @param
* @return
*/
public static PageResult findPage(PageRequest pageRequest, Object mapper) {
return findPage(pageRequest, mapper, findPage);
}

/**
* 调用分页插件进行分页查询
* @param pageRequest 分页请求
* @param mapper Dao对象,MyBatis的 Mapper
* @param queryMethodName 要分页的查询方法名
* @param args 方法参数
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static PageResult findPage(PageRequest pageRequest, Object mapper, String queryMethodName, Object... args) {
// 设置分页参数
int pageNum = pageRequest.getPageNum();
int pageSize = pageRequest.getPageSize();
PageHelper.startPage(pageNum, pageSize);
// 利用反射调用查询方法
Object result = ReflectionUtils.invoke(mapper, queryMethodName, args);
if(result == null){
System.out.println("result is null");
}
return getPageResult(pageRequest, new PageInfo((List) result));
}

/**
* 将分页信息封装到统一的接口
* @param pageRequest
* @param
* @return
*/
private static PageResult getPageResult(PageRequest pageRequest, PageInfo<?> pageInfo) {
PageResult pageResult = new PageResult();
pageResult.setPageNum(pageInfo.getPageNum());
pageResult.setPageSize(pageInfo.getPageSize());
pageResult.setTotalSize(pageInfo.getTotal());
pageResult.setTotalPages(pageInfo.getPages());
pageResult.setContent(pageInfo.getList());
return pageResult;
}

}
package cn.hcnet2006.core.page;

import java.util.HashMap;
import java.util.Map;

public class PageRequest {
/**
* 当前页码
*/
private int pageNum = 1;
/**
* 每页数量
*/
private int pageSize = 10;

public PageRequest(int pageNum, int pageSize, Map<String, Object> params) {
this.pageNum = pageNum;
this.pageSize = pageSize;
this.params = params;
}

/**
* 查询参数
*/

private Map<String, Object> params = new HashMap<>();

public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public Map<String, Object> getParams() {
return params;
}
public void setParams(Map<String, Object> params) {
this.params = params;
}
public Object getParam(String key) {
return getParams().get(key);
}

}
package cn.hcnet2006.core.page;

import java.util.List;

/**
* 分页返回结果
* @author Louis
* @date Jan 12, 2019
*/
public class PageResult {
/**
* 当前页码
*/
private int pageNum;
/**
* 每页数量
*/
private int pageSize;
/**
* 记录总数
*/
private long totalSize;
/**
* 页码总数
*/
private int totalPages;
/**
* 分页数据
*/
private List<?> content;
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public long getTotalSize() {
return totalSize;
}
public void setTotalSize(long totalSize) {
this.totalSize = totalSize;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public List<?> getContent() {
return content;
}
public void setContent(List<?> content) {
this.content = content;
}
}

5.删去启动类和test

  1. 我想了一下,集成一下代码生成器试一试
<!--添加MyBatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot</artifactId>
<version>2.1.1</version>
</dependency>
<!--添加MyBatis生成器-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
<!--MYBatis分页查询-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.13</version>
</dependency>
<!--MYSQL驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<!--Druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
<!--集成swagger2文档-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
  1. 设置application.yml
:
port: 8211 #应用端口
spring:
application:
name: hc-admin #应用名
cloud:
consul: #服务发现
host: 127.0.0.1
port: 8500
discovery:
service-name: ${spring.application.name}
enabled: true
servlet: #上传配置
multipart:
enabled: true
file-size-threshold: 0
max-file-size: 1000MB
max-request-size: 1000MB
resolve-lazily: false
datasource: #数据库配置
name: druidDataSource
type: com.alibaba.druid.pool.DruidDataSource
druid:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///hc_official_website_1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
filters: stat, wall, config
initial-size: 1
max-active: 100
max-wait: 60000
min-idle: 1
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: select 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true
max-open-prepared-statements: 50
max-pool-prepared-statement-per-connection-size: 20
filter:
wall:
config:
multi-statement-allow: true #允许一次批量更新操作,会导致SQL注入

mybatis: #Mybaytis映射文件位置
mapper-locations: classpath:/mappers/*Mapper.xml
configuration:
aggressive-lazy-loading: false #当参数设置为false时,对任意延迟属性的调用都将按需加载
  1. 接入MyBatis代码生成器
  • 代码生成器映射文件目录
  • xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--1. context属性targetRuntime设置为MyBatis3Simple避免生成Example相关的代码和方法,
如果需要Example设置为MyBatis3
2. context属性defaultModelType设为flat,目的是使每张表只生成一个实体类
3. 因为此处使用的数据库为MySql,所以前后分隔符都设置为‘‘’
4. 注释生成器commentGenerator中配置了生成数据库的注释信息,并且禁止在注释中生成日期
5. jdbcConnection简单的配置了要链接的数据源信息
6. javaModelGenerator配置生成的包名为com.hcnet2006.mango,
targetProject设置为src\main\java
7. sqlMapGenerator配置生成的Mapper.xml文件位置,这里采用XMLMapper类型。接口和XML完全分离
8. javaClientGenerator配置生成Mapper接口的位置,这里采用的XMLMAPPER类型,接口和XML完全分离
9. 最后的table使用通配符匹配数据库中所有的表,所有表都有主键自赠的id字段,
sqlStatement针对当前数据库配置MYSQL
-->

<context id="MySqlTables"
targetRuntime="MyBatis3Simple"
defaultModelType="flat">
<!--关键字与分隔符加反引号-->
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!--序列化以及字符串插件-->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<!--注释生成器-->
<commentGenerator>
<!--是否阻止生成注释-->
<property name="suppressAllComments" value="true"/>
<!--是否生成带注释的时间戳-->
<property name="suppressDate" value="true"/>
<!--是否添加数据表的备注信息-->
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<!--JDBC数据源连接-->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/hc_official_website_1?serverTimezone=UTC"
userId="root"
password="123456"


>
<!--确定一个数据库-->
<property name="nullCatalogMeansCurrent" value="true"/>

</jdbcConnection>
<!--实体类代码生成器-->
<javaModelGenerator targetPackage="cn.hcnet2006.admin.bean" targetProject="./hc-admin/src/main/java">
<!-- <property name="trimStrings" value="true"/>-->
</javaModelGenerator>
<!--MapperXML文件生成器-->
<sqlMapGenerator targetPackage="mappers" targetProject="./hc-admin/src/main/resources"/>
<!--Mappper接口生成器-->
<javaClientGenerator type="XMLMAPPER" targetPackage="cn.hcnet2006.admin.mapper" targetProject="./hc-admin/src/main/java"/>
<!--数据库表配置-->

<table tableName="sys_role_dept">
<!--数据库主键生成策略-->
<generatedKey column="id" sqlStatement="Mysql"/>
</table>
</context>
</generatorConfiguration>
  • java启动器
public class Generator {
public static void main(String []args) throws Exception{
//MBG执行过程中的警告信息
List<String> warnings = new ArrayList<>();
//当前代码重复时,覆盖旧的代码
boolean overwrite = true;
//读取BMG配置文件
InputStream is = Generator.class.getResourceAsStream(
"/generator/generatorConfig.xml");
//配置解析器
ConfigurationParser cp = new ConfigurationParser(warnings);
//配置器
Configuration config = cp.parseConfiguration(is);
//关闭输入流
is.close();
//默认回滚
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
//创建MBG
MyBatisGenerator mbg = new MyBatisGenerator(config,callback,warnings);
//执行生成代码
mbg.generate(null);
//输出警告信息
for(String warn: warnings){
System.out.println(warn);
}
}
}
  • Mybatis映射位置
: #Mybaytis映射文件位置
mapper-locations: classpath:/mappers/*Mapper.xml
configuration:
aggressive-lazy-loading: false #当参数设置为false时,对任意延迟属性的调用都将按需加载
  • 测试成功
  • 微服务的模块化设计与常用模块设计,实现业务类,工具类,DAO ,Service,Controller分离_spring_03

  • 集成富文本编辑器业务类
    重写bean
package cn.hcnet2006.core.ueditor;

public class Ueditor {
private String state;
private String url;
private String title;
private String original;

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getOriginal() {
return original;
}

public void setOriginal(String original) {
this.original = original;
}
}

重写PublicMsg

package cn.hcnet2006.core.ueditor;

public class PublicMsg {
public final static String UEDITOR_CONFIG = "{\n" +
" \"imageActionName\": \"uploadimage\",\n" +
" \"imageFieldName\": \"upfile\",\n" +
" \"imageMaxSize\": 2048000,\n" +
" \"imageAllowFiles\": [\".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\"],\n" +
" \"imageCompressEnable\": true,\n" +
" \"imageCompressBorder\": 1600,\n" +
" \"imageInsertAlign\": \"none\",\n" +
" \"imageUrlPrefix\": \"\",\n" +
" \"imagePathFormat\": \"/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}\",\n" +
"\n" +
" \"scrawlActionName\": \"uploadscrawl\",\n" +
" \"scrawlFieldName\": \"upfile\",\n" +
" \"scrawlPathFormat\": \"/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}\",\n" +
" \"scrawlMaxSize\": 2048000,\n" +
" \"scrawlUrlPrefix\": \"\",\n" +
" \"scrawlInsertAlign\": \"none\",\n" +
"\n" +
" \"snapscreenActionName\": \"uploadimage\",\n" +
" \"snapscreenPathFormat\": \"/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}\",\n" +
" \"snapscreenUrlPrefix\": \"\",\n" +
" \"snapscreenInsertAlign\": \"none\",\n" +
"\n" +
" \"catcherLocalDomain\": [\"127.0.0.1\", \"localhost\", \"img.baidu.com\"],\n" +
" \"catcherActionName\": \"catchimage\",\n" +
" \"catcherFieldName\": \"source\",\n" +
" \"catcherPathFormat\": \"/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}\",\n" +
" \"catcherUrlPrefix\": \"\",\n" +
" \"catcherMaxSize\": 2048000,\n" +
" \"catcherAllowFiles\": [\".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\"],\n" +
"\n" +
" \"videoActionName\": \"uploadvideo\",\n" +
" \"videoFieldName\": \"upfile\",\n" +
" \"videoPathFormat\": \"/ueditor/jsp/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}\",\n" +
" \"videoUrlPrefix\": \"\",\n" +
" \"videoMaxSize\": 102400000,\n" +
" \"videoAllowFiles\": [\n" +
" \".flv\", \".swf\", \".mkv\", \".avi\", \".rm\", \".rmvb\", \".mpeg\", \".mpg\",\n" +
" \".ogg\", \".ogv\", \".mov\", \".wmv\", \".mp4\", \".webm\", \".mp3\", \".wav\", \".mid\"],\n" +
"\n" +
" \"fileActionName\": \"uploadfile\",\n" +
" \"fileFieldName\": \"upfile\",\n" +
" \"filePathFormat\": \"/ueditor/jsp/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}\",\n" +
" \"fileUrlPrefix\": \"\",\n" +
" \"fileMaxSize\": 51200000,\n" +
" \"fileAllowFiles\": [\n" +
" \".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\",\n" +
" \".flv\", \".swf\", \".mkv\", \".avi\", \".rm\", \".rmvb\", \".mpeg\", \".mpg\",\n" +
" \".ogg\", \".ogv\", \".mov\", \".wmv\", \".mp4\", \".webm\", \".mp3\", \".wav\", \".mid\",\n" +
" \".rar\", \".zip\", \".tar\", \".gz\", \".7z\", \".bz2\", \".cab\", \".iso\",\n" +
" \".doc\", \".docx\", \".xls\", \".xlsx\", \".ppt\", \".pptx\", \".pdf\", \".txt\", \".md\", \".xml\"\n" +
" ],\n" +
"\n" +
" \"imageManagerActionName\": \"listimage\",\n" +
" \"imageManagerListPath\": \"/ueditor/jsp/upload/image/\",\n" +
" \"imageManagerListSize\": 20,\n" +
" \"imageManagerUrlPrefix\": \"\",\n" +
" \"imageManagerInsertAlign\": \"none\",\n" +
" \"imageManagerAllowFiles\": [\".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\"],\n" +
"\n" +
" \"fileManagerActionName\": \"listfile\",\n" +
" \"fileManagerListPath\": \"/ueditor/jsp/upload/file/\",\n" +
" \"fileManagerUrlPrefix\": \"\",\n" +
" \"fileManagerListSize\": 20,\n" +
" \"fileManagerAllowFiles\": [\n" +
" \".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\",\n" +
" \".flv\", \".swf\", \".mkv\", \".avi\", \".rm\", \".rmvb\", \".mpeg\", \".mpg\",\n" +
" \".ogg\", \".ogv\", \".mov\", \".wmv\", \".mp4\", \".webm\", \".mp3\", \".wav\", \".mid\",\n" +
" \".rar\", \".zip\", \".tar\", \".gz\", \".7z\", \".bz2\", \".cab\", \".iso\",\n" +
" \".doc\", \".docx\", \".xls\", \".xlsx\", \".ppt\", \".pptx\", \".pdf\", \".txt\", \".md\", \".xml\"\n" +
" ] \n" +
"\n" +
"}";
/**
* Ueditor的返回状态类型
*/
public enum UeditorMsg{
SUCCESS("SUCCESS"),ERROR("上传失败");
private String v;
UeditorMsg(String v){
this.v =v;
}
public String get(){
return this.v;
}
}
}
  • 控制层
package cn.hcnet2006.core.controller;

import cn.hcnet2006.common.util.OSSUtils;
import cn.hcnet2006.core.ueditor.PublicMsg;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Controller
public class UeditorController {
@RequestMapping("/")
private String showPage(){
return "index";
}
@RequestMapping("/content")
@ResponseBody
public String findContent(String content, String content1) throws IOException {
System.out.println("content1:"+content1);
String url = ResourceUtils.getURL("").getPath()+UUID.randomUUID().toString()+".html";
File folder = new File(url);
FileWriter fileWriter = new FileWriter(folder);
fileWriter.write(content1);
fileWriter.flush();
fileWriter.close();
url = OSSUtils.upload(folder,UUID.randomUUID().toString()+".html");

System.out.println("content:"+url);
return url;
}
@RequestMapping(value="/ueditor")
@ResponseBody
public String ueditor(HttpServletRequest request) {

return PublicMsg.UEDITOR_CONFIG;
}

@RequestMapping(value="/imgUpload")
@ResponseBody
public Map<String, Object> images (MultipartFile upfile, HttpServletRequest request, HttpServletResponse response){
Map<String, Object> params = new HashMap<String, Object>();
System.out.println("1111111111111");
try{
String url = ResourceUtils.getURL("").getPath()+upfile.getOriginalFilename();
File folder = new File(url);
upfile.transferTo(folder);
url = OSSUtils.upload(folder, UUID.randomUUID().toString()+upfile.getOriginalFilename().substring(upfile.getOriginalFilename().lastIndexOf(".")));
System.out.println(UUID.randomUUID().toString()+upfile.getOriginalFilename().substring(upfile.getOriginalFilename().lastIndexOf(".")));
folder.delete();
String fileName = upfile.getOriginalFilename();
params.put("state", "SUCCESS");
params.put("url", url);
params.put("size", upfile.getSize());
params.put("original", fileName);
params.put("type", upfile.getContentType());

} catch (Exception e){
params.put("state", "ERROR");
}
return params;
}

@RequestMapping(value="/videoUpload")
@ResponseBody
public Map<String, Object> videos (MultipartFile upfile, HttpServletRequest request, HttpServletResponse response){
Map<String, Object> params = new HashMap<String, Object>();
System.out.println("1111111111111");
try{
String url = ResourceUtils.getURL("").getPath()+upfile.getOriginalFilename();
File folder = new File(url);
upfile.transferTo(folder);
url = OSSUtils.upload(folder, UUID.randomUUID().toString()+upfile.getOriginalFilename().substring(upfile.getOriginalFilename().lastIndexOf(".")));
System.out.println(UUID.randomUUID().toString()+upfile.getOriginalFilename().substring(upfile.getOriginalFilename().lastIndexOf(".")));
folder.delete();
String fileName = upfile.getOriginalFilename();
params.put("state", "SUCCESS");
params.put("url", url);
params.put("size", upfile.getSize());
params.put("original", fileName);
params.put("type", upfile.getContentType());

} catch (Exception e){
params.put("state", "ERROR");
}
return params;
}

@RequestMapping(value="/fileUpload")
@ResponseBody
public Map<String, Object> files (MultipartFile upfile, HttpServletRequest request, HttpServletResponse response){
Map<String, Object> params = new HashMap<String, Object>();
System.out.println("1111111111111");
try{
String url = ResourceUtils.getURL("").getPath()+upfile.getOriginalFilename();
File folder = new File(url);
upfile.transferTo(folder);
url = OSSUtils.upload(folder, UUID.randomUUID().toString()+upfile.getOriginalFilename().substring(upfile.getOriginalFilename().lastIndexOf(".")));
System.out.println(UUID.randomUUID().toString()+upfile.getOriginalFilename().substring(upfile.getOriginalFilename().lastIndexOf(".")));
folder.delete();
String fileName = upfile.getOriginalFilename();
params.put("state", "SUCCESS");
params.put("url", url);
params.put("size", upfile.getSize());
params.put("original", fileName);
params.put("type", upfile.getContentType());

} catch (Exception e){
params.put("state", "ERROR");
}
return params;
}
}

hc-dao

hc-admin主要用于数据层的设计
1.pom

<!--添加MyBatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot</artifactId>
<version>2.1.1</version>
</dependency>
<!--添加MyBatis生成器-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
<!--MYBatis分页查询-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.13</version>
</dependency>
<!--MYSQL驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<!--Druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>

2.application.yml

spring:
servlet: #上传配置
multipart:
enabled: true
file-size-threshold: 0
max-file-size: 1000MB
max-request-size: 1000MB
resolve-lazily: false
datasource: #数据库配置
name: druidDataSource
type: com.alibaba.druid.pool.DruidDataSource
druid:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///hc_official_website_1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
filters: stat, wall, config
initial-size: 1
max-active: 100
max-wait: 60000
min-idle: 1
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: select 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true
max-open-prepared-statements: 50
max-pool-prepared-statement-per-connection-size: 20
filter:
wall:
config:
multi-statement-allow: true #允许一次批量更新操作,会导致SQL注入
mybatis: #Mybaytis映射文件位置
mapper-locations: classpath:/mappers/*Mapper.xml
configuration:
aggressive-lazy-loading: false #当参数设置为false时,对任意延迟属性的调用都将按需加载

3.系统结构

由于包扫描器的缘故,需要把该目录置于web启动器统一目录或者子目录之下

微服务的模块化设计与常用模块设计,实现业务类,工具类,DAO ,Service,Controller分离_mysql_04

hc-admin

本来是想做登录的模块。不过最后做成了服务层
1.pom文件

<!--集成hc-dao-->
<dependency>
<groupId>cn.hcnet2006.dao</groupId>
<artifactId>hc-dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--集成hc-core-->
<dependency>
<groupId>cn.hcnet2006.core</groupId>
<artifactId>hc-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--OAuth2依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<!--JSON WEB TOKEN-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!--添加MyBatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot</artifactId>
<version>2.1.1</version>
</dependency>
<!--添加MyBatis生成器-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
<!--MYBatis分页查询-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.13</version>
</dependency>
<!--MYSQL驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<!--Druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
<!-- <!&ndash;健康监控&ndash;>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- <!&ndash;集成服务发现&ndash;>-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- <!&ndash;集成配置&ndash;>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-config</artifactId>-->
<!-- </dependency>-->
<!-- <!&ndash;集成服务熔断&ndash;>-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!-- <!&ndash;集成服务消费&ndash;>-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2.application.yml依赖

:
servlet: #上传配置
multipart:
enabled: true
file-size-threshold: 0
max-file-size: 1000MB
max-request-size: 1000MB
resolve-lazily: false
datasource: #数据库配置
name: druidDataSource
type: com.alibaba.druid.pool.DruidDataSource
druid:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///hc_official_website_1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
filters: stat, wall, config
initial-size: 1
max-active: 100
max-wait: 60000
min-idle: 1
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: select 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true
max-open-prepared-statements: 50
max-pool-prepared-statement-per-connection-size: 20
filter:
wall:
config:
multi-statement-allow: true #允许一次批量更新操作,会导致SQL注入
mybatis: #Mybaytis映射文件位置
mapper-locations: classpath:/mappers/*Mapper.xml
configuration:
aggressive-lazy-loading: false #当参数设置为false时,对任意延迟属性的调用都将按需加载

3.结构
也是要在启动器通目录或者子目录

微服务的模块化设计与常用模块设计,实现业务类,工具类,DAO ,Service,Controller分离_mysql_05

现在的控制端

直接文件结构

微服务的模块化设计与常用模块设计,实现业务类,工具类,DAO ,Service,Controller分离_spring_06


没什么东西了