通过追踪代码发现play框架在收到http请求后将HTTP请求在pipeline中被交给了PlayHandler来处理
在PlayHandler的messageReceived方法中有如下代码片段:
Http.Request.current.set(new Http.Request());
finalResponse response =new Response();
Http.Response.current.set(response);
final Request request = parseRequest(ctx, nettyRequest, messageEvent);
可以看到request请求被获取到并放入了ThreadLocal中
往下追踪我们可以看到play框架调用了一组插件来处理当前请求,每个请求都会调用插件的rawInvocation方法
boolean raw = Play.pluginCollection.rawInvocation(request, response);
我们可以在这个方法里面给response注入
Access-Control-Allow-Origin:*
那么自实现一个插件:
CorsPlugin:
importplay.PlayPlugin;
importplay.mvc.Http;
/**
* Created by yyp on 2017/7/5.
*/
public class CorsPlugin extends PlayPlugin {
public CorsPlugin() {
}
@Override
public boolean rawInvocation(Http.Request request, Http.Response response) throws Exception {
//获取请求头中的请求类型
if(request.headers.containsKey("access-control-request-method")) {
//注入请求类型到requst的method中// 在跨域请求中play框架不会自转换请求类型所以需要手动注入
request.method= request.headers.get("access-control-request-method").value();
}
Http.Response.current().setHeader("Access-Control-Allow-Origin","*");
if( request.headers.containsKey("access-control-request-headers")) {
Http.Response.current().setHeader("Access-Control-Allow-Headers",request.headers.get("access-control-request-headers").value());
}
return super.rawInvocation(request, response);
}
}
将插件注入play框架中
在conf中新建文件play.plugins 在里面写入
800:com.power.util.CorsPlugin
其中800指的是插件的执行顺序,play会扫描classpath下所有的play.plugins文件来加载插件
如下:
play框架自带的插件文件如下:
0:play.CorePlugin
1:play.ConfigurationChangeWatcherPlugin
100:play.data.parsing.TempFilePlugin
200:play.data.validation.ValidationPlugin
300:play.db.DBPlugin
400:play.db.jpa.JPAPlugin
450:play.db.Evolutions
500:play.i18n.MessagesPlugin
600:play.libs.WS
700:play.jobs.JobsPlugin
100000:play.plugins.ConfigurablePluginDisablingPlugin
自此解决play框架跨域问题