diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/RedisConfig.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/RedisConfig.java index 5920f86..3a826d6 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/RedisConfig.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/RedisConfig.java @@ -6,6 +6,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import javax.annotation.Resource; @@ -36,4 +37,11 @@ public class RedisConfig { return template; } + @Bean + public StringRedisTemplate stringRedisTemplate() { + StringRedisTemplate template = new StringRedisTemplate(); + template.setConnectionFactory(factory); + return template; + } + } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/SerializeConfig.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/SerializeConfig.java index c5d940a..ed81dda 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/SerializeConfig.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/SerializeConfig.java @@ -1,8 +1,10 @@ package cn.edu.hfut.rmdjzz.projectmanagement.config; +import cn.edu.hfut.rmdjzz.projectmanagement.utils.http.IPAddress; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Autowired; @@ -25,11 +27,32 @@ public class SerializeConfig { @Bean public ObjectMapper objectMapper() { - ObjectMapper om = new ObjectMapper(); + om.registerModule(javaTimeModule()); + om.registerModule(customClassModule()); + return om; + } + + @SuppressWarnings({"Convert2Diamond", "NullableProblems", "rawtypes"}) + @Bean + public Converter mapConverter() { + return new Converter() { + + @Autowired + private ObjectMapper objectMapper; + + @SneakyThrows + @Override + public Map convert(String source) { + return objectMapper.readValue(source, Map.class); + } + }; + } + + private JavaTimeModule javaTimeModule() { JavaTimeModule javaTimeModule = new JavaTimeModule(); - //LocalDataTime + //LocalDateTime javaTimeModule.addSerializer(LocalDateTime.class, new JsonSerializer<>() { @Override public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { @@ -77,24 +100,27 @@ public class SerializeConfig { } }); - om.registerModule(javaTimeModule); - return om; + return javaTimeModule; } - @SuppressWarnings({"Convert2Diamond", "NullableProblems", "rawtypes"}) - @Bean - public Converter mapConverter() { - return new Converter() { - - @Autowired - private ObjectMapper objectMapper; - - @SneakyThrows + //TODO: Redis可能改成tostringSerializer + private SimpleModule customClassModule() { + SimpleModule customClassModule = new SimpleModule("CustomClassModule"); + customClassModule.addSerializer(IPAddress.class, new JsonSerializer<>() { @Override - public Map convert(String source) { - return objectMapper.readValue(source, Map.class); + public void serialize(IPAddress value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + if (value != null) { + gen.writeString(value.toString()); + } } - }; + }); + customClassModule.addDeserializer(IPAddress.class, new JsonDeserializer<>() { + @Override + public IPAddress deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + return IPAddress.of(Long.decode(p.getValueAsString())); + } + }); + return customClassModule; } } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/WebConfig.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/WebConfig.java index 684bc24..4a07b0e 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/WebConfig.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/WebConfig.java @@ -32,6 +32,7 @@ public class WebConfig implements WebMvcConfigurer { .excludePathPatterns("/hello", "/error") //测试 .excludePathPatterns("/staff/login") //登录 .excludePathPatterns("/swagger-ui.html", "/swagger-resources/**", "/swagger-ui/**", - "/v2/**", "/v3/**", "/webjars/**", "/doc.html"); //swagger + "/v2/**", "/v3/**", "/webjars/**", "/doc.html") //swagger + .excludePathPatterns("/favicon.ico", "/public/**"); //静态资源 } } \ No newline at end of file diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/AnnouncementController.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/AnnouncementController.java index 35b1137..e2ff8ff 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/AnnouncementController.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/AnnouncementController.java @@ -46,7 +46,7 @@ public class AnnouncementController { if (projectGroupService.getProjectAccessLevel(token, projectId) == 0) { throw new ForbiddenException(IProjectGroupService.UNABLE_TO_ACCESS_PROJECT); } - return ResponseMap.ofSuccess(announcementService.getAnnouncementById(announcementId)); + return ResponseMap.ofSuccess(announcementService.getAnnouncementById(projectId, announcementId)); } @SneakyThrows diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/StaffController.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/StaffController.java index a111f9a..6571d4a 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/StaffController.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/StaffController.java @@ -2,7 +2,6 @@ package cn.edu.hfut.rmdjzz.projectmanagement.controller; import cn.edu.hfut.rmdjzz.projectmanagement.entity.Staff; import cn.edu.hfut.rmdjzz.projectmanagement.exception.BadRequestException; -import cn.edu.hfut.rmdjzz.projectmanagement.exception.ForbiddenException; import cn.edu.hfut.rmdjzz.projectmanagement.exception.TokenException; import cn.edu.hfut.rmdjzz.projectmanagement.service.IStaffService; import cn.edu.hfut.rmdjzz.projectmanagement.utils.FileUtils; @@ -12,12 +11,12 @@ import cn.edu.hfut.rmdjzz.projectmanagement.utils.http.ResponseMap; import io.swagger.v3.oas.annotations.Parameter; import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.util.DigestUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.util.Objects; /** @@ -72,7 +71,8 @@ public class StaffController { return ResponseMap.ofSuccess("成功导入" + successCount + "条数据"); } - @SneakyThrows + //取消功能 + /*@SneakyThrows @GetMapping("/import/template") public void downloadTemplate( @RequestHeader(TokenUtils.HEADER_TOKEN) String token, @@ -81,9 +81,18 @@ public class StaffController { if (TokenUtils.getStaffGlobalLevel(token) > 2) { throw new ForbiddenException(ForbiddenException.UNABLE_TO_OPERATE); } - if (FileUtils.downloadResource("static/账户导入模板.xlsx", response)) { + if (FileUtils.downloadResource("static/public/账户导入模板.xlsx", response)) { return; } throw new BadRequestException(BadRequestException.OPERATE_FAILED); + }*/ + + @SneakyThrows + @GetMapping("/import/template") + @ResponseStatus(HttpStatus.SEE_OTHER) + public ResponseMap downloadTemplate() { + return ResponseMap.of(HttpStatus.SEE_OTHER.value(), + HttpStatus.SEE_OTHER.getReasonPhrase()) + .put("URI","/public/账户导入模板.xlsx"); } } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/entity/dto/AnnouncementDTO.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/entity/dto/AnnouncementDTO.java index 2f1e987..d03a726 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/entity/dto/AnnouncementDTO.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/entity/dto/AnnouncementDTO.java @@ -13,6 +13,7 @@ public class AnnouncementDTO { private Long announcementId; private Integer announcementPublisherId; private String announcementPublisherName; + private Integer announcementPublisherAccessLevel; private LocalDateTime announcementPublishTime; private String announcementTitle; private String announcementContent; diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/interceptor/CorsInterceptor.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/interceptor/CorsInterceptor.java index 69a98df..b16b045 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/interceptor/CorsInterceptor.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/interceptor/CorsInterceptor.java @@ -7,6 +7,8 @@ import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.util.Enumeration; +import java.util.Iterator; /** * @author 张韬 @@ -20,7 +22,15 @@ public class CorsInterceptor implements HandlerInterceptor { response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "*"); response.setHeader("Access-Control-Allow-Headers", "Content-Type,Token"); - response.setHeader("Access-Control-Allow-Credentials","false"); + response.setHeader("Access-Control-Allow-Credentials", "false"); + + //test + Enumeration headerNames = request.getHeaderNames(); + Iterator nameIter = headerNames.asIterator(); + while (nameIter.hasNext()) { + System.out.println(nameIter.next()); + } + // 如果是OPTIONS则结束请求 if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) { response.setStatus(HttpStatus.OK.value()); diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/mapper/AnnouncementMapper.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/mapper/AnnouncementMapper.java index 5d1ddae..3b85cb3 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/mapper/AnnouncementMapper.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/mapper/AnnouncementMapper.java @@ -14,5 +14,5 @@ import java.util.List; public interface AnnouncementMapper extends BaseMapper { List selectAnnouncementList(@Param("projectId") Integer projectId); - AnnouncementDTO selectAnnouncementById(@Param("announcementId") Long announcementId); + AnnouncementDTO selectAnnouncementById(@Param("projectId") Integer projectId, @Param("announcementId") Long announcementId); } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/IAnnouncementService.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/IAnnouncementService.java index 5e89ff1..1e5a6d1 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/IAnnouncementService.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/IAnnouncementService.java @@ -16,7 +16,7 @@ public interface IAnnouncementService extends IService { List getAnnouncementList(Integer projectId); - AnnouncementDTO getAnnouncementById(Long announcementId); + AnnouncementDTO getAnnouncementById(Integer projectId, Long announcementId); Boolean updateAnnouncement(String token, Integer projectId, Announcement announcement) throws ForbiddenException, BadRequestException; diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/IProjectGroupService.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/IProjectGroupService.java index 1f940da..2fb73bd 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/IProjectGroupService.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/IProjectGroupService.java @@ -28,7 +28,7 @@ public interface IProjectGroupService extends IService { Boolean removeMember(String token, Integer projectId, Integer targetId) throws ForbiddenException, BadRequestException; - Boolean updateStaffPositions(String token, Integer projectId, Integer targetId, String positions) throws ForbiddenException; + Boolean updateStaffPositions(String token, Integer projectId, Integer targetId, String positions) throws ForbiddenException, BadRequestException; /** * @return 如果不存在就返回0,否则返回AccessLevel;对于全局权限为1的用户,直接返回1 diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/AnnouncementServiceImpl.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/AnnouncementServiceImpl.java index 5a6eecc..0cd8e11 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/AnnouncementServiceImpl.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/AnnouncementServiceImpl.java @@ -31,8 +31,8 @@ public class AnnouncementServiceImpl extends ServiceImpllambdaQuery() - .select(Announcement::getProjectId) - .select(Announcement::getAnnouncementPublisherId) + .select(Announcement::getProjectId, Announcement::getAnnouncementPublisherId) .eq(Announcement::getAnnouncementId, announcementId) ); if (!Objects.equals(projectId, rawAnnouncement.getProjectId())) { diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/ProjectGroupServiceImpl.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/ProjectGroupServiceImpl.java index 0f8e546..6a6b5e4 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/ProjectGroupServiceImpl.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/ProjectGroupServiceImpl.java @@ -44,6 +44,9 @@ public class ProjectGroupServiceImpl extends ServiceImpl implements @SuppressWarnings("ConstantConditions") @Override public Map login(String requestIpAddress, String staffUsername, String password) throws BadRequestException, ForbiddenException { - if (Boolean.FALSE.equals(redisTemplate.hasKey(requestIpAddress))) { - redisTemplate.opsForValue().set(requestIpAddress, 0, LOGIN_TRY_COUNT_TIMEOUT, TimeUnit.MINUTES); + String requestIpAddressHex = IPAddress.of(requestIpAddress).toString(); + if (Boolean.FALSE.equals(redisTemplate.hasKey(requestIpAddressHex))) { + redisTemplate.opsForValue().set(requestIpAddressHex, 0, LOGIN_TRY_COUNT_TIMEOUT, TimeUnit.MINUTES); } - int loginCount = (int) redisTemplate.opsForValue().get(requestIpAddress); + int loginCount = (int) redisTemplate.opsForValue().get(requestIpAddressHex); if (loginCount >= LOGIN_MAX_TRY_COUNT) { throw new ForbiddenException(String.format("还需要等待%s才能登录" - , TimeUtils.secondsFormat(redisTemplate.getExpire(requestIpAddress)))); + , TimeUtils.secondsFormat(redisTemplate.getExpire(requestIpAddressHex)))); } if (staffUsername == null || staffUsername.strip().length() == 0) //throw new BadRequestException("用户名为空"); - throwLoginException(requestIpAddress, loginCount); + throw loginException(requestIpAddressHex, loginCount); if (!staffUsername.equals(staffUsername.replaceAll("[^a-zA-Z0-9]", ""))) //throw new BadRequestException("用户名格式错误"); - throwLoginException(requestIpAddress, loginCount); + throw loginException(requestIpAddressHex, loginCount); if (password == null || password.trim().length() != 32) //throw new BadRequestException("密码格式错误"); - throwLoginException(requestIpAddress, loginCount); + throw loginException(requestIpAddressHex, loginCount); Staff staff = getOne(Wrappers.lambdaQuery().eq(Staff::getStaffUsername, staffUsername)); if (staff == null) //throw new BadRequestException(STAFF_DOES_NOT_EXIST); - throwLoginException(requestIpAddress, loginCount); + throw loginException(requestIpAddressHex, loginCount); password = DigestUtils.md5DigestAsHex((password + staff.getStaffSalt()).getBytes()); if (!staff.getStaffPassword().equals(password)) { - throwLoginException(requestIpAddress, loginCount); + throw loginException(requestIpAddressHex, loginCount); } String token = TokenUtils.getToken(staff.getStaffUsername(), staff.getStaffId(), staff.getStaffGlobalLevel(), tokenDuration); redisTemplate.opsForValue().set( @@ -80,15 +82,16 @@ public class StaffServiceImpl extends ServiceImpl implements token, Objects.requireNonNull(TokenUtils.getDuration(token)), TimeUnit.SECONDS ); + redisTemplate.delete(requestIpAddressHex); return new MapBuilder() .put(TokenUtils.HEADER_TOKEN, token) .putAll(BeanUtils.beanToMap(staff, false)) .build(); } - private void throwLoginException(String requestIpAddress, int loginCount) throws BadRequestException { + private BadRequestException loginException(String requestIpAddress, int loginCount) { redisTemplate.opsForValue().set(requestIpAddress, ++loginCount, LOGIN_TRY_COUNT_TIMEOUT, TimeUnit.MINUTES); - throw new BadRequestException(String.format("登录失败,%d分钟内还有%d次登录机会", LOGIN_TRY_COUNT_TIMEOUT, LOGIN_MAX_TRY_COUNT - loginCount)); + return new BadRequestException(String.format("登录失败,%d分钟内还有%d次登录机会", LOGIN_TRY_COUNT_TIMEOUT, LOGIN_MAX_TRY_COUNT - loginCount)); } @Override diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/IPAddress.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/IPAddress.java new file mode 100644 index 0000000..ee6b965 --- /dev/null +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/IPAddress.java @@ -0,0 +1,43 @@ +package cn.edu.hfut.rmdjzz.projectmanagement.utils.http; + +import lombok.AllArgsConstructor; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * @author 佘语殊 + * @since 2022/7/12 17:12 + */ +@AllArgsConstructor(staticName = "of") +public class IPAddress { + private long ipHex; + + public static IPAddress of(String ip) { + long ipHex = 0; + String[] split = ip.split("\\."); + for (String s : split) { + ipHex = (ipHex << 8) + Integer.parseInt(s); + } + return new IPAddress(ipHex); + } + + public String getIpString() { + List ipSectionList = new LinkedList<>(); + long tempHex = ipHex; + int section; + while (tempHex > 0) { + section = (int) (tempHex & 0xFF); + ipSectionList.add(String.valueOf(section)); + tempHex >>= 8; + } + Collections.reverse(ipSectionList); + return String.join(".", ipSectionList); + } + + @Override + public String toString() { + return "#" + Long.toHexString(ipHex); + } +} diff --git a/src/main/resources/mapper/AnnouncementMapper.xml b/src/main/resources/mapper/AnnouncementMapper.xml index b41c211..f220fa9 100644 --- a/src/main/resources/mapper/AnnouncementMapper.xml +++ b/src/main/resources/mapper/AnnouncementMapper.xml @@ -12,7 +12,7 @@ announcement_publish_time, announcement_title FROM announcement - JOIN (SELECT staff_id, staff_fullname FROM staff) s + JOIN (SELECT staff_id, staff_fullname FROM staff) AS s ON staff_id = announcement.announcement_publisher_id WHERE is_deleted = 0 AND project_id = #{projectId} @@ -21,13 +21,18 @@ diff --git a/src/main/resources/static/账户导入模板.xlsx b/src/main/resources/static/public/账户导入模板.xlsx similarity index 100% rename from src/main/resources/static/账户导入模板.xlsx rename to src/main/resources/static/public/账户导入模板.xlsx diff --git a/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/RedisTests.java b/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/RedisTests.java index 7b3db89..b460466 100644 --- a/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/RedisTests.java +++ b/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/RedisTests.java @@ -1,9 +1,11 @@ package cn.edu.hfut.rmdjzz.projectmanagement; +import cn.edu.hfut.rmdjzz.projectmanagement.utils.http.IPAddress; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; import java.time.LocalDateTime; @@ -15,14 +17,21 @@ import java.time.LocalDateTime; public class RedisTests { @Autowired private RedisTemplate redisTemplate; + @Autowired + private StringRedisTemplate stringRedisTemplate; @Test void test() { - System.out.println(redisTemplate.opsForValue().get("l1")); + System.out.println(redisTemplate.opsForValue().get(0x15A2)); } @Test void testValue() { redisTemplate.opsForValue().set("time", LocalDateTime.now()); } + + @Test + void stringTest() { + stringRedisTemplate.opsForValue().set(IPAddress.of("192.168.0.1").toString(),String.valueOf(2)); + } } diff --git a/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/SerializeTests.java b/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/SerializeTests.java index 4c0fbd7..75b45ef 100644 --- a/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/SerializeTests.java +++ b/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/SerializeTests.java @@ -1,12 +1,12 @@ package cn.edu.hfut.rmdjzz.projectmanagement; +import cn.edu.hfut.rmdjzz.projectmanagement.utils.http.IPAddress; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import java.time.LocalDate; import java.time.LocalDateTime; /** @@ -24,4 +24,13 @@ public class SerializeTests { public void serializeTime() { System.out.println(objectMapper.readValue("1657166400", LocalDateTime.class)); } + + @SneakyThrows + @Test + public void serializeIPTest() { + IPAddress ip = IPAddress.of("192.108.1.1"); + System.out.println(objectMapper.writeValueAsString(ip)); + System.out.println(ip.getIpString()); + System.out.println(objectMapper.readValue("0xc06c0101",IPAddress.class)); + } }