jersey获取inputstream body为空问题

在处理一个第三方加密回调时,需要读取body的byte内容,用了springMVC后,字节数不对,后因大部分API使用jersey, 故决定用jersey, 但jersey中想要获取request的body时遇到一直无法获取的问题

取body的多种方式

1
2
3
4
5
6
@Post //直接注入body(也可以是String)  
public void doSomething(byte[] body)
@Post //直接注入inputStream后读取
public void doSomething(InputStream inputStream)
@Post //从request读inputStream再读取
public void doSomething(@Context HttpServletRequest request)

结果试了各种方式,要么读不到,要么报下面这些错。。。

Only resource methods using @FormParam will work as expected
getInputStream() has already been called for this request
The resource configuration is not modifiable in this context. 

跟据经验InputStream只能被取一次,在配置对的情况下,还取不到大概都是这个问题,且报错也有该提示,然后主要方向就是这个了,推测是某个filter先用了inputStream,一看Springboot 自动注入了8个。。。表示想一个个找会很痛苦了

最后找到了stackoverflow的一个类似问题,试了下,成功了,特记录一下

StackOverflow上的问题:
inputstream-giving-null-data-in-messagebodyreader-jersey

上面的不能直接用,提供下我写的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Configuration  
public class FilterConfig {
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new MyHiddenHttpMethodFilter();
}

class MyHiddenHttpMethodFilter extends HiddenHttpMethodFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
if ("POST".equals(request.getMethod())
&& MediaType.APPLICATION_FORM_URLENCODED.equals(request.getContentType())){
//Skip this filter and call the next filter in the chain.
filterChain.doFilter(request, response);
} else {
//Continue with processing this filter.
super.doFilterInternal(request, response, filterChain);
}
}
}
}

配置好后直接就可以各种花式读到body了。。。

后记:好奇为什么springboot会配这样一个HiddenHttpMethodFilter
查了下,原来是为了将form表单扩展,使之支持DELETE PUT。
说是在这个filter里将原始POST替换为form表单中的对应的,再传到后面处理。
具体没看了

Hello World

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new -p hello-word.md "Hello Word"

More info: Writing

Run server

1
$ hexo server -p 1824

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

Test Java Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.kandebiji.ts.wiremock;

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import com.github.tomakehurst.wiremock.junit.WireMockRule;

public class WeatherApplicationTest {

@Rule
public WireMockRule forecastIoService = new WireMockRule(wireMockConfig().port(8089).httpsPort(8443));

@Test
public void exampleTest() throws InterruptedException {
stubFor(get(urlEqualTo("/.my/resource"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "text/xml")
.withBody("<response>Saddaontent</response>")));
Thread.sleep(300000L);
}
}

恭喜发财

Kafka安装-Windows与Linux环境

目标: 安装出一个可供学习测试使用的kafka环境

下载kafka

最新的有两个版本,由不同的Scala版本编译
Scala 2.11 - kafka_2.11-0.11.0.1.tgz (asc, md5)
Scala 2.12 - kafka_2.12-0.11.0.1.tgz (asc, md5)

除非要直接使用Scala开发,那就用对应版本,否则推荐是使用2.11版本

官网地址: https://www.apache.org/dyn/closer.cgi?path=/kafka/0.11.0.1/kafka_2.11-0.11.0.1.tgz

最终获取到一个kafka_2.11-0.11.0.1.tgz文件

Windows 环境安装及命令行测试

Linux 环境安装及命令行测试

安装

1
2
tar -xzf kafka_2.11-0.11.0.1.tgz
cd kafka_2.11-0.11.0.1

启动 zookeeper

启动 kafka server

Docker image of Spring boot

目标: 将一个可执行的jar打包成docker image

源文件总共3个 Dockerfile, SampleController.java, pom.xml

  • src
    • main
      • docker
        • Dockerfile
      • java
        • com.kandebiji.ts.docker.hello
          • SampleController.java
  • pom.xml

一. 创建hello world

用spring boot新建一个hello world的web程序

File: pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kandebiji.ts</groupId>
<artifactId>docker-war</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>docker-war</name>
<url>http://maven.apache.org</url>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

</project>

File: SampleController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.kandebiji.ts.docker.hello;

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.annotation.ApplicationScope;

@Controller
@EnableAutoConfiguration
public class SampleController {

@RequestMapping("/")
@ResponseBody
String home() {
return "Hello World!";
}

public static void main(String[] args) throws Exception {
SpringApplication.run(SampleController.class, args);
}
}

Run:
右键运行, 然后浏览器访问 http://localhost:8080 , 看到 Hello World! 就成功了。

二. 打包可执行jar

使用spring boot plugin将web程序打包成可执行的jar

File: pom.xml 增加内容

1
2
3
4
5
6
7
8
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

Run:
mvn package
在 target 下面可以看到

  • docker-war-1.0-SNAPSHOT.jar
  • docker-war-1.0-SNAPSHOT.jar.original

然后 java -jar docker-war-1.0-SNAPSHOT.jar 启动
浏览器访问 http://localhost:8080 , 看到 Hello World! 就成功了。

三. 打包出images

增加docker maven plugin,在有maven, docker环境的linux机器上进行打包

File: pom.xml 增加内容

1
2
3
<properties>
<docker-plugin>1.3.1</docker-plugin>
</properties>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.14</version>
<configuration>
<imageName>ts/${project.artifactId}</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>

docker-maven里指定了Dockerfile的文件位置:src/main/docker
同时也将可执行的jar包放在plugin的根路径

File: Dockerfile

1
2
3
4
5
6
7
FROM java:8
VOLUME /tmp
ADD docker-war-1.0-SNAPSHOT.jar app.jar
RUN sh -c 'touch /app.jar'
EXPOSE 8080
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar"

Dockerfile的主要含义:
基于java 8
增加根路径下的docker-war-1.0-SNAPSHOT.jar为app.jar
暴露 8080 端口
接收JAVA_OPTS的环境变量

Run:
mvn package
mvn docker:build
docker images 可以看到ts/docker-war
docker run –name tsdw -d -p 8080:8080 ts/docker-war
浏览器访问 http://localhost:8080 , 看到 Hello World! 就成功了。