1.pom依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.hcnet2006.blog</groupId>
<artifactId>blog-base</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>cn.hcnet2006.blog</groupId>
<artifactId>hcnet-website</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hcnet-website</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-boot-admin.version>2.2.2</spring-boot-admin.version>
<docker.image.prefix>47.97.170.173:5000</docker.image.prefix>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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-starter</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring-boot-admin.version}</version>
</dependency>
<!--APK解析-->
<dependency>
<groupId>net.dongliu</groupId>
<artifactId>apk-parser</artifactId>
<version>2.6.10</version>
</dependency>
<!--Swagger2文档-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!--添加消息总线依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<!--fastjson依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<!--使用googlezxing生成二维码-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.2.0</version>
</dependency>
<!--转换MARKDOWN-->
<dependency>
<groupId>org.pegdown</groupId>
<artifactId>pegdown</artifactId>
<version>1.6.0</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>
<!--集成阿里云OSS存储对象服务-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.8.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--防止jks密钥文件被编译,导致乱码-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>cert</nonFilteredFileExtension>
<nonFilteredFileExtension>jks</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
<!--使用Maven和Dockerfile命令构建镜像-->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<!--生成镜像名称-->
<repository>
${docker.image.prefix}/${project.name}
</repository>
<!--生成镜像版本-->
<tag>${project.version}</tag>
<!--推送到私有仓库或者DockerHub时需要开启用户认证-->
<useMavenSettingsForAuth>true</useMavenSettingsForAuth>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
<JAR_EXPOSE>8204</JAR_EXPOSE>
</buildArgs>
<!-- <imageName>${project.name}:${project.version}</imageName>-->
<!-- <baseImage>java</baseImage>-->
<!-- <entryPoint>-->
<!-- {"java","-jar","/${project.build.finalName}.jar"}-->
<!-- </entryPoint>-->
<!-- <!– <dockerDirectory>–>-->
<!-- <!– ${project.basedir}/src/main/docker–>-->
<!-- <!– </dockerDirectory>–>-->
<!-- <skipDockerBuild>false</skipDockerBuild>-->
<!-- <resources>-->
<!-- <resource>-->
<!-- <directory>${project.build.directory}</directory>-->
<!-- <include>${project.build.finalName}.jar</include>-->
<!-- </resource>-->
<!-- </resources>-->
</configuration>
<!--直接使用 mvn install 命令打包项目, 就会自动构建并推送镜像-->
<executions>
<execution>
<id>default</id>
<phase>install</phase>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
2.application.yml
server:
port: 8210
spring:
application:
name: hcnet-website
# cloud:
# consul:
# host: localhost
# port: 8500
# discovery:
# service-name: ${spring.application.name}
servlet:
multipart:
enabled: true
file-size-threshold: 0
max-file-size: 100000000
max-request-size: 100000000
resolve-lazily: false
boot:
admin:
client:
url: "http://172.17.0.1:8205"
instance:
service-base-url: "http://172.17.0.1:8205"
datasource:
name: druidDataSource
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://172.17.0.1:3306/hc_official_website?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
username: root
password: 123456
rabbitmq:
username: guest
password: guest
port: 5672
publisher-confirms: true
virtual-host: /
host: 172.17.0.1
management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include: '*'
mybatis:
mapper-locations: classpath:/mappers/*Mapper.xml
feign:
hystrix:
enabled: true
3.bootstrap.yml
spring:
application:
name: hcnet-website
cloud:
config:
discovery:
service-id: config-server #配置中心
enabled: true #开启发现服务
name: user-server
profile: pro #对应{profiles}部分
label: master
consul:
host: 172.17.0.1
port: 8500
discovery:
service-name: ${spring.application.name}
hostname: 172.17.0.1
health-check-url: http://172.17.0.1:8210/actuator/health
zipkin:
base-url: http://172.17.0.1:9411/
sleuth:
sampler:
probability: 1
feign:
hystrix:
enabled: true
4.配置MYBATI代码生成器
4.1.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);
}
}
}
4.2 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?serverTimezone=UTC"
userId="root"
password="123456"
/>
<!--实体类代码生成器-->
<javaModelGenerator targetPackage="cn.hcnet2006.blog.hcnetwebsite.bean" targetProject="./upload-apk/src/main/java">
<!-- <property name="trimStrings" value="true"/>-->
</javaModelGenerator>
<!--MapperXML文件生成器-->
<sqlMapGenerator targetPackage="mappers" targetProject="./upload-apk/src/main/resources"/>
<!--Mappper接口生成器-->
<javaClientGenerator type="XMLMAPPER" targetPackage="cn.hcnet2006.blog.hcnetwebsite.mapper" targetProject="./upload-apk/src/main/java"/>
<!--数据库表配置-->
<table tableName="sys_apk">
<!--数据库主键生成策略-->
<generatedKey column="id" sqlStatement="Mysql"/>
</table>
</context>
</generatorConfiguration>
4.3. 解决不同数据库表名相同导致生成覆盖问题
<?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.blog.hcnetwebsite.bean" targetProject="./hcnet-website-1/src/main/java">
<!-- <property name="trimStrings" value="true"/>-->
</javaModelGenerator>
<!--MapperXML文件生成器-->
<sqlMapGenerator targetPackage="mappers" targetProject="./hcnet-website-1/src/main/resources"/>
<!--Mappper接口生成器-->
<javaClientGenerator type="XMLMAPPER" targetPackage="cn.hcnet2006.blog.hcnetwebsite.mapper" targetProject="./hcnet-website-1/src/main/java"/>
<!--数据库表配置-->
<table tableName="sys_user">
<!--数据库主键生成策略-->
<generatedKey column="id" sqlStatement="Mysql"/>
</table>
</context>
</generatorConfiguration>
5.设置全局DataBase
6.HTTP结果封装
6.1.http返回结果封装
package cn.hcnet2006.blog.hcnetwebsite.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;
}
}
6.2.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;
}
7.分页模块封装
7.1.分页请求封装
package cn.hcnet2006.blog.hcnetwebsite.page;
import java.util.HashMap;
import java.util.Map;
/**
* 分页请求
* @author Louis
* @date Jan 12, 2019
*/
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);
}
}
7.2分页结果封装
package cn.hcnet2006.blog.hcnetwebsite.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;
}
}
7.3.MyBatis分页助手
package cn.hcnet2006.blog.hcnetwebsite.page;
import cn.hcnet2006.blog.hcnetwebsite.utils.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;
}
}
7.4.反射相关辅助方法
package cn.hcnet2006.blog.hcnetwebsite.utils;
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;
}
}
8.通用CURD接口
package cn.hcnet2006.blog.hcnetwebsite.service;
import cn.hcnet2006.blog.hcnetwebsite.page.PageRequest;
import cn.hcnet2006.blog.hcnetwebsite.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);
}
9.swagger聚合文档设置
package cn.hcnet2006.blog.hcnetwebsite.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
//添加head参数start
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<Parameter>();
tokenPar.name("Authorization").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
pars.add(tokenPar.build());
//添加head参数end
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.globalOperationParameters(pars)
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("后台接口文档与测试")
.description("这是一个给app端人员调用server端接口的测试文档与平台")
.version("1.0.0")
.termsOfServiceUrl("http://terms-of-services.url")
//.license("LICENSE")
//.licenseUrl("http://url-to-license.com")
.build();
}
}
10.集成阿里云OSS
仅仅使用上传功能,上传后返回下载链接
package cn.hcnet2006.blog.hcnetwebsite.utils;
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.OSSObject;
import com.aliyun.oss.model.PutObjectResult;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* OSS文件上传
*/
public class OSSUtils {
@Autowired
//private static OSSConstant ossConstant;
static String bucketName = "hcnetxxxx-apk";
static String accessKeyId = "LTAI4Fn8xxxxxxxxucSR5AX";
static String accessKeySecret = "yuYPFquHRK3xxxxxxxMBUaWjLdC";
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){
ossClient = new OSSClientBuilder().build(endpoint,accessKeyId,
accessKeySecret);
System.out.println("accessKeyId2:"+accessKeyId);
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);
return url;
}catch (OSSException oe){
oe.printStackTrace();
}catch (ClientException | FileNotFoundException ce){
ce.printStackTrace();
}finally{
ossClient.shutdown();
}
return null;
}
public static void download(String apkName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
//设置文件内容
resp.setContentType("application/vnd.android.package-archive");
//下载显示的文件名
String apk_name = apkName;
//下载显示文件名解决中文乱码问题
//在下载之前首先判断是否是微软浏览器,如果是,用UTF-8编码,
//如果不是,用万能解码
//这样就可以在IE8-11,EDGE,FIXBO一级Chrome浏览器下载文件时,不会中文乱码了
boolean isMSIE = HttpUtils.isMSBrowser(req);
//如果是IE浏览器
if(isMSIE){
apk_name = URLEncoder.encode(apk_name,"UTF-8");
}else{
//其他浏览器
apk_name = new String(apk_name.getBytes("UTF-8"),"ISO-8859-1");
}
//设置response的Content-disposition时,apk_name的值要加上双引号如果不佳双引号
//在火狐下载数据时,如果文件名是英文加中文的组合,那么火狐在下载时,文件名只有英文部分
//只有加了双引号之后,文件名和代码设置的文件名一致,因为这个双引号是在字符串中的,所以需
//要加反斜杠来转义
resp.setHeader("Content-disposition","attachment;filename:"+apk_name);
//设置文件大小,这样就可以在下载时,显示文件的大小
//resp.setContentLength(Integer.parseInt("7629672"));
//读取要下载的文件保存到文件输入流
OSS ossClient = new OSSClientBuilder().build("oss-cn-shenzhen.aliyuncs.com","LTAI4Fn8YhRW2FkbpucSR5AX","yuYPFquHRK3UHHKq3YlV0MBUaWjLdC");
OSSObject ossObject = ossClient.getObject("hcnet2006-file-apk",apkName);
System.out.println("Object content:");
InputStream is = ossObject.getObjectContent();
BufferedInputStream in = new BufferedInputStream(is);
//InputStream in = new FileInputStream(apk_url);
//创建文件输出流
OutputStream out = resp.getOutputStream();
//创建缓冲区
byte buffer[] = new byte[1024];
int len = 0;
while((len = in.read(buffer)) > 0){
out.write(buffer,0,len);
}
//关闭输入流
in.close();
//关闭输出流
out.close();
//关闭OSSClient;
ossClient.shutdown();
}
}
11.APK上传(另外一个项目)参考
package cn.hcnet2006.blog.uploadapk.controller;
import brave.http.HttpRequest;
import cn.hcnet2006.blog.uploadapk.bean.SysApk;
import cn.hcnet2006.blog.uploadapk.config.OSSConfig;
import cn.hcnet2006.blog.uploadapk.constant.OSSConstant;
import cn.hcnet2006.blog.uploadapk.http.HttpResult;
import cn.hcnet2006.blog.uploadapk.page.PageRequest;
import cn.hcnet2006.blog.uploadapk.page.PageResult;
import cn.hcnet2006.blog.uploadapk.service.SysApkService;
import cn.hcnet2006.blog.uploadapk.utils.ApkInfoUtil;
import cn.hcnet2006.blog.uploadapk.utils.HttpUtils;
import cn.hcnet2006.blog.uploadapk.utils.OSSUtils;
import com.aliyun.oss.OSS;
//import com.google.gson.internal.$Gson$Preconditions;
//import com.netflix.ribbon.proxy.annotation.Http;
import io.swagger.annotations.*;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@Api(tags = "上传信息接口")
@RestController
@RequestMapping("/upload")
public class UploadController {
@Autowired
private SysApkService sysApkService;
//文件按时间结构存储
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
@ApiOperation(value = "文件上传",notes = "文件上传")
@ApiImplicitParams({
@ApiImplicitParam(type = "query",name = "createBy",dataType = "String",required = true)
})
//@PreAuthorize("hasAuthority('ROLE_USER')")
@PostMapping("/apk")
public HttpResult upload(@ApiParam(value = "uploadFile",required = true) MultipartFile uploadFile,String createBy, HttpServletRequest req) throws NullPointerException, IOException {
//获取文件大小
String apkSize = uploadFile.getSize()+"";
//应用类型
String cType = uploadFile.getContentType();
System.out.println("应用类型:"+cType);
//规划文件上传路径
String realPath = "/home/lidengyin/Documents/uploadFile/apk/";
//文件目录格式,时期划分
String format = sdf.format(new Date());
//指定上传文件目录
File folder = new File(realPath + format);
if(!folder.isDirectory()){
//生成路径下所有目录
folder.mkdirs();
}
//文件上传名
String apkOldName = uploadFile.getOriginalFilename();
System.out.println("fileName:"+apkOldName);
//文件存储名:UUID+文件类型后缀
String apkStoName = UUID.randomUUID().toString()+
apkOldName.substring(apkOldName.lastIndexOf("."),apkOldName.length());
//
try{
//将上传文件以指定名称上传到指定文件夹
uploadFile.transferTo(new File(folder, apkStoName));
//获取文件在服务器存储路径
String filePath = folder.getPath()+"/"+apkStoName;
System.out.println("filePath:"+filePath);
File convFile = new File(filePath);
Map<String,Object> apkInfo = ApkInfoUtil.readAPK(convFile);
//应用名
String apkName = (String) apkInfo.get("name");
//应用包
String pkName = (String) apkInfo.get("pkName");
//版本名
String vName = (String) apkInfo.get("vName");
//版本号
long vCode = (long) apkInfo.get("vCode");
System.out.println("名称:"+apkName);
System.out.println("包名:"+pkName);
System.out.println("版本名:"+vName);
System.out.println("版本号:"+vCode);
//设置SysApk
SysApk sysApk = new SysApk();
sysApk.setApkName(apkName);
sysApk.setApkPk(pkName);
sysApk.setApkVc(vCode);
sysApk.setApkVn(vName);
sysApk.setCreateBy(createBy);
sysApk.setCreateTime(new Date());
sysApk.setLastUpdateBy(createBy);
sysApk.setLastUpdateTime(new Date());
sysApk.setApkSize(apkSize);
//sysApk.setApkUrl(filePath);
sysApk.setDelFlag((byte)0);
String apkUrl = OSSUtils.upload(convFile,apkName);
apkUrl = apkUrl.substring(0,apkUrl.indexOf("?"));
System.out.println("apkurl:"+apkUrl);
System.out.println("url:"+sysApk.getApkUrl());
sysApk.setApkUrl(apkUrl);
sysApkService.save(sysApk);
return HttpResult.ok(filePath);
}catch (IOException e){
e.printStackTrace();
}
return HttpResult.error("上传失败");
}
// @ApiOperation(value = "下载信息接口",notes = "下载信息接口")
// @ApiImplicitParams({
// @ApiImplicitParam(type = "query",name = "id",value = "资源序号",required = true)
// })
// @PostMapping("/download")
// //@PreAuthorize("hasAuthority('ROLE_USER')")
// @CrossOrigin(origins = "*", maxAge = 3600, allowedHeaders = "*",allowCredentials = "true")
// public String download(Long id, HttpServletResponse resp,HttpServletRequest req){
// try{
// SysApk sysApk = sysApkService.findById(id);
// if (sysApk.getDelFlag() == -1){
// return "链接失效";
// }
// OSSUtils.download("海行健V2.0",req,resp);
// System.out.println("id:"+id);
// //根据主键获取对应文件
// SysApk sysApk = sysApkService.findById(Long.parseLong(id));
// System.out.println("name:"+sysApk.getApkName());
// System.out.println("url:"+sysApk.getApkUrl());
//
// //文件大小
// String content_length = sysApk.getApkSize();
// //文件下载路径
// String apk_url = sysApk.getApkUrl();
// //生成文件
// File file = new File(apk_url);
// System.out.println("fileName:"+file.getName());
// System.out.println("fileIsDirectory:"+file.isDirectory());
//
// //设置文件内容
// resp.setContentType("application/octet-stream");
// //下载显示的文件名
// String apk_name = sysApk.getApkName();
// //下载显示文件名解决中文乱码问题
// //在下载之前首先判断是否是微软浏览器,如果是,用UTF-8编码,
// //如果不是,用万能解码
// //这样就可以在IE8-11,EDGE,FIXBO一级Chrome浏览器下载文件时,不会中文乱码了
// boolean isMSIE = HttpUtils.isMSBrowser(req);
// //如果是IE浏览器
// if(isMSIE){
// apk_name = URLEncoder.encode(apk_name,"UTF-8");
// }else{
// //其他浏览器
// apk_name = new String(apk_name.getBytes("UTF-8"),"ISO-8859-1");
// }
// //设置response的Content-disposition时,apk_name的值要加上双引号如果不佳双引号
// //在火狐下载数据时,如果文件名是英文加中文的组合,那么火狐在下载时,文件名只有英文部分
// //只有加了双引号之后,文件名和代码设置的文件名一致,因为这个双引号是在字符串中的,所以需
// //要加反斜杠来转义
//
// resp.setHeader("Content-disposition","attachment;filename:"+apk_name);
// //设置文件大小,这样就可以在下载时,显示文件的大小
// resp.setContentLength(Integer.parseInt(content_length));
//
// //读取要下载的文件保存到文件输入流
// InputStream in = new FileInputStream(apk_url);
// //创建文件输出流
// OutputStream out = resp.getOutputStream();
// //创建缓冲区
// byte buffer[] = new byte[1024];
// int len = 0;
// while((len = in.read(buffer)) > 0){
// out.write(buffer,0,len);
// }
// //关闭输入流
// in.close();
// //关闭输出流
// out.close();
// return HttpResult.ok("下载成功");
// }catch (Exception e){
// e.printStackTrace();
// //return HttpResult.error("下载失败");
// }
// }
@ApiOperation(value = "根据删除标志,分页查看上传文件",notes = "根据删除标志,分页查看上传文件")
@ApiImplicitParams({
// @ApiImplicitParam(type = "query", name = "pageNum", value = "页码",required = true),
// @ApiImplicitParam(type = "query", name = "pageSize", value = "行数",required = true),
// @ApiImplicitParam(type = "query",name = "delFlag", value = "删除标志,-1为删除,0为正常",required = true)
})
@PostMapping("/select/delFlag")
@PreAuthorize("hasAuthority('ROLE_USER')")
@CrossOrigin(maxAge = 3600, origins = "*", allowedHeaders = "*",allowCredentials = "true")
public HttpResult selectByDelFlag(@RequestBody PageRequest pageRequest){
Byte delFlag = Byte.parseByte( pageRequest.getParam("delFlag")+"") ;
Map<String ,Object> map = new HashMap<>();
map.put("delFlag", delFlag);
pageRequest.setParams(map);
System.out.println(pageRequest.getParam("delFlag"));
PageResult pageResult = sysApkService.findPage(pageRequest);
return HttpResult.ok(pageResult);
}
@ApiOperation(value = "修改可用性",notes = "修改可用性")
@ApiImplicitParams({
@ApiImplicitParam(type = "query",name = "id",value = "ID",required = true),
@ApiImplicitParam(type = "query",name = "delFlag",value = "删除标志,-1删除,0正常",required = true)
})
@PostMapping("/update/id")
@PreAuthorize("hasAuthority('ROLE_USER')")
public HttpResult updateDelFlagById(String id, String delFlag){
try{
SysApk sysApk = new SysApk();
sysApk.setId(Long.parseLong(id));
sysApk.setDelFlag(Byte.parseByte(delFlag));
int result = sysApkService.delete(sysApk);
return HttpResult.ok(sysApk);
}catch (Exception e){
return HttpResult.error("修改失败");
}
}
}
12.简单用户注册实现,通过捕获异常
package cn.hcnet2006.blog.hcnetwebsite.controller;
import cn.hcnet2006.blog.hcnetwebsite.bean.SysUser;
import cn.hcnet2006.blog.hcnetwebsite.http.HttpResult;
import cn.hcnet2006.blog.hcnetwebsite.service.SysUserService;
import cn.hcnet2006.blog.hcnetwebsite.util.OSSUtils;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Date;
@Api(tags = "用户信息接口")
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private SysUserService sysUserService;
//private String url = "/usr/local/spring";
@ApiOperation(value = "用户注册",notes = "用户注册" +
"参数包括:" +
"1.")
@ApiImplicitParams({
@ApiImplicitParam(type = "query", name = "name",value = "用户名",required = true),
@ApiImplicitParam(type = "query", name = "password",value = "密码",required = true),
@ApiImplicitParam(type = "query", name = "deptId",value = "所属方向ID",required = true),
@ApiImplicitParam(type = "query", name = "grade",value = "年级,比如2018",required = true),
@ApiImplicitParam(type = "query", name = "email",value = "邮箱,确保格式正确",required = true),
@ApiImplicitParam(type = "query", name = "mobile",value = "手机,确保格式正确",required = true),
@ApiImplicitParam(type = "query", name = "createBy",value = "创建者",required = true),
//@ApiImplicitParam(type = "query", name = "createTime",value = "创建时间",required = true)
})
@PostMapping("/save")
public HttpResult register(SysUser sysUser, @ApiParam(value = "uploadFile", required = true) MultipartFile uploadFile,
HttpServletRequest request) throws FileNotFoundException {
//新建暂时缓存目录,该目录一定存在
String url = ResourceUtils.getURL("").getPath()+uploadFile.getOriginalFilename();
System.out.println(url);
File folder = new File(url);
try{
//转义文件到服务器
uploadFile.transferTo(folder);
//从服务器获取文件传递到阿里云OSS.返回下载链接地址
String avator_url = OSSUtils.upload(folder,sysUser.getName()+".jpg");
//删除服务器缓存文件
folder.delete();
//设置属性
//设置用户头像
sysUser.setAvator(avator_url);
//设置创建时间
sysUser.setCreateTime(new Date());
//设置更新时间
sysUser.setLastUpdateTime(new Date());
//设置创建者
sysUser.setLastUpdateBy(sysUser.getCreateBy());
//删除标志
sysUser.setDelFlag((byte)0);
//保存
sysUserService.save(sysUser);
return HttpResult.ok(sysUser);
}catch (DuplicateKeyException e){
return HttpResult.error("重复注册");
}catch (IOException e){
e.printStackTrace();
return HttpResult.error("注册失败");
}
}
}
13.工具类(旧),可用的仅有捕捉图片第一帧
package cn.hcnet2006.blog.hcnetwebsite.util;
import cn.hcnet2006.blog.hcnetwebsite.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 HttpResult 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 HttpResult 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;
}
}