一、效果演示
二、实现思路
版本检测 -> 安装包下载 -> 调用系统安装包程序进行安装
三、具体实现1
3.1 版本检测
3.1.1 思路:
版本需要更新时,tomcat后端更新数据库信息,Android启动时通过http请求查看最新版本号,将拿到的版本号与自身版本号对比。
3.1.2 数据库表设计:
-- ----------------------------
-- Table structure for `versions`
-- ----------------------------
DROP TABLE IF EXISTS `versions`;
CREATE TABLE `versions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`version_number` varchar(50) NOT NULL,
`release_date` date NOT NULL,
`description` text,
`is_current` tinyint(1) DEFAULT '0',
`package_url` varchar(255) NOT NULL,
`image_url` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
3.1.3 tomcat 后端(自己新建JavaWeb项目,我的tomcat版本为10.1.10)
下面的代码请按照自己的环境选择性复制、修改:
- pom文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gm.optical_fiber</groupId>
<artifactId>optical_fiber_app</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>optical_fiber_app Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties><!--属性-->
<!-- 项目构建使用的编码方式-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 编译java代码使用的jdk版本-->
<maven.compiler.source>20</maven.compiler.source>
<!-- 你的Java项目应该运行在什么样的jdk版本-->
<maven.compiler.target>20</maven.compiler.target>
<!-- 自定义全局变量(自定义的标签名即属性名,包含的东西即为属性值),
用${属性名}取值,一般用来指定版本号(可能会多处使用,用来可以一改全改)-->
<junit.version>4.13.2</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<!-- 依赖的使用范围,也就是在maven构建项目中的那些阶段起作用-->
<!-- 默认是compile,其外还有test(只在测试阶段使用),provided-->
<!-- compile:编译,测试,打包,部署都需用到-->
<!-- provided:编译,测试用。打包,部署时,其他人会提供,
例如:web应用的servlet不需要打包,部署时不需要带上,因为tomcat里有,用它的-->
<scope>test</scope>
</dependency>
<!-- 导入servlet依赖(直接写,若爆红说明本地仓库里没有,
之后点击右上角刷新会自动下载相应文件到本地仓库指定坐标位置)-->
<!-- 导入jar包-->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet.jsp</groupId>
<artifactId>jakarta.servlet.jsp-api</artifactId>
<version>3.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.8</version>
</dependency>
<!-- tomcat 10后使用的jstl maven依赖-->
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
<scope>compile</scope>
</dependency>
</dependencies>
<!--配置mybatis逆向工程的插件-->
<!--定制构建过程-->
<build>
<!--可配置多个插件-->
<plugins>
<!--其中的一个插件:mybatis逆向工程插件-->
<plugin>
<!--插件的GAV坐标-->
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.1</version>
<!--允许覆盖-->
<configuration>
<overwrite>true</overwrite>
</configuration>
<!--插件的依赖-->
<dependencies>
<!--mysql驱动依赖-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>20</source>
<target>20</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<!-- <outputDirectory></outputDirectory>-->
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include><!-- ** mean 匹配任意层级的目录,* mean any filename-->
<include>**/*.xml</include>
</includes>
<!--don't start the filter,Cause '*.properties(include)' had the use-->
<filtering>false</filtering>
</resource>
</resources>
<finalName>op_f</finalName>
</build>
</project>
- util类:
SqlSessionUtil
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
public class SqlSessionUtil {
private SqlSessionUtil() {
}
// one database one SqlSessionFactory Object
private static SqlSessionFactory sqlSessionFactory = null;
private static ThreadLocal<SqlSession> local = new ThreadLocal<>();
//made sqlSessionFactory
static {
//only run one time,but it exits in the whole time
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
//direction a not default database
// sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"),"app");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* get sqlSession
*
* @return sqlSession object
*/
public static SqlSession openSqlSession() {
//get from local Thread first
// a thread a sqlSession object
SqlSession sqlSession = local.get();
if (sqlSession == null) {
sqlSession = sqlSessionFactory.openSession();//is not exit, create a new one
local.set(sqlSession);
}
return sqlSession;
}
/**
* release resource and remove the local sqlSession
* @param sqlSession
*/
public static void closeSqlSession(SqlSession sqlSession) {
if (sqlSession != null) {
local.remove();
sqlSession.close();
}
}
}
json格式化工具GsonUtil
import com.google.gson.*;
import java.text.SimpleDateFormat;
import java.util.Date;
public class GsonUtils {
private GsonUtils(){
}
/**
* 指定json的生成形式,保留空,日期格式化
* @return
*/
public static Gson getGson(){
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.serializeNulls();//保留空属性
// 自定义Date类型的序列化和反序列化
gsonBuilder.registerTypeAdapter(Date.class, (JsonSerializer<Date>) (src, typeOfSrc, context) -> {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedDate = formatter.format(src);
return new JsonPrimitive(formattedDate);
});
gsonBuilder.registerTypeAdapter(Date.class, (JsonDeserializer<Date>) (json, typeOfT, context) -> {
try {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return formatter.parse(json.getAsString());
} catch (Exception e) {
return null;
}
});
return gsonBuilder.create();
}
}
- dao 持久层(使用了mybatis框架)
- mybatis 配置文件(记得改为自己的包名和自己的路径、数据库名等)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties"/>
<typeAliases>
<package name="com.gm.optical_fiber.pojo"/>
</typeAliases>
<environments default="app">
<environment id="app">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
<!--提醒:正常使用连接池的话,池中有很多参数是需要设置的。设置好参数,可以让连接池发挥的更好。事半功倍的效果。-->
<!--具体连接池当中的参数如何配置呢?需要反复的根据当前业务情况进行测试。-->
<!-- poolMaximumActiveConnections:连接池当中最多的正在使用的连接对象的数量上限。最多有多少个连接可以活动。默认值10-->
<property name="poolMaximumActiveConnections" value="1000"/>
<property name="poolPingQuery" value="SELECT NOW()" />
<property name="poolPingEnabled" value="true" />
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.gm.optical_fiber.mapper"/>
</mappers>
</configuration>
在resource目录下新建自己的数据库配置文件,ip地址改为自己云服务器的ip地址或域名(db.properties)
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/optical_fiber?autoReconnect=true
user=breeze
password=1949
- 实现类接口 VersionMapper(反射机制)
import java.util.List;
public interface VersionMapper {
int deleteByPrimaryKey(Integer id);
int insert(Version row);
Version selectByPrimaryKey(Integer id);
List<Version> selectAll();
int updateByPrimaryKey(Version row);
int updateAllToOld();
Version selectIsCurrent();
}
- 接口对应的sql配置文件(记得改自己的包名且将该文件放到资源文件夹下的与对应的mapper包名同名的目录<这个目录需要自己新建>)
<?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.gm.optical_fiber.mapper.VersionMapper">
<resultMap id="BaseResultMap" type="com.gm.optical_fiber.pojo.Version">
<id column="id" jdbcType="INTEGER" property="id"/>
<result column="version_number" jdbcType="VARCHAR" property="versionNumber"/>
<result column="release_date" jdbcType="DATE" property="releaseDate"/>
<result column="is_current" jdbcType="BIT" property="isCurrent"/>
<result column="package_url" jdbcType="VARCHAR" property="packageUrl"/>
<result column="image_url" jdbcType="VARCHAR" property="imageUrl"/>
<result column="description" jdbcType="LONGVARCHAR" property="description"/>
</resultMap>
<!-- 删除指定主键的记录 -->
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete
from versions
where id = #{
id}
</delete>
<!-- 插入一条新记录 -->
<insert id="insert" useGeneratedKeys="true" keyColumn="id" keyProperty="id"
parameterType="com.gm.optical_fiber.pojo.Version">
insert into versions (id, version_number, release_date, is_current, package_url, image_url, description)
values (#{
id}, #{
versionNumber}, #{
releaseDate}, #{
isCurrent}, #{
packageUrl}, #{
imageUrl}, #{
description})
</insert>
<!-- 更新指定主键的记录 -->
<update id="updateByPrimaryKey" parameterType="com.gm.optical_fiber.pojo.Version">
update versions
<set>
<if test="versionNumber != null">
version_number = #{
versionNumber},
</if>
<if test="releaseDate != null">
release_date = #{
releaseDate},
</if>
<if test="isCurrent != null">
is_current = #