From 66c67179c7493343f1f4bfb807c15385c2abb684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johnny=20Miller=20=28=E9=94=BA=E4=BF=8A=29?= Date: Tue, 29 Dec 2020 16:04:21 +0800 Subject: [PATCH] feat($AuthCenter): add logout API --- .../src/main/resources/application.yml | 2 + .../security/service/JwtService.java | 6 +- .../security/service/impl/JwtServiceImpl.java | 34 +++--- .../RedisClientConfiguration.java | 40 ------- .../universal/service/RedisService.java | 107 ----------------- .../service/impl/RedisServiceImpl.java | 110 ------------------ .../user/controller/UserController.java | 15 ++- .../authcenter/user/service/UserService.java | 10 ++ .../user/service/impl/UserServiceImpl.java | 7 ++ .../domain/authcenter/user/LogoutPayload.java | 13 +++ .../controller/CommonController.java | 9 +- .../service/CommonService.java | 4 +- .../service/impl/CommonServiceImpl.java | 93 +-------------- 13 files changed, 72 insertions(+), 378 deletions(-) delete mode 100644 auth-center/src/main/java/com/jmsoftware/maf/authcenter/universal/configuration/RedisClientConfiguration.java delete mode 100644 auth-center/src/main/java/com/jmsoftware/maf/authcenter/universal/service/RedisService.java delete mode 100644 auth-center/src/main/java/com/jmsoftware/maf/authcenter/universal/service/impl/RedisServiceImpl.java create mode 100644 common/src/main/java/com/jmsoftware/maf/common/domain/authcenter/user/LogoutPayload.java diff --git a/api-gateway/src/main/resources/application.yml b/api-gateway/src/main/resources/application.yml index 9bc74fd6..14df26f2 100644 --- a/api-gateway/src/main/resources/application.yml +++ b/api-gateway/src/main/resources/application.yml @@ -95,7 +95,9 @@ maf: configuration: ignored-url: post: + - "/auth-center/users/signup" - "/auth-center/users/login" + - "/auth-center/users/logout" get: - "/favicon.ico" - "/auth/check-username-uniqueness" diff --git a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/security/service/JwtService.java b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/security/service/JwtService.java index ffc42151..f89d152a 100644 --- a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/security/service/JwtService.java +++ b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/security/service/JwtService.java @@ -28,9 +28,8 @@ public interface JwtService { * @param authentication the authentication * @param rememberMe the remember me * @return the string - * @throws SecurityException the security exception */ - String createJwt(Authentication authentication, Boolean rememberMe) throws SecurityException; + String createJwt(Authentication authentication, Boolean rememberMe); /** * Create JWT string. @@ -41,10 +40,9 @@ public interface JwtService { * @param roles the roles * @param authorities the authorities * @return the JWT string - * @throws SecurityException the security exception */ String createJwt(Boolean rememberMe, Long id, String subject, List roles, Collection authorities) throws SecurityException; + extends GrantedAuthority> authorities); /** * Parse JWT. diff --git a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/security/service/impl/JwtServiceImpl.java b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/security/service/impl/JwtServiceImpl.java index 1935af31..f3a07d99 100644 --- a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/security/service/impl/JwtServiceImpl.java +++ b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/security/service/impl/JwtServiceImpl.java @@ -5,7 +5,6 @@ import cn.hutool.core.util.StrUtil; import com.jmsoftware.maf.authcenter.security.service.JwtService; import com.jmsoftware.maf.authcenter.universal.configuration.JwtConfiguration; -import com.jmsoftware.maf.authcenter.universal.service.RedisService; import com.jmsoftware.maf.common.domain.authcenter.security.ParseJwtPayload; import com.jmsoftware.maf.common.domain.authcenter.security.ParseJwtResponse; import com.jmsoftware.maf.common.domain.authcenter.security.UserPrincipal; @@ -15,6 +14,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import lombok.val; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; @@ -44,7 +46,7 @@ @SuppressWarnings("unused") public class JwtServiceImpl implements JwtService { private final JwtConfiguration jwtConfiguration; - private final RedisService redisService; + private final RedisTemplate redisTemplate; private SecretKey secretKey; private JwtParser jwtParser; @@ -54,10 +56,12 @@ private void init() { secretKey = Keys.hmacShaKeyFor(jwtConfiguration.getSigningKey().getBytes(StandardCharsets.UTF_8)); log.warn("Secret key for JWT was generated. Algorithm: {}", secretKey.getAlgorithm()); jwtParser = Jwts.parserBuilder().setSigningKey(secretKey).build(); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); } @Override - public String createJwt(Authentication authentication, Boolean rememberMe) throws SecurityException { + public String createJwt(Authentication authentication, Boolean rememberMe) { val userPrincipal = (UserPrincipal) authentication.getPrincipal(); return createJwt(rememberMe, userPrincipal.getId(), userPrincipal.getUsername(), userPrincipal.getRoles(), userPrincipal.getAuthorities()); @@ -65,7 +69,7 @@ public String createJwt(Authentication authentication, Boolean rememberMe) throw @Override public String createJwt(Boolean rememberMe, Long id, String subject, List roles, - Collection authorities) throws SecurityException { + Collection authorities) { val now = new Date(); val builder = Jwts.builder() .setId(id.toString()) @@ -82,13 +86,10 @@ public String createJwt(Boolean rememberMe, Long id, String subject, ListRedisClientConfiguration - *

- * Ignored request configuration. - * - * @author Johnny Miller (锺俊), email: johnnysviva@outlook.com - * @date 5/2/20 11:41 PM - **/ -@Configuration -@EnableCaching -@AutoConfigureAfter(RedisAutoConfiguration.class) -public class RedisClientConfiguration extends CachingConfigurerSupport { - /** - * Redis template. Support for <String, Serializable> - */ - @Bean - public RedisTemplate redisFactory(LettuceConnectionFactory lettuceConnectionFactory) { - val template = new RedisTemplate(); - template.setKeySerializer(new StringRedisSerializer()); - template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); - template.setConnectionFactory(lettuceConnectionFactory); - return template; - } -} diff --git a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/universal/service/RedisService.java b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/universal/service/RedisService.java deleted file mode 100644 index 56d154fd..00000000 --- a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/universal/service/RedisService.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.jmsoftware.maf.authcenter.universal.service; - -import java.io.Serializable; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.TimeUnit; - -/** - *

RedisService

- *

Redis service interface for Redis useful operations

- * - * @author Johnny Miller (锺俊), email: johnnysviva@outlook.com - * @date 2019-07-05 09:38 - **/ -public interface RedisService { - /** - * Set key and value in Redis with expiration - * - * @param key key - * @param value value - * @param expirationTime expiration time - * @param timeUnit time unit - * @return true - operation done; false - operation failure - */ - Boolean set(String key, String value, Long expirationTime, TimeUnit timeUnit); - - /** - * Set key and list in Redis with expiration - * - * @param key key - * @param list list - * @param expirationTime expiration time - * @param timeUnit time unit - * @return true - operation done; false - operation failure - */ - Boolean set(String key, List list, Long expirationTime, TimeUnit timeUnit); - - /** - * Set key and value in Redis - * - * @param key key - * @param value value - * @return true - operation done; false - operation failure - */ - Boolean set(String key, String value); - - /** - * Set key and list in Redis - * - * @param key key - * @param list list - * @return true - operation done; false - operation failure - */ - Boolean set(String key, List list); - - /** - * Make key expire - * - * @param key key - * @param expirationTime expiration time - * @param timeUnit time unit - * @return true - operation done; false - operation failure - */ - Boolean expire(String key, long expirationTime, TimeUnit timeUnit); - - /** - * Get expiration time by key - * - * @param key key - * @param timeUnit time unit - * @return expiration time. Null when used in pipeline / transaction. - */ - Long getExpire(String key, TimeUnit timeUnit); - - /** - * Get value by key - * - * @param key key - * @return null when key does not exist or used in pipeline / transaction. - */ - String get(String key); - - /** - * Get list by key - * - * @param key key - * @param clazz type - * @return null when key does not exist or used in pipeline / transaction. - */ - List get(String key, Class clazz); - - /** - * Delete by key - * - * @param key key - * @return the number of keys that were removed. Null when used in pipeline / transaction. - */ - Long delete(String key); - - /** - * Delete by keys - * - * @param keys key list - * @return the number of keys that were removed. Null when used in pipeline / transaction. - */ - Long delete(Collection keys); -} diff --git a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/universal/service/impl/RedisServiceImpl.java b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/universal/service/impl/RedisServiceImpl.java deleted file mode 100644 index ae4fd1c5..00000000 --- a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/universal/service/impl/RedisServiceImpl.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.jmsoftware.maf.authcenter.universal.service.impl; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.json.JSONUtil; -import com.jmsoftware.maf.authcenter.universal.service.RedisService; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.data.redis.connection.RedisStringCommands; -import org.springframework.data.redis.core.RedisCallback; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.types.Expiration; -import org.springframework.stereotype.Service; - -import java.io.Serializable; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.TimeUnit; - -/** - *

RedisServiceImpl

- *

Redis service implementation for Redis useful operations

- * - * @author Johnny Miller (锺俊), email: johnnysviva@outlook.com - * @date 2019-07-05 09:39 - **/ -@Service -public class RedisServiceImpl implements RedisService { - private final RedisTemplate redisTemplate; - - public RedisServiceImpl(@Qualifier("redisFactory") RedisTemplate redisTemplate) { - this.redisTemplate = redisTemplate; - } - - @Override - public Boolean set(String key, String value, Long expirationTime, TimeUnit timeUnit) { - return redisTemplate.execute((RedisCallback) connection -> { - var serializer = redisTemplate.getStringSerializer(); - var result = connection.set(Objects.requireNonNull(serializer.serialize(key)), - Objects.requireNonNull(serializer.serialize(value)), - Expiration.from(expirationTime, timeUnit), - RedisStringCommands.SetOption.upsert()); - return ObjectUtil.isNotNull(result) ? result : false; - }); - } - - @Override - public Boolean set(String key, List list, Long expirationTime, TimeUnit timeUnit) { - var value = JSONUtil.toJsonStr(list); - return set(key, value, expirationTime, timeUnit); - } - - @Override - public Boolean set(String key, String value) { - return redisTemplate.execute((RedisCallback) connection -> { - var serializer = redisTemplate.getStringSerializer(); - var result = connection.set(Objects.requireNonNull(serializer.serialize(key)), - Objects.requireNonNull(serializer.serialize(value))); - return ObjectUtil.isNotNull(result) ? result : false; - }); - } - - @Override - public Boolean set(String key, List list) { - var value = JSONUtil.toJsonStr(list); - return set(key, value); - } - - @Override - public Boolean expire(String key, long expirationTime, TimeUnit timeUnit) { - var result = redisTemplate.expire(key, expirationTime, timeUnit); - return ObjectUtil.isNotNull(result) ? result : false; - } - - @Override - public Long getExpire(String key, TimeUnit timeUnit) { - return redisTemplate.getExpire(key, timeUnit); - } - - @Override - public String get(String key) { - return redisTemplate.execute((RedisCallback) connection -> { - var serializer = redisTemplate.getStringSerializer(); - var bytes = connection.get(Objects.requireNonNull(serializer.serialize(key))); - return serializer.deserialize(bytes); - }); - } - - @Override - public List get(String key, Class clazz) { - var json = get(key); - if (StrUtil.isNotBlank(json)) { - return JSONUtil.toList(JSONUtil.parseArray(json), clazz); - } - return null; - } - - @Override - public Long delete(String key) { - return redisTemplate.execute((RedisCallback) connection -> { - var serializer = redisTemplate.getStringSerializer(); - return connection.del(serializer.serialize(key)); - }); - } - - @Override - public Long delete(Collection keys) { - return redisTemplate.delete(keys); - } -} diff --git a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/user/controller/UserController.java b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/user/controller/UserController.java index 15ac5776..4ef3bfbe 100644 --- a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/user/controller/UserController.java +++ b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/user/controller/UserController.java @@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; /** @@ -32,15 +33,21 @@ public class UserController { private final UserService userService; + @PostMapping("/users/signup") + @ApiOperation(value = "Save user for signup", notes = "Save user for signup") + public ResponseBodyBean signup(@Valid @RequestBody SignupPayload payload) { + return ResponseBodyBean.ofSuccess(userService.saveUserForSignup(payload)); + } + @PostMapping("/users/login") @ApiOperation(value = "Login", notes = "Login") public ResponseBodyBean login(@Valid @RequestBody LoginPayload payload) throws SecurityException { return ResponseBodyBean.ofSuccess(userService.login(payload)); } - @PostMapping("/users/signup") - @ApiOperation(value = "Save user for signup", notes = "Save user for signup") - public ResponseBodyBean signup(@Valid @RequestBody SignupPayload payload) { - return ResponseBodyBean.ofSuccess(userService.saveUserForSignup(payload)); + @PostMapping("/users/logout") + @ApiOperation(value = "Logout", notes = "Logout") + public ResponseBodyBean logout(HttpServletRequest request) throws SecurityException { + return ResponseBodyBean.ofSuccess(userService.logout(request)); } } diff --git a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/user/service/UserService.java b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/user/service/UserService.java index 55364dea..7eaeda5c 100644 --- a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/user/service/UserService.java +++ b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/user/service/UserService.java @@ -6,6 +6,7 @@ import com.jmsoftware.maf.common.exception.SecurityException; import org.springframework.validation.annotation.Validated; +import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import javax.validation.constraints.NotBlank; @@ -43,4 +44,13 @@ public interface UserService extends IService { * @throws SecurityException the security exception */ LoginResponse login(@Valid LoginPayload payload) throws SecurityException; + + /** + * Logout boolean. + * + * @param request the request + * @return the boolean + * @throws SecurityException the security exception + */ + boolean logout(HttpServletRequest request) throws SecurityException; } diff --git a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/user/service/impl/UserServiceImpl.java b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/user/service/impl/UserServiceImpl.java index b394b3b8..a54f6571 100644 --- a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/user/service/impl/UserServiceImpl.java +++ b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/user/service/impl/UserServiceImpl.java @@ -18,6 +18,7 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; +import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import java.util.Date; @@ -88,4 +89,10 @@ public LoginResponse login(@Valid LoginPayload payload) throws SecurityException } throw new SecurityException(HttpStatus.UNAUTHORIZED); } + + @Override + public boolean logout(HttpServletRequest request) throws SecurityException { + jwtService.invalidateJwt(request); + return true; + } } diff --git a/common/src/main/java/com/jmsoftware/maf/common/domain/authcenter/user/LogoutPayload.java b/common/src/main/java/com/jmsoftware/maf/common/domain/authcenter/user/LogoutPayload.java new file mode 100644 index 00000000..9738ed0d --- /dev/null +++ b/common/src/main/java/com/jmsoftware/maf/common/domain/authcenter/user/LogoutPayload.java @@ -0,0 +1,13 @@ +package com.jmsoftware.maf.common.domain.authcenter.user; + +import lombok.Data; + +/** + * Description: LogoutPayload, change description here. + * + * @author 钟俊(zhongjun), email: zhongjun@toguide.cn, date: 12/29/2020 3:33 PM + **/ +@Data +public class LogoutPayload { + private String jwt; +} diff --git a/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/controller/CommonController.java b/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/controller/CommonController.java index bf743594..ad92774c 100644 --- a/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/controller/CommonController.java +++ b/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/controller/CommonController.java @@ -1,16 +1,14 @@ package com.jmsoftware.maf.springbootstarter.controller; +import cn.hutool.json.JSON; import com.jmsoftware.maf.common.bean.ResponseBodyBean; import com.jmsoftware.maf.common.domain.ValidationTestPayload; import com.jmsoftware.maf.springbootstarter.service.CommonService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; -import lombok.val; import org.springframework.web.bind.annotation.*; -import java.util.Map; - /** *

CommonController

*

@@ -27,9 +25,8 @@ public class CommonController { @GetMapping("/app-info") @ApiOperation(value = "/app-info", notes = "Retrieve application information") - public ResponseBodyBean> applicationInformation() { - val data = commonService.getApplicationInfo(); - return ResponseBodyBean.ofSuccess(data, "Succeed to retrieve app info."); + public ResponseBodyBean applicationInformation() { + return ResponseBodyBean.ofSuccess(commonService.getApplicationInfo(), "Succeed to retrieve app info."); } @PostMapping("/validation-test") diff --git a/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/service/CommonService.java b/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/service/CommonService.java index 524c852f..37467418 100644 --- a/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/service/CommonService.java +++ b/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/service/CommonService.java @@ -1,10 +1,10 @@ package com.jmsoftware.maf.springbootstarter.service; +import cn.hutool.json.JSON; import com.jmsoftware.maf.common.domain.ValidationTestPayload; import org.springframework.validation.annotation.Validated; import javax.validation.Valid; -import java.util.Map; /** *

CommonService

@@ -21,7 +21,7 @@ public interface CommonService { * * @return the application info. */ - Map getApplicationInfo(); + JSON getApplicationInfo(); /** * Validate object. diff --git a/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/service/impl/CommonServiceImpl.java b/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/service/impl/CommonServiceImpl.java index a4b87980..4b05c0d6 100644 --- a/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/service/impl/CommonServiceImpl.java +++ b/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/service/impl/CommonServiceImpl.java @@ -1,5 +1,7 @@ package com.jmsoftware.maf.springbootstarter.service.impl; +import cn.hutool.json.JSON; +import cn.hutool.json.JSONUtil; import com.jmsoftware.maf.common.domain.ValidationTestPayload; import com.jmsoftware.maf.springbootstarter.configuration.MafProjectProperty; import com.jmsoftware.maf.springbootstarter.service.CommonService; @@ -8,12 +10,6 @@ import org.springframework.stereotype.Service; import javax.validation.Valid; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; /** *

CommonServiceImpl

@@ -29,93 +25,12 @@ public class CommonServiceImpl implements CommonService { private final MafProjectProperty mafProjectProperty; @Override - public Map getApplicationInfo() { - var map = new HashMap(16); - var fieldsInfo = getFieldsInfo(mafProjectProperty); - fieldsInfo.forEach(fieldInfo -> { - var type = fieldInfo.get("type"); - if ("class java.lang.String".equals(type)) { - map.put((String) fieldInfo.get("name"), fieldInfo.get("value")); - } - }); - return map; + public JSON getApplicationInfo() { + return JSONUtil.parse(mafProjectProperty); } @Override public void validateObject(@Valid ValidationTestPayload payload) { log.info("Validation passed! {}", payload); } - - /** - * Gets field value by name. - * - * @param fieldName the field name - * @param object the object - * @return the field value by name - * @see Java 中遍历一个对象的所有属性 - */ - private Object getFieldValueByName(String fieldName, Object object) { - try { - String firstLetter = fieldName.substring(0, 1).toUpperCase(); - String getter = "get" + firstLetter + fieldName.substring(1); - Method method = object.getClass().getMethod(getter); - return method.invoke(object); - } catch (Exception e) { - log.error("Can't get field's value by name! Cause: {}", e.getMessage()); - return null; - } - } - - /** - * Get filed name string [ ]. - * - * @param o the o - * @return the string [ ] - * @see Java 中遍历一个对象的所有属性 - */ - private String[] getFiledName(Object o) { - Field[] fields = o.getClass().getDeclaredFields(); - String[] fieldNames = new String[fields.length]; - for (int i = 0; i < fields.length; i++) { - log.info("fields[i].getType(): {}", fields[i].getType()); - fieldNames[i] = fields[i].getName(); - } - return fieldNames; - } - - /** - * Get Fields Info - * - * @param o the o - * @return the fields info - * @see Java 中遍历一个对象的所有属性 - */ - private List> getFieldsInfo(Object o) { - Field[] fields = o.getClass().getDeclaredFields(); - var arrayList = new ArrayList>(); - for (Field field : fields) { - var infoMap = new HashMap(16); - infoMap.put("type", field.getType().toString()); - infoMap.put("name", field.getName()); - infoMap.put("value", getFieldValueByName(field.getName(), o)); - arrayList.add(infoMap); - } - return arrayList; - } - - /** - * Get Filed Values - * - * @param o the o - * @return the object [ ] - * @see Java 中遍历一个对象的所有属性 - */ - public Object[] getFiledValues(Object o) { - String[] fieldNames = this.getFiledName(o); - Object[] value = new Object[fieldNames.length]; - for (int i = 0; i < fieldNames.length; i++) { - value[i] = this.getFieldValueByName(fieldNames[i], o); - } - return value; - } }