IDEA空包粘黏问题
创建好目录以后会发现idea自动将空包合并在一起了,而且点击设置里面也没有Compact Middle Package
Compact Middle Package如果不在设置的主面板上,则点击Tree Appearance,会发现Compact Middle Package在Tree Appearance里面,然后去掉Compact Middle Package前面的勾选即可展开包
IDEA中解决控制台乱码问题
IDEA控制台输出乱码解决办法 - 知乎
在使用Filter的时候只重写doFilter方法带来的问题
在使用过滤器的时候,xml文件配置都没有问题:
但访问页面的时候(不管是静态的还是动态的),都会报404错误。原因就是因为没有重写Filter里面的init方法。在 web 工程启动的时候执行构造器方法和init 初始化方法 ,如果没有重写过滤器的初始化方法,那么就没法使用过滤器,而xml文件里面有配置了过滤器的信息,所以服务器在执行的时候,根据xml的配置他找MyFilter这个类,发现这个类没有初始化,根本就没有,所以就会报404。
在mapper.xml文件中插入对象的SQL语句遇到的问题
当我们需要在mapper.xml文件中插入对象时,我们可以像下面这样写:
<insert id="addStudent" parameterType="com.example.demo.entity.Student">
insert into student (name,age,school,gender) values(#{name},#{age},#{school},#{gender});
</insert>
上面的parameterType只是使用指定参数类型的,可有可无,没有也不会出错,但是协商以后含义更加明确。
将对象存储到Redis遇到的问题
再将封装好的对象转化为json字符串存储到redis中时,遇到了下面问题
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private ObjectMapper objectMapper;
//登录操作
@RequestMapping("/login")
public Object login(HttpServletRequest req,String username,String password) throws IOException {
if(StringUtils.hasLength(username) && StringUtils.hasLength(password)){
User user = userService.findUserByName(username);
if(user!=null && user.getPassword().equals(password)){
//将登录信息存储到session中
HttpSession session = req.getSession(true);
session.setAttribute("username",username);
//将session持久化到redis中
String sessionStr = objectMapper.writeValueAsString(session);
stringRedisTemplate.opsForValue().set("session",sessionStr);
return 1;
}
}
return -1;
}
}
[org.apache.ibatis.session.defaults.DefaultSqlSession@3e9c5527]
2023-06-11T20:38:19.353+08:00 WARN 21124 --- [nio-8080-exec-5] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.util.Collections$3 and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.apache.catalina.session.StandardSessionFacade["servletContext"]->org.apache.catalina.core.ApplicationContextFacade["initParameterNames"])]
警告消息指出在序列化对象时发生了问题,无法找到适当的序列化器。
警告消息的原因是将某个对象序列化为 JSON 格式返回给客户端,但在序列化过程中发现了一个问题。具体来说,异常消息中提到的是找不到合适的序列化器,因为被序列化的对象是 `java.util.Collections$3` 类型,且没有发现属性来创建 `BeanSerializer`。
解决此问题的方法是禁用 Jackson 库在遇到空对象时抛出异常。可以通过在 Spring Boot 的配置文件(如 `application.yml` 或 `application.properties`)中添加以下配置来实现:
spring:
jackson:
serialization:
fail-on-empty-beans: false
或者在 Java 配置类中使用以下代码:
@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizeJackson() {
return builder -> builder.failOnEmptyBeans(false);
}
}
通过以上配置,可以禁用 Jackson 序列化库在遇到空对象时抛出异常,从而避免警告消息的出现。
请注意,该警告消息可能不会对应用程序的功能造成实质性的影响,因为它只是提醒在序列化过程中发生了一些问题。然而,如果你的应用程序依赖于正确的序列化行为,并且你希望避免警告消息的出现,可以采取上述的配置方法来解决问题。
引入工具类的时候遇到的问题
在引入别人的工具类的时候,因为自己的项目java版本和他的不一样,导致JVM在加载类的时候报了下面这样的错误:
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
解释一下上面的错误:Java运行时无法在运行时找到特定类时发生,即使在编译时存在该类
出现上面错误的原因:
这个问题通常出现在使用Java 9及更高版本时。从Java 9开始,默认情况下,Java开发工具包(JDK)中移除了包括`DatatypeConverter`在内的`javax.xml.bind`包。它是Java API for XML Binding(JAXB)的一部分,不再包含在标准JDK中。
要解决此错误,您有几个选项:
1. 如果您使用的是Java 8或更早版本:确保您使用的是正确的Java版本,并仔细检查类路径,确保它包括所需的库或包含所需类的JAR文件。
2. 如果您使用的是Java 9或更高版本:您需要显式向项目添加JAXB API库,因为它不再默认包含在其中。您可以从Maven中央仓库或其他仓库获取JAXB API库。要添加该库,请按照以下步骤操作:
- 对于Maven用户:将以下依赖项添加到您的`pom.xml`文件中:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
- 对于Gradle用户:将以下依赖项添加到您的`build.gradle`文件中:
implementation 'javax.xml.bind:jaxb-api:2.3.1'
确保根据您的需求调整版本号。
3. 如果您使用的是Java 11或更高版本:在Java 11中,完全从JDK中删除了`javax.xml.bind`包。相反,它作为一个名为`java.xml.bind`的独立模块可用。您可以通过在运行Java应用程序时添加以下命令行参数来添加该模块:
--add-modules java.xml.bind
如果您使用的是IntelliJ或Eclipse等IDE,您可能需要在项目设置或VM参数中配置该模块。
通过遵循其中一种方法,您应该能够解决与`javax.xml.bind.DatatypeConverter`相关的`NoClassDefFoundError`。
在window中启动kafka时遇到的问题
[2023-06-17 17:37:33,486] ERROR Uncaught exception in scheduled task 'kafka-log-retention' (kafka.utils.KafkaScheduler)
org.apache.kafka.common.errors.KafkaStorageException: Error while deleting segments for follow-0 in dir E:\work\data\kafka-logs
Caused by: java.nio.file.FileSystemException: E:\work\data\kafka-logs\follow-0\00000000000000000000.timeindex -> E:\work\data\kafka-logs\follow-0\00000000000000000000.timeindex.deleted: 另一个程序正在使用此文件,进程无法访问。
ERROR Shutdown broker because all log dirs in E:\work\data\kafka-logs have failed (kafka.log.LogManager)
出现上面问题的原因是因为
1. 日志目录不存在:请检查指定的日志目录是否存在。如果指定的日志目录不存在或路径错误,Kafka无法写入或读取日志文件,从而导致失败。确保指定的日志目录存在,并且Kafka broker具有正确的读写权限。
2. 文件系统错误:如果指定的日志目录所在的文件系统发生错误,如磁盘故障、文件系统损坏等,Kafka无法读取或写入日志文件,导致失败。请检查文件系统的健康状况,并确保文件系统没有发生任何故障。
3. 存储空间不足:如果指定的日志目录的存储空间已满,Kafka无法继续写入日志文件,导致失败。请检查指定的日志目录的磁盘空间,并确保有足够的可用空间供Kafka使用。
4. 文件权限问题:Kafka broker需要具有适当的文件权限才能读取和写入日志文件。请确保Kafka broker具有足够的权限来访问指定的日志目录及其内部的文件。
但最直接的办法就是将Kafka brokers的日志文件和zookeeper的数据和日志文件,然后重启。
在使用swagger时遇到的问题
在使用swagger时,引入依赖和编写配置类以后,访问localhost:xxxx:/swagger-ui.html#/时,弹出页面:
Unable to infer base url. This is common when using dynamic servlet registration or when the API is behind an API Gateway. The base url is the root of where all the swagger resources are served. For e.g. if the api is available at http://example.org/api/v2/api-docs then the base url is http://example.org/api/. Please enter the location manually:
网上说了很多原因,后来我降低了springBoot的版本为2.2.1.RELEASE以后就可以了,真的坑爹。
最主要的还是要检查你的maven里面的Dependencies里面有没有相关的依赖,还有就是SpringBoot版本不能过高。
如果出现了上面的情况,你最好在你的swagger配置的同级包下面写一个测试类,看看该类能不能正常运行。如果不能正常运行,那么向下面这样做:
首先在Maven里面的Lifecycle里面点击clean,然后在install一下,如果install过程中出现了某某jar包无法导入的情况,那么在点击Reload All Maven Projects,在运行一下你的测试类。
debug的时候,断点只有第一次能够进入,第二次去不能进入
IDEA的debug模式下断点只走一次,第二次断点都失效,解决办法_liang_336的博客-CSDN博客
在启动微服务时,报某个路径下面找不到某个类的问题
nested exception is java.io.FileNotFoundException: class path resource XXX.class cannot be opened because it does not exist
报这样的问题一般是由缓存引起的,只需要清理缓存然后重新构建项目即可,别忘了在maven里面install
在使用openfeign时遇到Request method 'POST' not supported问题
在远程调用时我最开始使用的是GetMapping,然后启动程序在服务端就报了Request method 'POST' not supported异常,然后我尝试在参数前面加上@RequestParam注解
@FeignClient(value = ServiceNameConstants.TRANSFORM_SERVICE)
public interface ResolveBidResponseService {
@GetMapping("/response")
BidResponse resolve(@RequestParam("list") List<String> list);
}
@Slf4j
@RequiredArgsConstructor
@RestController
public class ResolveBidController {
@GetMapping("/response")
public BidResponse resolve(@RequestParam("list") List<String> list) {
BidResponse result = list.stream()
.map(item -> JSONObject.parseObject(item,BidResponse.class))
.filter(bidResponse -> bidResponse.getAds() != null)
.findFirst()
.orElse(null);
return result;
}
}
修改成上面以后不再报Request method 'POST' not supported异常,但是由于我的业务需求需要将json字符串解析为json对象,在解析的过程中报了如下错误。后面经过思考,对于json类的字符串还是放在请求body里面传递为好,因为通过拼接url的方式传递在拼接过程中json字符串里面又嵌套了json字符串,那么就会对解析工作带来不必要的异常。
10:25:02.166 [http-nio-9231-exec-5] ERROR c.z.d.c.s.h.GlobalExceptionHandler - [handleException,51] - not match : - , info : pos 43, line 1, column 44{"bidid":"b1405b10ed6a4fb9bdfb0c6ba5e9d07f"
com.alibaba.fastjson.JSONException: not match : - , info : pos 43, line 1, column 44{"bidid":"b1405b10ed6a4fb9bdfb0c6ba5e9d07f"
最终我将请求方式改为了PostMapping,并在方法参数前面加上了@RequestBody注解,一定要加上该注解,因为需要告诉Feign如何将请求数据映射到参数上。修改后的代码如下
@FeignClient(value = ServiceNameConstants.TRANSFORM_SERVICE)
public interface ResolveBidResponseService {
@PostMapping("/response")
BidResponse resolve(@RequestBody List<String> list);
}
@Slf4j
@RequiredArgsConstructor
@RestController
public class ResolveBidController {
@PostMapping("/response")
public BidResponse resolve(@RequestBody List<String> list) {
BidResponse result = list.stream()
.map(item -> JSONObject.parseObject(item,BidResponse.class))
.filter(bidResponse -> bidResponse.getAds() != null)
.findFirst()
.orElse(null);
return result;
}
}
springboot依赖注入的问题
我们项目中需要个根据下游的渠道号的接口地址来拉取他们的数据到我们的数据库中,所以需要将这些下游的渠道号和接口地址配置到bootstrap.yml文件中,如下
enterprises:
importResource:
- channel: judian_dsp
url: http://192.168.37.1:9203/callback/apk/pull
- channel: baishuo_dsp
url: http://192.168.37.1:9204/callback/apk/pull
根据配置信息我们需要定义一个对象ImportResource和一个配置解析类EnterpriseProperties。最开始我是像下面这样写的
@Data
@Component
@ConfigurationProperties(prefix = "enterprises")
public class ImportResource {
private static String url;
private static String channel;
public static String getUrl() {
return url;
}
public static void setUrl(String url) {
ImportResource.url = url;
}
public static String getChannel() {
return channel;
}
public static void setChannel(String channel) {
ImportResource.channel = channel;
}
}
@Component
public class EnterprisesProperties {
@Autowired
private List<ImportResource> importResources;
public List<ImportResource> getImportResources() {
return importResources;
}
public void setImportResources(List<ImportResource> importResources) {
this.importResources = importResources;
}
}
System.out.println(enterprisesProperties.getImportResources().get(0).getChannel());
System.out.println(enterprisesProperties.getImportResources().get(0).getUrl());
可是这种写法在EnterprisesProperties的getImportResources方法中得到的ImportResource对象始终为null
后面我该了一种写法如下
@Component
@ConfigurationProperties(prefix = "enterprises")
public class EnterprisesProperties {
private List<ImportResource> importResource;
public List<ImportResource> getImportResource() {
return importResource;
}
public void setImportResource(List<ImportResource> importResource) {
this.importResource = importResource;
}
public static class ImportResource {
private String url;
private String channel;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getChannel() {
return channel;
}
public void setChannel(String channel) {
this.channel = channel;
}
}
}
这种写法getImportResources就能获取到配置中的数据了
解释一下我的想法,第二种写法ImportResource属于静态内部类,当主类来调用EnterprisesProperties这个实例的时候ImportResource对象就会被加载和初始化,所以getImportResource方法就能够获取到值。而第一种方式ImportResource是另外一个类,当主类调用EnterprisesProperties实例的时候,EnterprisesProperties才去把ImportResource对象注入进来,这是注入进来的ImportResource就是一个没有被赋值的对象而已。
还有在使用第二种方法的时候有重要的细节:
EnterprisesProperties类中get方法的名字必须是getImportResource,换其他的名字不行,因为必须和配置类中的对象名字(importResource)一样,不然就获取不到对象的结果,只能获取到null