Skip to content

Commit

Permalink
完成jsonp支持,只需要提供参数即可
Browse files Browse the repository at this point in the history
  • Loading branch information
inkroom committed Aug 30, 2019
1 parent 74e7632 commit 3eb6e25
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 7 deletions.
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@

## SpringBoot 学习项目

#### 已实现功能
- 基于redis的分布式锁
- 基于kryo序列化的分布式session
> 引入devtools将会导致无法正常使用

#### 待学习项目
- [x] 基于redis的分布式锁
- [x] 基于kryo序列化的分布式session
> 引入devtools将会导致无法正常使用
- [x] jsonp跨域

- [ ] mysql读写分离
- [ ] mysql分库分表
Expand All @@ -20,4 +18,17 @@
- [ ] 分布式事务
- [ ] zookeeper相关应用

- [ ] mysql索引使用
- [ ] mysql索引使用
- [ ] mysql行锁表锁等

- [ ] 消息中间件消息有序性

- [ ] jstack定时地打印调用栈
- [ ] redis集群的使用
- [ ] 订单等有效期数据实现

- [ ] 服务监控


- [ ] oauth认证
- [ ] jwt登录
47 changes: 47 additions & 0 deletions src/main/java/com/inkbox/boot/demo/config/MvcConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.inkbox.boot.demo.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.util.StreamUtils;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;

/**
* 解决返回字符串时再次被json转换,最后多出双引号问题
*/
@Configuration
public class MvcConfig implements WebMvcConfigurer {

private Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private MappingJackson2HttpMessageConverter converter;

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// MappingJackson2HttpMessageConverter converter = mappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(new LinkedList<MediaType>() {{
add(MediaType.TEXT_HTML);
add(MediaType.APPLICATION_JSON_UTF8);
}});
converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
converters.add(converter);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

import com.inkbox.boot.demo.dao.UserDao;
import com.inkbox.boot.demo.dos.UserDo;
import com.inkbox.boot.demo.dto.Position;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
Expand All @@ -30,6 +33,7 @@ public String index(UserDo userDo) {
}

@GetMapping("show")
@CrossOrigin
public String show() {


Expand All @@ -43,5 +47,9 @@ public String show() {

}

@RequestMapping("dto")
public Position dto() {
return new Position(239, 43);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.inkbox.boot.demo.converter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.Charset;

@Component
public class Jackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {

private Logger logger = LoggerFactory.getLogger(getClass());

@Override
protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
if (object instanceof String) {
//绕开实际上返回的String类型,不序列化
Charset charset = this.getDefaultCharset();
StreamUtils.copy((String) object, charset, outputMessage.getBody());
} else {
super.writeInternal(object, type, outputMessage);
}
}
}
5 changes: 5 additions & 0 deletions src/main/java/com/inkbox/boot/demo/dao/UserDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface UserDao extends JpaRepository<UserDo,Long> {


List<UserDo> findAllByName(String name);
}
32 changes: 32 additions & 0 deletions src/main/java/com/inkbox/boot/demo/dto/Position.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.inkbox.boot.demo.dto;


public class Position {

private int x;
private int y;

public Position() {
}

public Position(int x, int y) {
this.x = x;
this.y = y;
}

public int getX() {
return x;
}

public void setX(int x) {
this.x = x;
}

public int getY() {
return y;
}

public void setY(int y) {
this.y = y;
}
}
86 changes: 86 additions & 0 deletions src/main/java/com/inkbox/boot/demo/handler/JsonpAdvice.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.inkbox.boot.demo.handler;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.inkbox.boot.demo.controllers.IndexController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;

/**
* 处理controller返回值,对于有callback值的使用jsonp格式,其余不处理
*/
@RestControllerAdvice(basePackageClasses = IndexController.class)
public class JsonpAdvice implements ResponseBodyAdvice {

private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ObjectMapper mapper;

//jquery默认是callback,其余jsonp库可能不一样
private final String callBackKey = "callback";

@Override
public boolean supports(MethodParameter methodParameter, Class aClass) {
logger.debug("返回的class={}", aClass);
return true;
}

/**
* 在此处对返回值进行处理,需要特别注意如果是非String类型,会被Json序列化,从而添加了双引号,解决办法见
*
* @param body 返回值
* @param methodParameter 方法参数
* @param mediaType 当前contentType,非String类型为json
* @param aClass convert的class
* @param serverHttpRequest request,暂时支持是ServletServerHttpRequest类型,其余类型将会原样返回
* @param serverHttpResponse response
* @return 如果body是String类型,加上方法头后返回,如果是其他类型,序列化后返回
* @see com.inkbox.boot.demo.converter.Jackson2HttpMessageConverter
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {

if (body == null)
return null;
//TODO 2019/8/30 如果返回String类型,media是plain,否则是json,将会经过json序列化,在下方返回纯字符串之后依然会被序列化,就会添上多余的双引号
logger.debug("body={},request={},response={},media={}", body, serverHttpRequest, serverHttpResponse, mediaType.getSubtype());


if (serverHttpRequest instanceof ServletServerHttpRequest) {
HttpServletRequest request = ((ServletServerHttpRequest) serverHttpRequest).getServletRequest();

String callback = request.getParameter(callBackKey);

if (!StringUtils.isEmpty(callback)) {
//使用了jsonp
if (body instanceof String) {
return callback + "(\"" + body + "\")";
} else {
try {
String res = mapper.writeValueAsString(body);
logger.debug("转化后的返回值={},{}", res, callback + "(" + res + ")");

return callback + "(" + res + ")";
} catch (JsonProcessingException e) {
logger.warn("【jsonp支持】数据body序列化失败", e);
return body;
}
}
}
} else {
logger.warn("【jsonp支持】不支持的request class ={}", serverHttpRequest.getClass());
}
return body;
}
}
2 changes: 2 additions & 0 deletions src/test/java/com/inkbox/boot/demo/DemoApplicationTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public void contextLoads() {

Assert.assertNotNull("没有reids操作实例", template);


logger.debug("{}",dao.findAllByName("inkbox"));
}

@Test
Expand Down

0 comments on commit 3eb6e25

Please sign in to comment.