前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >轻量级框架Spark快速入门

轻量级框架Spark快速入门

作者头像
老钱
发布2018-08-15 16:31:19
1.1K0
发布2018-08-15 16:31:19
举报
文章被收录于专栏:码洞码洞

尝试过Python/Ruby/Nodejs/Golang语言开发的人往往难以适应Java Web框架,相对于这些语言提供的web框架来说,Java的Web框架显的过于笨重了。

那有没有一种看起来很轻量级的Java Web框架呢?当然有,本篇介绍的Spark框架就是其中之一。此Spark不是大数据用到的Spark,名字相同,纯属巧合,两者完全没有关联性。

作者坦言Spark框架的灵感源于Ruby的Sinatra微框架,正好赶上了Java8迟来的闭包,于是就诞生了看起来非常轻量级的Spark。另外Google牵头的kotlin又正被炒的火热,Spark与时俱进,很快就出了一个kotlin版本的Spark框架。

首先引入它的依赖

代码语言:javascript
复制
<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-core</artifactId>
    <version>2.7.1</version>
</dependency>

我们看看它的Hello World

代码语言:javascript
复制
import static spark.Spark.*;

public class HelloWorld {
    public static void main(String[] args) {
        get("/hello", (req, res) -> "Hello World");
    }
}

运行一下上面的代码,你就可以在浏览器里访问http://localhost:4567/hello这个了

我们来比较一下Sinatra框架的Hello World

代码语言:javascript
复制
require 'sinatra'

get '/' do
  'Hello world!'
end

Wow,虽然Spark要敲打的字母还是要多很多,但是毫无疑问,它们已经很接近了。值得一提的是,Spark框架启动速度非常快速,肉眼几乎没有延迟,而相比之下,SpringBoot的启动效率就之于马车和火箭的关系了。

也许你会当心Spark框架并不主流,估计不是太稳定吧。关于这一点我必须说明的是Spark本身只是底层Jetty内核容器的一个包装,Jetty才是Spark的灵魂,Spark不过是一间非常漂亮的外衣,让我们用起来赏心悦目。

下面是Spark最常用的CRUD调用形式

代码语言:javascript
复制
get("/", (request, response) -> {
    // Get Something
});

post("/", (request, response) -> {
    // Create something
});

put("/", (request, response) -> {
    // Update something
});

delete("/", (request, response) -> {
    // Delete something
});

复杂一点可以使用路由组合,将页面API模块化

代码语言:javascript
复制
path("/api", () -> {
    path("/email", () -> {
        post("/add",       EmailApi.addEmail);
        put("/change",     EmailApi.changeEmail);
        delete("/remove",  EmailApi.deleteEmail);
    });
    path("/username", () -> {
        post("/add",       UserApi.addUsername);
        put("/change",     UserApi.changeUsername);
        delete("/remove",  UserApi.deleteUsername);
    });
});

同时还支持过滤器,我们可以在过滤器里加鉴权逻辑/访问日志/服务耗时跟踪等

代码语言:javascript
复制
before((request, response) -> {
    boolean authenticated;
    // ... check if authenticated
    if (!authenticated) {
        halt(401, "You are not welcome here");
    }
});

after((request, response) -> {
    response.header("foo", "set by after filter");
});

对于request和response对象,Spark提供了丰富的API

代码语言:javascript
复制
request.attributes();             // the attributes list
request.attribute("foo");         // value of foo attribute
request.attribute("A", "V");      // sets value of attribute A to V
request.body();                   // request body sent by the client
request.bodyAsBytes();            // request body as bytes
request.contentLength();          // length of request body
request.contentType();            // content type of request.body
request.contextPath();            // the context path, e.g. "/hello"
request.cookies();                // request cookies sent by the client
request.headers();                // the HTTP header list
request.headers("BAR");           // value of BAR header
request.host();                   // the host, e.g. "example.com"
request.ip();                     // client IP address
request.params("foo");            // value of foo path parameter
request.params();                 // map with all parameters
request.pathInfo();               // the path info
request.port();                   // the server port
request.protocol();               // the protocol, e.g. HTTP/1.1
request.queryMap();               // the query map
request.queryMap("foo");          // query map for a certain parameter
request.queryParams();            // the query param list
request.queryParams("FOO");       // value of FOO query param
request.queryParamsValues("FOO")  // all values of FOO query param
request.raw();                    // raw request handed in by Jetty
request.requestMethod();          // The HTTP method (GET, ..etc)
request.scheme();                 // "http"
request.servletPath();            // the servlet path, e.g. /result.jsp
request.session();                // session management
request.splat();                  // splat (*) parameters
request.uri();                    // the uri, e.g. "http://example.com/foo"
request.url();                    // the url. e.g. "http://example.com/foo"
request.userAgent();              // user agent

