Browse Source

用户表增删改查 ~~~

master
sige 2 years ago
parent
commit
903c1bbd20
  1. 9
      src/src/main/java/com/my/graphiteDigesterBg/diframe/ActiveRecordField.java
  2. 179
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActiveRecord.java
  3. 10
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActiveRecordCriteria.java
  4. 15
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiApiControllerBase.java
  5. 95
      src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiUser.java
  6. 40
      src/src/main/java/com/my/graphiteDigesterBg/diframe/mapper/DiActiveRecordMapper.java
  7. 49
      src/src/main/java/com/my/graphiteDigesterBg/diframe/model/DiMdbUser.java
  8. 4
      src/src/main/resources/application.yml

9
src/src/main/java/com/my/graphiteDigesterBg/diframe/ActiveRecordField.java

@ -0,0 +1,9 @@
package com.my.graphiteDigesterBg.diframe;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface ActiveRecordField {
}

179
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActiveRecord.java

@ -1,12 +1,181 @@
package com.my.graphiteDigesterBg.diframe;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.my.graphiteDigesterBg.diframe.mapper.DiActiveRecordMapper;
abstract public class DiActiveRecord {
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DiActiveRecord {
// is new record
@JsonIgnore
public Boolean isNewRecord = true;
// save model
public void save() {
var context = DiApplicationContextProvider.getContext();
DiActiveRecordMapper mapper = context.getBean(DiActiveRecordMapper.class);
String tableName = DiActiveRecord.getTableNameFromModelClass(this.getClass());
Map<String,Object> data = DiActiveRecord.exportModelData(this);
if ( this.isNewRecord ) {
mapper.insert(tableName, data);
} else {
mapper.update(tableName, (Integer)data.get("id"), data);
}
}
// delete model
public void delete() {
var context = DiApplicationContextProvider.getContext();
DiActiveRecordMapper mapper = context.getBean(DiActiveRecordMapper.class);
String tableName = DiActiveRecord.getTableNameFromModelClass(this.getClass());
Map<String,Object> data = DiActiveRecord.exportModelData(this);
mapper.delete(tableName, (Integer)data.get("id"));
}
// set attributes
public void setAttributes( Map<String,Object> attributes ) {
for ( Map.Entry<String,Object> entry : attributes.entrySet() ) {
String key = entry.getKey();
Field field = null;
try {
field = this.getClass().getDeclaredField(key);
} catch (NoSuchFieldException e) {
continue ;
}
Class<?> fieldType = field.getType();
if ( !fieldType.isAssignableFrom(entry.getValue().getClass()) ) {
throw new RuntimeException("Attribute type mismatch: " + key);
}
field.setAccessible(true);
try {
field.set(this, entry.getValue());
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
// find by id
public static void findOne(Integer id) {
public static <T extends DiActiveRecord> T findOne( Class<T> modelClass, Integer id) {
return DiActiveRecord.findOne(modelClass, Map.of("id", id));
}
// find one by conditions
public static <T extends DiActiveRecord> T findOne( Class<T> modelClass, Map<String,Object> conditions) {
var criteria = new DiActiveRecordCriteria();
criteria.tableName = DiActiveRecord.getTableNameFromModelClass(modelClass);
criteria.conditions = conditions;
criteria.limit = 1;
var context = DiApplicationContextProvider.getContext();
DiActiveRecordMapper mapper = context.getBean(DiActiveRecordMapper.class);
var rows = mapper.find(criteria);
if (rows.isEmpty()) {
return null;
}
T model = DiActiveRecord.fillModel(modelClass, rows.get(0));
model.isNewRecord = false;
return model;
}
// find all by criteria
public static <T extends DiActiveRecord> List<T> find( Class<T> modelClass, DiActiveRecordCriteria criteria ) {
criteria.tableName = DiActiveRecord.getTableNameFromModelClass(modelClass);
var context = DiApplicationContextProvider.getContext();
DiActiveRecordMapper mapper = context.getBean(DiActiveRecordMapper.class);
var row = mapper.findById("di_app_users", id);
// // @TODO : 这里要根据配置参数计算 ~~~
System.out.println("DiActiveRecord.findById");
var rows = mapper.find(criteria);
List<T> models = new ArrayList<>();
for ( var row : rows ) {
T model = DiActiveRecord.fillModel(modelClass, row);
model.isNewRecord = false;
models.add(model);
}
return models;
}
// get table name from model class
private static <T> String getTableNameFromModelClass( Class<T> modelClass) {
Method tableNameGetter = null;
try {
tableNameGetter = modelClass.getMethod("getTableName");
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
String tableName = null;
try {
tableName = (String)tableNameGetter.invoke(null);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
return tableName;
}
// fill model
private static <T> T fillModel(Class<T> modelClass, Map<String,Object> data) {
Constructor<?> modelConstructor = null;
try {
modelConstructor = modelClass.getDeclaredConstructor();
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
T model = null;
try {
model = (T)modelConstructor.newInstance();
} catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
for ( Map.Entry<String,Object> entry : data.entrySet() ) {
String key = entry.getKey();
Field field = null;
try {
field = model.getClass().getDeclaredField(key);
} catch (NoSuchFieldException e) {
continue ;
}
Class<?> fieldType = field.getType();
if ( !fieldType.isAssignableFrom(entry.getValue().getClass()) ) {
throw new RuntimeException("Attribute type mismatch: " + key);
}
field.setAccessible(true);
try {
field.set(model, entry.getValue());
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
return model;
}
// model to map
private static Map<String,Object> exportModelData(Object model) {
Map<String,Object> data = new HashMap<>();
var fields = model.getClass().getDeclaredFields();
for ( var field : fields ) {
var annotation = field.getAnnotation(ActiveRecordField.class);
if ( annotation == null ) {
continue ;
}
field.setAccessible(true);
try {
data.put(field.getName(), field.get(model));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
return data;
}
}

10
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActiveRecordCriteria.java

@ -0,0 +1,10 @@
package com.my.graphiteDigesterBg.diframe;
import java.util.Map;
public class DiActiveRecordCriteria {
// table name
public String tableName;
// conditions
public Map<String,Object> conditions;
// limit
public Integer limit;
}

15
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiApiControllerBase.java

@ -1,4 +1,10 @@
package com.my.graphiteDigesterBg.diframe;
import com.my.graphiteDigesterBg.diframe.model.DiMdbUser;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Map;
abstract public class DiApiControllerBase {
/**
* success response
@ -51,4 +57,13 @@ abstract public class DiApiControllerBase {
response.code = code;
return response;
}
// get user from request
protected DiMdbUser getUserFromRequest(HttpServletRequest request) {
String accessToken = request.getHeader("App-Access-Token");
if ( null == accessToken ) {
return null;
}
return DiActiveRecord.findOne(DiMdbUser.class, Map.of("accessToken", accessToken));
}
}

95
src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiUser.java

@ -1,18 +1,107 @@
package com.my.graphiteDigesterBg.diframe.api;
import com.my.graphiteDigesterBg.diframe.DiActiveRecord;
import com.my.graphiteDigesterBg.diframe.DiActiveRecordCriteria;
import com.my.graphiteDigesterBg.diframe.DiApiControllerBase;
import com.my.graphiteDigesterBg.diframe.DiApiResponse;
import com.my.graphiteDigesterBg.diframe.model.DiMdbUser;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Map;
import java.util.UUID;
@Controller
public class DiApiUser extends DiApiControllerBase {
@ResponseBody
@RequestMapping("/api/user/login")
public DiApiResponse login() {
DiMdbUser.findOne(1);
public DiApiResponse login(@RequestBody Map<String,Object> params) {
Integer id = (Integer)params.get("id");
String password = (String)params.get("password");
var user = DiActiveRecord.findOne(DiMdbUser.class, id);
if ( null == user || !user.matchPassword(password) ) {
return this.error("无效的账号或密码");
}
user.accessToken = UUID.randomUUID().toString();
user.accessTokenExpiredAt = (int)(System.currentTimeMillis() / 1000) + 3600 * 24;
user.save();
return this.success(Map.of(
"accessToken", user.accessToken,
"accessTokenExpiredAt", user.accessTokenExpiredAt
));
}
@ResponseBody
@RequestMapping("/api/user/logout")
public DiApiResponse logout( HttpServletRequest request ) {
String accessToken = request.getHeader("App-Access-Token");
var user = DiActiveRecord.findOne(DiMdbUser.class, Map.of("accessToken", accessToken));
if ( null == user ) {
return this.success();
}
user.accessToken = "";
user.accessTokenExpiredAt = 0;
user.save();
return this.success();
}
@ResponseBody
@PostMapping("/api/user/save")
public DiApiResponse save( HttpServletRequest request, @RequestBody Map<String,Object> params ) {
DiMdbUser curUser = this.getUserFromRequest(request);
Integer id = (Integer)params.get("id");
Map<String,Object> data = (Map<String,Object>)params.get("data");
var user = new DiMdbUser();
user.salt = UUID.randomUUID().toString().substring(0, 8);
user.createdAt = (int)(System.currentTimeMillis() / 1000);
user.createdBy = curUser.id;
if ( null != id ) {
user = DiActiveRecord.findOne(DiMdbUser.class, id);
}
user.setAttributes(data);
user.save();
return this.success();
}
public void logout() {}
@ResponseBody
@PostMapping("/api/user/delete")
public DiApiResponse delete( @RequestBody Map<String,Object> params ) {
Integer id = (Integer)params.get("id");
var user = DiActiveRecord.findOne(DiMdbUser.class, id);
if ( null == user ) {
return this.success();
}
user.delete();
return this.success();
}
@ResponseBody
@PostMapping("/api/user/updatePassword")
public DiApiResponse updatePassword( @RequestBody Map<String,Object> params ) {
Integer id = (Integer)params.get("id");
String password = (String)params.get("password");
var user = DiActiveRecord.findOne(DiMdbUser.class, id);
if ( null == user ) {
return this.error("无效的用户");
}
user.password = user.hashPassword(password);
user.save();
return this.success();
}
@ResponseBody
@RequestMapping("/api/user/list")
public DiApiResponse list() {
var criteria = new DiActiveRecordCriteria();
criteria.limit = 10;
var users = DiActiveRecord.find(DiMdbUser.class, criteria);
return this.success(Map.of("list",users));
}
}

40
src/src/main/java/com/my/graphiteDigesterBg/diframe/mapper/DiActiveRecordMapper.java

@ -1,9 +1,45 @@
package com.my.graphiteDigesterBg.diframe.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import com.my.graphiteDigesterBg.diframe.DiActiveRecordCriteria;
import org.apache.ibatis.annotations.*;
import java.util.List;
import java.util.Map;
@Mapper
public interface DiActiveRecordMapper {
@Select(
"<script>" +
"SELECT * FROM ${tableName} " +
"<if test='conditions != null'>" +
"WHERE " +
"<foreach collection='conditions' item='value' index='key' separator=' AND '>${key} = #{value}</foreach>" +
"</if>" +
"LIMIT #{limit}" +
"</script>"
)
List<Map<String,Object>> find(DiActiveRecordCriteria criteria);
@Select("SELECT * FROM ${tableName} WHERE id = #{id}")
Map<String,Object> findById(String tableName, Integer id);
@Insert(
"<script>" +
"INSERT INTO ${tableName} " +
"<foreach collection='data' item='value' index='key' open='(' separator=',' close=')'>${key}</foreach>" +
"VALUES " +
"<foreach collection='data' item='value' index='key' open='(' separator=',' close=')'>#{value}</foreach>" +
"</script>"
)
Integer insert(String tableName, Map<String,Object> data);
@Update(
"<script>" +
"UPDATE ${tableName} SET " +
"<foreach collection='data' item='value' index='key' separator=','>${key} = #{value}</foreach>" +
"WHERE id = #{id}" +
"</script>"
)
Integer update(String tableName, Integer id, Map<String,Object> data);
@Delete("DELETE FROM ${tableName} WHERE id = #{id}")
Integer delete(String tableName, Integer id);
}

49
src/src/main/java/com/my/graphiteDigesterBg/diframe/model/DiMdbUser.java

@ -1,5 +1,54 @@
package com.my.graphiteDigesterBg.diframe.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.my.graphiteDigesterBg.diframe.ActiveRecordField;
import com.my.graphiteDigesterBg.diframe.DiActiveRecord;
import org.springframework.util.DigestUtils;
public class DiMdbUser extends DiActiveRecord {
@ActiveRecordField
public Integer id;
@ActiveRecordField
public String account;
@JsonIgnore
@ActiveRecordField
public String password;
@JsonIgnore
@ActiveRecordField
public String salt;
@ActiveRecordField
public Integer roleId;
@ActiveRecordField
public Integer createdAt;
@ActiveRecordField
public Integer createdBy;
@JsonIgnore
@ActiveRecordField
public String accessToken;
@JsonIgnore
@ActiveRecordField
public Integer accessTokenExpiredAt;
// get table name
public static String getTableName() {
return "app_users";
}
// check if password matches
public Boolean matchPassword(String password) {
String hash = this.hashPassword(password);
return this.password.equals(hash);
}
// hash password
public String hashPassword(String password) {
String salt = this.salt;
return DigestUtils.md5DigestAsHex((salt + password + salt).getBytes());
}
}

4
src/src/main/resources/application.yml

@ -5,6 +5,10 @@ spring:
password: 1
driver-class-name: org.sqlite.JDBC
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
device :
connection :
class : com.my.graphiteDigesterBg.diframe.connection.DiConSerialPort

Loading…
Cancel
Save