碼雲地址:https://gitee.com/wangdefu/caraprk_public?_from=gitee_search
源代碼已經完全開源,還望大神發現問題多多指點,在下感激不盡,怎麼部署和安裝環境我已經在後面描述清楚了,這個主要關鍵還是對接硬件,如果你要改寫底層硬件的協議,你用C來對接已經接口,內置到相機中去,這樣也可以解決掉不需要場端要架電腦的問題,省掉很多麻煩
源代碼開源地址:https://gitee.com/wangdefu/caraprk_public?_from=gitee_search
對接停車場硬件示例代碼:
package com.google.gson;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gson.internal.$Gson$Preconditions;
import com.google.gson.internal.Excluder;
import com.google.gson.internal.bind.TreeTypeAdapter;
import com.google.gson.internal.bind.TypeAdapters;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import static com.google.gson.Gson.DEFAULT_COMPLEX_MAP_KEYS;
import static com.google.gson.Gson.DEFAULT_ESCAPE_HTML;
import static com.google.gson.Gson.DEFAULT_JSON_NON_EXECUTABLE;
import static com.google.gson.Gson.DEFAULT_LENIENT;
import static com.google.gson.Gson.DEFAULT_PRETTY_PRINT;
import static com.google.gson.Gson.DEFAULT_SERIALIZE_NULLS;
import static com.google.gson.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES;
/**
* <p>Use this builder to construct a {@link Gson} instance when you need to set configuration
* options other than the default. For {@link Gson} with default configuration, it is simpler to
* use {@code new Gson()}. {@code GsonBuilder} is best used by creating it, and then invoking its
* various configuration methods, and finally calling create.</p>
*
* <p>The following is an example shows how to use the {@code GsonBuilder} to construct a Gson
* instance:
*
* <pre>
* Gson gson = new GsonBuilder()
* .registerTypeAdapter(Id.class, new IdTypeAdapter())
* .enableComplexMapKeySerialization()
* .serializeNulls()
* .setDateFormat(DateFormat.LONG)
* .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
* .setPrettyPrinting()
* .setVersion(1.0)
* .create();
* </pre></p>
*
* <p>NOTES:
* <ul>
* <li> the order of invocation of configuration methods does not matter.</li>
* <li> The default serialization of {@link Date} and its subclasses in Gson does
* not contain time-zone information. So, if you are using date/time instances,
* use {@code GsonBuilder} and its {@code setDateFormat} methods.</li>
* </ul>
* </p>
*
* @author Inderjeet Singh
* @author Joel Leitch
* @author Jesse Wilson
*/
public final class GsonBuilder {
private Excluder excluder = Excluder.DEFAULT;
private LongSerializationPolicy longSerializationPolicy = LongSerializationPolicy.DEFAULT;
private FieldNamingStrategy fieldNamingPolicy = FieldNamingPolicy.IDENTITY;
private final Map<Type, InstanceCreator<?>> instanceCreators
= new HashMap<Type, InstanceCreator<?>>();
private final List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
/** tree-style hierarchy factories. These come after factories for backwards compatibility. */
private final List<TypeAdapterFactory> hierarchyFactories = new ArrayList<TypeAdapterFactory>();
private boolean serializeNulls = DEFAULT_SERIALIZE_NULLS;
private String datePattern;
private int dateStyle = DateFormat.DEFAULT;
private int timeStyle = DateFormat.DEFAULT;
private boolean complexMapKeySerialization = DEFAULT_COMPLEX_MAP_KEYS;
private boolean serializeSpecialFloatingPointValues = DEFAULT_SPECIALIZE_FLOAT_VALUES;
private boolean escapeHtmlChars = DEFAULT_ESCAPE_HTML;
private boolean prettyPrinting = DEFAULT_PRETTY_PRINT;
private boolean generateNonExecutableJson = DEFAULT_JSON_NON_EXECUTABLE;
private boolean lenient = DEFAULT_LENIENT;
/**
* Creates a GsonBuilder instance that can be used to build Gson with various configuration
* settings. GsonBuilder follows the builder pattern, and it is typically used by first
* invoking various configuration methods to set desired options, and finally calling
* {@link #create()}.
*/
public GsonBuilder() {
}
/**
* Configures Gson to enable versioning support.
*
* @param ignoreVersionsAfter any field or type marked with a version higher than this value
* are ignored during serialization or deserialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder setVersion(double ignoreVersionsAfter) {
excluder = excluder.withVersion(ignoreVersionsAfter);
return this;
}
/**
* Configures Gson to excludes all class fields that have the specified modifiers. By default,
* Gson will exclude all fields marked transient or static. This method will override that
* behavior.
*
* @param modifiers the field modifiers. You must use the modifiers specified in the
* {@link java.lang.reflect.Modifier} class. For example,
* {@link java.lang.reflect.Modifier#TRANSIENT},
* {@link java.lang.reflect.Modifier#STATIC}.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder excludeFieldsWithModifiers(int... modifiers) {
excluder = excluder.withModifiers(modifiers);
return this;
}
/**
* Makes the output JSON non-executable in Javascript by prefixing the generated JSON with some
* special text. This prevents attacks from third-party sites through script sourcing. See
* <a href="http://code.google.com/p/google-gson/issues/detail?id=42">Gson Issue 42</a>
* for details.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder generateNonExecutableJson() {
this.generateNonExecutableJson = true;
return this;
}
/**
* Configures Gson to exclude all fields from consideration for serialization or deserialization
* that do not have the {@link com.google.gson.annotations.Expose} annotation.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder excludeFieldsWithoutExposeAnnotation() {
excluder = excluder.excludeFieldsWithoutExposeAnnotation();
return this;
}
/**
* Configure Gson to serialize null fields. By default, Gson omits all fields that are null
* during serialization.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public GsonBuilder serializeNulls() {
this.serializeNulls = true;
return this;
}
/**
* Enabling this feature will only change the serialized form if the map key is
* a complex type (i.e. non-primitive) in its <strong>serialized</strong> JSON
* form. The default implementation of map serialization uses {@code toString()}
* on the key; however, when this is called then one of the following cases
* apply:
*
* <h3>Maps as JSON objects</h3>
* For this case, assume that a type adapter is registered to serialize and
* deserialize some {@code Point} class, which contains an x and y coordinate,
* to/from the JSON Primitive string value {@code "(x,y)"}. The Java map would
* then be serialized as a {@link JsonObject}.
*
* <p>Below is an example:
* <pre> {@code
* Gson gson = new GsonBuilder()
* .register(Point.class, new MyPointTypeAdapter())
* .enableComplexMapKeySerialization()
* .create();
*
* Map<Point, String> original = new LinkedHashMap<Point, String>();
* original.put(new Point(5, 6), "a");
* original.put(new Point(8, 8), "b");
* System.out.println(gson.toJson(original, type));
* }</pre>
* The above code prints this JSON object:<pre> {@code
* {
* "(5,6)": "a",
* "(8,8)": "b"
* }
* }</pre>
*
* <h3>Maps as JSON arrays</h3>
* For this case, assume that a type adapter was NOT registered for some
* {@code Point} class, but rather the default Gson serialization is applied.
* In this case, some {@code new Point(2,3)} would serialize as {@code
* {"x":2,"y":5}}.
*
* <p>Given the assumption above, a {@code Map<Point, String>} will be
* serialize as an array of arrays (can be viewed as an entry set of pairs).
*
* <p>Below is an example of serializing complex types as JSON arrays:
* <pre> {@code
* Gson gson = new GsonBuilder()
* .enableComplexMapKeySerialization()
* .create();
*
* Map<Point, String> original = new LinkedHashMap<Point, String>();
* original.put(new Point(5, 6), "a");
* original.put(new Point(8, 8), "b");
* System.out.println(gson.toJson(original, type));
* }
*
* The JSON output would look as follows:
* <pre> {@code
* [
* [
* {
* "x": 5,
* "y": 6
* },
* "a"
* ],
* [
* {
* "x": 8,
* "y": 8
* },
* "b"
* ]
* ]
* }</pre>
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
*/
public GsonBuilder enableComplexMapKeySerialization() {
complexMapKeySerialization = true;
return this;
}
/**
* Configures Gson to exclude inner classes during serialization.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder disableInnerClassSerialization() {
excluder = excluder.disableInnerClassSerialization();
return this;
}
/**
* Configures Gson to apply a specific serialization policy for {@code Long} and {@code long}
* objects.
*
* @param serializationPolicy the particular policy to use for serializing longs.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder setLongSerializationPolicy(LongSerializationPolicy serializationPolicy) {
this.longSerializationPolicy = serializationPolicy;
return this;
}
/**
* Configures Gson to apply a specific naming policy to an object's field during serialization
* and deserialization.
*
* @param namingConvention the JSON field naming convention to use for serialization and
* deserialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention) {
this.fieldNamingPolicy = namingConvention;
return this;
}
/**
* Configures Gson to apply a specific naming policy strategy to an object's field during
* serialization and deserialization.
*
* @param fieldNamingStrategy the actual naming strategy to apply to the fields
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) {
this.fieldNamingPolicy = fieldNamingStrategy;
return this;
}
/**
* Configures Gson to apply a set of exclusion strategies during both serialization and
* deserialization. Each of the {@code strategies} will be applied as a disjunction rule.
* This means that if one of the {@code strategies} suggests that a field (or class) should be
* skipped then that field (or object) is skipped during serialization/deserialization.
*
* @param strategies the set of strategy object to apply during object (de)serialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.4
*/
public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) {
for (ExclusionStrategy strategy : strategies) {
excluder = excluder.withExclusionStrategy(strategy, true, true);
}
return this;
}
/**
* Configures Gson to apply the passed in exclusion strategy during serialization.
* If this method is invoked numerous times with different exclusion strategy objects
* then the exclusion strategies that were added will be applied as a disjunction rule.
* This means that if one of the added exclusion strategies suggests that a field (or
* class) should be skipped then that field (or object) is skipped during its
* serialization.
*
* @param strategy an exclusion strategy to apply during serialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
*/
public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy) {
excluder = excluder.withExclusionStrategy(strategy, true, false);
return this;
}
/**
* Configures Gson to apply the passed in exclusion strategy during deserialization.
* If this method is invoked numerous times with different exclusion strategy objects
* then the exclusion strategies that were added will be applied as a disjunction rule.
* This means that if one of the added exclusion strategies suggests that a field (or
* class) should be skipped then that field (or object) is skipped during its
* deserialization.
*
* @param strategy an exclusion strategy to apply during deserialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
*/
public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy) {
excluder = excluder.withExclusionStrategy(strategy, false, true);
return this;
}
/**
* Configures Gson to output Json that fits in a page for pretty printing. This option only
* affects Json serialization.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder setPrettyPrinting() {
prettyPrinting = true;
return this;
}
/**
* By default, Gson is strict and only accepts JSON as specified by
* <a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>. This option makes the parser
* liberal in what it accepts.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @see JsonReader#setLenient(boolean)
*/
public GsonBuilder setLenient() {
lenient = true;
return this;
}
/**
* By default, Gson escapes HTML characters such as < > etc. Use this option to configure
* Gson to pass-through HTML characters as is.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder disableHtmlEscaping() {
this.escapeHtmlChars = false;
return this;
}
/**
* Configures Gson to serialize {@code Date} objects according to the pattern provided. You can
* call this method or {@link #setDateFormat(int)} multiple times, but only the last invocation
* will be used to decide the serialization format.
*
* <p>The date format will be used to serialize and deserialize {@link java.util.Date}, {@link
* java.sql.Timestamp} and {@link java.sql.Date}.
*
* <p>Note that this pattern must abide by the convention provided by {@code SimpleDateFormat}
* class. See the documentation in {@link java.text.SimpleDateFormat} for more information on
* valid date and time patterns.</p>
*
* @param pattern the pattern that dates will be serialized/deserialized to/from
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public GsonBuilder setDateFormat(String pattern) {
// TODO(Joel): Make this fail fast if it is an invalid date format
this.datePattern = pattern;
return this;
}
/**
* Configures Gson to to serialize {@code Date} objects according to the style value provided.
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format.
*
* <p>Note that this style value should be one of the predefined constants in the
* {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
* information on the valid style constants.</p>
*
* @param style the predefined date style that date objects will be serialized/deserialized
* to/from
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public GsonBuilder setDateFormat(int style) {
this.dateStyle = style;
this.datePattern = null;
return this;
}
/**
* Configures Gson to to serialize {@code Date} objects according to the style value provided.
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format.
*
* <p>Note that this style value should be one of the predefined constants in the
* {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
* information on the valid style constants.</p>
*
* @param dateStyle the predefined date style that date objects will be serialized/deserialized
* to/from
* @param timeStyle the predefined style for the time portion of the date objects
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public GsonBuilder setDateFormat(int dateStyle, int timeStyle) {
this.dateStyle = dateStyle;
this.timeStyle = timeStyle;
this.datePattern = null;
return this;
}
/**
* Configures Gson for custom serialization or deserialization. This method combines the
* registration of an {@link TypeAdapter}, {@link InstanceCreator}, {@link JsonSerializer}, and a
* {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter} implements
* all the required interfaces for custom serialization with Gson. If a type adapter was
* previously registered for the specified {@code type}, it is overwritten.
*
* <p>This registers the type specified and no other types: you must manually register related
* types! For example, applications registering {@code boolean.class} should also register {@code
* Boolean.class}.
*
* @param type the type definition for the type adapter being registered
* @param typeAdapter This object must implement at least one of the {@link TypeAdapter},
* {@link InstanceCreator}, {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
$Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|| typeAdapter instanceof JsonDeserializer<?>
|| typeAdapter instanceof InstanceCreator<?>
|| typeAdapter instanceof TypeAdapter<?>);
if (typeAdapter instanceof InstanceCreator<?>) {
instanceCreators.put(type, (InstanceCreator) typeAdapter);
}
if (typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?>) {
TypeToken<?> typeToken = TypeToken.get(type);
factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter));
}
if (typeAdapter instanceof TypeAdapter<?>) {
factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter));
}
return this;
}
/**
* Register a factory for type adapters. Registering a factory is useful when the type
* adapter needs to be configured based on the type of the field being processed. Gson
* is designed to handle a large number of factories, so you should consider registering
* them to be at par with registering an individual type adapter.
*
* @since 2.1
*/
public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) {
factories.add(factory);
return this;
}
/**
* Configures Gson for custom serialization or deserialization for an inheritance type hierarchy.
* This method combines the registration of a {@link TypeAdapter}, {@link JsonSerializer} and
* a {@link JsonDeserializer}. If a type adapter was previously registered for the specified
* type hierarchy, it is overridden. If a type adapter is registered for a specific type in
* the type hierarchy, it will be invoked instead of the one registered for the type hierarchy.
*
* @param baseType the class definition for the type adapter being registered for the base class
* or interface
* @param typeAdapter This object must implement at least one of {@link TypeAdapter},
* {@link JsonSerializer} or {@link JsonDeserializer} interfaces.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter) {
$Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|| typeAdapter instanceof JsonDeserializer<?>
|| typeAdapter instanceof TypeAdapter<?>);
if (typeAdapter instanceof JsonDeserializer || typeAdapter instanceof JsonSerializer) {
hierarchyFactories.add(TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter));
}
if (typeAdapter instanceof TypeAdapter<?>) {
factories.add(TypeAdapters.newTypeHierarchyFactory(baseType, (TypeAdapter)typeAdapter));
}
return this;
}
/**
* Section 2.4 of <a href="http://www.ietf.org/rfc/rfc4627.txt">JSON specification</a> disallows
* special double values (NaN, Infinity, -Infinity). However,
* <a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf">Javascript
* specification</a> (see section 4.3.20, 4.3.22, 4.3.23) allows these values as valid Javascript
* values. Moreover, most JavaScript engines will accept these special values in JSON without
* problem. So, at a practical level, it makes sense to accept these values as valid JSON even
* though JSON specification disallows them.
*
* <p>Gson always accepts these special values during deserialization. However, it outputs
* strictly compliant JSON. Hence, if it encounters a float value {@link Float#NaN},
* {@link Float#POSITIVE_INFINITY}, {@link Float#NEGATIVE_INFINITY}, or a double value
* {@link Double#NaN}, {@link Double#POSITIVE_INFINITY}, {@link Double#NEGATIVE_INFINITY}, it
* will throw an {@link IllegalArgumentException}. This method provides a way to override the
* default behavior when you know that the JSON receiver will be able to handle these special
* values.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder serializeSpecialFloatingPointValues() {
this.serializeSpecialFloatingPointValues = true;
return this;
}
/**
* Creates a {@link Gson} instance based on the current configuration. This method is free of
* side-effects to this {@code GsonBuilder} instance and hence can be called multiple times.
*
* @return an instance of Gson configured with the options currently set in this builder
*/
public Gson create() {
List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>(this.factories.size() + this.hierarchyFactories.size() + 3);
factories.addAll(this.factories);
Collections.reverse(factories);
Collections.reverse(this.hierarchyFactories);
factories.addAll(this.hierarchyFactories);
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories);
return new Gson(excluder, fieldNamingPolicy, instanceCreators,
serializeNulls, complexMapKeySerialization,
generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient,
serializeSpecialFloatingPointValues, longSerializationPolicy, factories);
}
private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
List<TypeAdapterFactory> factories) {
DefaultDateTypeAdapter dateTypeAdapter;
if (datePattern != null && !"".equals(datePattern.trim())) {
dateTypeAdapter = new DefaultDateTypeAdapter(datePattern);
} else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle);
} else {
return;
}
factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Date.class), dateTypeAdapter));
factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Timestamp.class), dateTypeAdapter));
factories.add(TreeTypeAdapter.newFactory(TypeToken.get(java.sql.Date.class), dateTypeAdapter));
}
}
功能介紹】:
①兼容市面上主流的多家相機,理論上兼容所有硬件,可靈活擴展,②相機識別後數據自動上傳到雲端並記錄,校驗相機唯一id和硬件序列號,防止非法數據錄入,③用戶手機查詢停車記錄詳情可自主繳費(支持微信,支付寶,銀行接口支付,支持每個停車場指定不同的商戶進行收款),支付後出場在免費時間內會自動擡杆。④支持app上查詢附近停車場(導航,可用車位數,停車場費用,優惠券,評分,評論等),可預約車位。⑤斷電斷網支持崗亭人員使用app可接管硬件進行停車記錄的錄入。
【技術架構】:
後端開發語言java,框架oauth2+springboot2+doubble2.7.3,數據庫mysql/mongodb/redis,即時通訊底層框架netty4,安卓和ios均爲原生開發,後臺管理模板vue-typescript-admin-template,文件服務fastDFS,短信目前僅集成阿里雲短信服務。爲千萬級數據而生,千萬級用戶無憂,目前真實用戶40w無壓力,大數據時代物聯網必備
【開源情況】:
代碼完全開源,不存在授權問題,完全自主原創,不存在任何後門,不使用任何第三方私有jar包,性能和安全完全自主可控,想怎麼耍就這麼耍,就是這麼任性,後續更新的話本人會持續更新部署教程。代碼專業規範,新手看得懂,高手喜歡用。本系統完全免費
【部署環境】:
目前僅測試linux環境一切正常,win環境沒部署過,演示地址在本文章末尾
【關於作者】:
屌絲碼農一枚,4年前曾就職於開發停車場系統的公司,發現目前國內該領域壟斷,技術過於陳舊,沒有一個規範,故個人用來接近1年的時間在業餘時間開發出這種系統,現代化標準的互聯網應用,定位大型物聯網大數據雲平臺系統,存在不足之處還望多多提寶貴意見,讓我們打破市場壟斷,讓物聯網應用更好的服務生活社會
軟件架構
一、技術構成簡述 (一)編程語言與架構簡述 1.開發語言 (1)服務端 服務端語言目前均採用java語言開發,jdk版本要求1.8+。開發框架爲springboot2+dubbo,鑑權採用oauth2,DB操作框架Mybaits,即時通訊底層框架與協議netty4
(2)客戶端 目前我們主要客戶端分爲三個場景,分別爲安卓,ios,微信公衆號。安卓與ios均爲原生開發,H5頁面web端框架爲vue
(3)後臺管理 後臺管理前端框架採用的是主流的vue element admin(TypeScript版本),分層清晰,官方文檔完整,社區活躍
2.數據存儲 (1)重要數據存儲 重要數據均採用mysql進行存儲,支持部署主從,大部分數據儘可能進行事務處理,確保數據容災性
(2)一般數據存儲 非重要性數據例如聊天內容,系統消息通知,廣告等數據均存儲於mongodb數據庫中
(3)緩存數據存儲 微小量緩存會存在mysql中,例如評論的前N條評論快照會超小量進行字段適當冗餘,在提高存儲性價比情況下大大提高數據的查詢能力。其它大部分數據緩存均存儲於redis數據中
3.性能與安全 (1)性能解決方案 架構與技術解決方案均爲本團隊一線5年開發經驗總結,目前我們正在接觸的項目真實用戶40w+,毫無壓力,我們系統採用的架構與技術均在仔細多方面綜合考慮後多次調整,採用更加合理,性能更佳的模式與解決方案
(2)安全解決方案 所有請求均需攜帶jwt串token進行訪問,每個接口服務和管理服務均需配置公鑰文件且具有jwt串token合法性校驗能力,用戶權限服務攜帶私鑰文件負責密鑰生成
4.架構與生命力 (1)採用架構 本系統採用阿里巴巴微服務框架dubbo來進行實現微服務提供能力,追求高性能,高可用,超細粒度獨立微服務,相同服務可以動態靈活增加與減少,支持不停機發布新版本服務。每個服務之間均爲獨立存在,互不影響。例如短信發送,支付,訂單,停車場系統接口,停車場後臺管理,停車場提供者服務等均爲獨立的服務。
(2)架構潛力 整個系統衆多服務分工明確,細粒度微服務,實現真正的插拔服務,功能的刪減或停用,新增等均可在不破壞和入侵原來系統的前提下滿足新的開發需求
5.二次開發說明 (1)適用客戶對象 ①本身有互聯網it編程技術和經驗或者擁有技術團隊的。 ②不具備第一個條件但是費用預算比較充足,二次開發需求少或者願意支付高額定製費的 (2)團隊要求 服務器運維,安卓與ios開發者,web前端開發者,java實際開發經驗2年+開發者
(3)技術要求 過硬的java編程能力,網絡編程能力,數據庫設計與優化能力,架構設計能力,微服務思維能力,成熟的前端技術開發能力,中大型系統部署與運營能力
(4)硬件要求 Linux操作系統,4核8G(最低)5M帶寬,可多臺服務器中的微服務指向統一微服務調度中心(本系統微服務調度中心管理平臺zookeeper)
(二)軟件與硬件數據交互簡述 1.硬件端 (1)目前解決方案 封裝工具類,兼容市場主流硬件設備,只負責各類硬件數據封裝爲統一數據結構。硬件發包目前多爲http主動推送數據,被動接受服務端返回指令
(2)未來解決方案 改造主流廠商硬件底層服務系統,新增硬件規範的合法身份數據,採用長連接進行數據交互,保證數據與指令的實時性與可靠性得到更好的保障
2.服務端 (1)被動處理硬件數據 中間件處理各類前端數據,接收硬件推送數據,解析,計算,做出相應反饋
(2)主動通知硬件發生事件行爲 長連接推送指令,例如開閘,實時動態配置硬件數據等,
二、常規功能簡述 (一)基礎功能 1.硬件管理 支持單個硬件管理與記錄,硬件在線狀態,維修與進度記錄等。與指定停車場出入口進行綁定,均有記錄GPS位置
2.停車場管理 不同時段費用配置,每日封頂因素綜合參與動態計費,也支持靜態+每日上限計費。支持查詢附近停車場功能
3.停車記錄管理 詳細記錄產生時間,地點,進出口位置,進出時間,異常數據實時推送與快速處理
4.支付機構管理 每個停車場的支付賬號均可以獨立配置,支持同一個停車場使用多家支付機構進行支付,例如支付寶,微信,銀聯等。
5.支付與優惠活動管理 支付寶與微信,銀聯都均支持免密支付(無感支付)。本系統自帶優惠券功能,支持支持多種套餐自定義與用戶進行快捷手機上下單隨時購買
(二)特色功能 1.異常數據實時推送,彙報,及時處理,提前預知與通知 2.即時通訊功能(IM聊天溝通) 性能,架構,優化等均參考微信聊天功能機制進行開發
3.行業好友與圈子 讓該應用不止只能停車,還能交到志同道合的行業知音,讓應用更有溫度
4.商城與營銷功能 此功能主要考慮到使用者有運營周邊的興趣和能力,在商城和廣告營銷上進行盈利
安裝教程
- 安裝JDK1.8+
- 安裝MySQL5.6+ 安裝MongoDB 安裝Redis 安裝FastDFS 安裝Zookeeper
- 將打包好的代碼上傳到服務器上,直接運行jar包即可
使用說明(swagger2文檔)
【用戶基礎數據相關】:http://139.9.155.149:8080/swagger-ui.html 【停車場相關】:http://139.9.155.149:8089/swagger-ui.html 【短信】:http://139.9.155.149:8085/swagger-ui.html 【文件上傳】:http://139.9.155.149:8088/swagger-ui.html 【支付相關】:http://139.9.155.149:8096/swagger-ui.html
參與貢獻
- Fork 本倉庫
- 新建 Feat_xxx 分支
- 提交代碼
- 新建 Pull Request
演示地址
http://139.9.155.149 admin 123456
如果您發現有代碼有什麼不足之處請跟我留言