response.body();               // get response content
response.body("Hello");        // sets content to Hello
response.header("FOO", "bar"); // sets header FOO with value bar
response.raw();                // raw response handed in by Jetty
response.redirect("/example"); // browser redirect to /example
response.status();             // get the response status
response.status(401);          // set status code to 401
response.type();               // get the content type
response.type("text/xml");     // set content type to text/xml

还有一些更加高级的API,比如精细控制线程池大小

代码语言:javascript
复制
int maxThreads = 8;
int minThreads = 2;
int timeOutMillis = 30000;
threadPool(maxThreads, minThreads, timeOutMillis);

HTTPS支持

代码语言:javascript
复制
secure(keystoreFilePath, keystorePassword, truststoreFilePath, truststorePassword);

自定义错误页面

代码语言:javascript
复制
// Using Route
notFound((req, res) -> {
    res.type("application/json");
    return "{\"message\":\"Custom 404\"}";
});
// Using Route
internalServerError((req, res) -> {
    res.type("application/json");
    return "{\"message\":\"Custom 500 handling\"}";
});

自定义异常处理

代码语言:javascript
复制
get("/throwexception", (request, response) -> {
    throw new YourCustomException();
});

exception(YourCustomException.class, (exception, request, response) -> {
    // Handle the exception here
});

实现API服务时,我们需要一个JSON转换器,将回应的对象转换成JSON形式

代码语言:javascript
复制
import com.google.gson.Gson;

public class JsonTransformer implements ResponseTransformer {

    private Gson gson = new Gson();

    @Override
    public String render(Object model) {
        return gson.toJson(model);
    }

}

get("/hello", "application/json", (request, response) -> {
    return new MyMessage("Hello World");
}, new JsonTransformer());

或者使用一个更加简洁的转换方法

代码语言:javascript
复制
Gson gson = new Gson();
get("/hello", (request, response) -> new MyMessage("Hello World"), gson::toJson);

制作网页时,我们需要一个模版渲染引擎,将编写的视图文件和数据融合在一起

代码语言:javascript
复制
get("template-example", (req, res) -> {
    Map<String, Object> model = new HashMap<>();
    return render(model, "path-to-template");
});

// declare this in a util-class
public static String render(Map<String, Object> model, String templatePath) {
    return new VelocityTemplateEngine().render(new ModelAndView(model, templatePath));
}

有很多种模版渲染引擎可供选择,Spark已经提供了扩展的library将这些引擎集成进来。只需要倒入相关maven依赖即可。比如集成FreeMarker

代码语言:javascript
复制
<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-template-freemarker</artifactId>
    <version>2.7.1</version>
</dependency>

WebSocket支持,可以用来开发你的交互式微信小程序了

代码语言:javascript
复制
import org.eclipse.jetty.websocket.api.*;
import org.eclipse.jetty.websocket.api.annotations.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;

@WebSocket
public class EchoWebSocket {

    // Store sessions if you want to, for example, broadcast a message to all users
    private static final Queue<Session> sessions = new ConcurrentLinkedQueue<>();

    @OnWebSocketConnect
    public void connected(Session session) {
        sessions.add(session);
    }

    @OnWebSocketClose
    public void closed(Session session, int statusCode, String reason) {
        sessions.remove(session);
    }

    @OnWebSocketMessage
    public void message(Session session, String message) throws IOException {
        System.out.println("Got: " + message);   // Print message
        session.getRemote().sendString(message); // and send it back
    }

}

webSocket("/echo", EchoWebSocket.class);
init(); // Needed if you don't define any HTTP routes after your WebSocket routesCopy

最后看看我们这个项目在github上的受欢迎程度如何,受惊的7000个Star

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-12-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码洞 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档