[![Build Status](https://travis-ci.org/crossoverJie/cicada.svg?branch=master)](https://travis-ci.org/crossoverJie/cicada)
[![](https://maven-badges.herokuapp.com/maven-central/top.crossoverjie.opensource/cicada-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/top.crossoverjie.opensource/cicada-core/)
[![QQ群](https://img.shields.io/badge/QQ%E7%BE%A4-787381170-yellowgreen.svg)](https://jq.qq.com/?_wv=1027&k=5HPYvQk)
[qq0groupsvg]: https://img.shields.io/badge/QQ%E7%BE%A4-787381170-yellowgreen.svg
[qq0group]: https://jq.qq.com/?_wv=1027&k=5HPYvQk
📘[Features](#features) |🌁[Quick Start](#quick-start) | 🏖[Performance Test](#performance-test) | 🌈[ChangeLog](#changelog) | 💡 [Contact Author](#contact-author)|🇨🇳[中文文档](https://github.com/TogetherOS/cicada/blob/master/README-ZH.md)
---
## Introduction
Fast, lightweight Web framework based on Netty; without too much dependency, and the core jar package is only `30KB`.
If you are interested, please click [Star](https://github.com/crossoverJie/cicada/stargazers).
## Features
- [x] Clean code, without too much dependency.
- [x] One line of code to start the HTTP service.
- [x] [Custom interceptor](#custom-interceptor).
- [x] [Custom exception handle](#custom-exception-handle).
- [x] Flexible parameters way.
- [x] Response `json`.
- [x] Start with `jar`.
- [x] [Custom configuration](#custom-configuration).
- [x] Multiple response ways.
- [x] Pluggable `IOC` beanFactory。
- [x] [Support `Cookie`](#cookie).
- [ ] File Upload.
## Quick Start
Create a project with `Maven`, import core dependency.
```xml
top.crossoverjie.opensource
cicada-core
x.y.z
```
Of course, it is recommended to introduce an additional `IOC` container plugin:
```xml
top.crossoverjie.opensource
cicada-ioc
2.0.4
```
start class:
```java
public class MainStart {
public static void main(String[] args) throws InterruptedException {
CicadaServer.start(MainStart.class,"/cicada-example") ;
}
}
```
### Configuring Business Action
```java
@CicadaAction("routeAction")
public class RouteAction {
private static final Logger LOGGER = LoggerBuilder.getLogger(RouteAction.class);
@CicadaRoute("getUser")
public void getUser(DemoReq req){
LOGGER.info(req.toString());
WorkRes
reqWorkRes = new WorkRes<>() ;
reqWorkRes.setMessage("hello =" + req.getName());
CicadaContext.getContext().json(reqWorkRes) ;
}
@CicadaRoute("getInfo")
public void getInfo(DemoReq req){
WorkRes reqWorkRes = new WorkRes<>() ;
reqWorkRes.setMessage("getInfo =" + req.toString());
CicadaContext.getContext().json(reqWorkRes) ;
}
@CicadaRoute("getReq")
public void getReq(CicadaContext context,DemoReq req){
WorkRes reqWorkRes = new WorkRes<>() ;
reqWorkRes.setMessage("getReq =" + req.toString());
context.json(reqWorkRes) ;
}
}
```
Launch and apply access: [http://127.0.0.1:5688/cicada-example/routeAction/getUser?id=1234&name=zhangsan](http://127.0.0.1:5688/cicada-example/routeAction/getUser?id=1234&name=zhangsan)
```json
{"message":"hello =zhangsan"}
```
## Cicada Context
Through `context.json(), context.text()`, you can choose different response ways.
```java
@CicadaAction("routeAction")
public class RouteAction {
private static final Logger LOGGER = LoggerBuilder.getLogger(RouteAction.class);
@CicadaRoute("getUser")
public void getUser(DemoReq req){
LOGGER.info(req.toString());
WorkRes reqWorkRes = new WorkRes<>() ;
reqWorkRes.setMessage("hello =" + req.getName());
CicadaContext.getContext().json(reqWorkRes) ;
}
@CicadaRoute("hello")
public void hello() throws Exception {
CicadaContext context = CicadaContext.getContext();
String url = context.request().getUrl();
String method = context.request().getMethod();
context.text("hello world url=" + url + " method=" + method);
}
}
```
## Cookie Support
### Set Cookie
```java
Cookie cookie = new Cookie() ;
cookie.setName("cookie");
cookie.setValue("value");
CicadaContext.getResponse().setCookie(cookie);
```
### Get Cookie
```java
Cookie cookie = CicadaContext.getRequest().getCookie("cookie");
logger.info("cookie = " + cookie.toString());
```
## Custom configuration
By default, the configuration file under the `classpath` is read.
You can also customize the configuration file.
Just need to extends `top.crossoverjie.cicada.server.configuration.AbstractCicadaConfiguration`
class.
Write the name of the configuration file at the same time.
Like this:
```java
public class RedisConfiguration extends AbstractCicadaConfiguration {
public RedisConfiguration() {
super.setPropertiesName("redis.properties");
}
}
public class KafkaConfiguration extends AbstractCicadaConfiguration {
public KafkaConfiguration() {
super.setPropertiesName("kafka.properties");
}
}
```
![](https://ws3.sinaimg.cn/large/0069RVTdgy1fv5mw7p5nvj31by0fo76t.jpg)
### Get configuration information
Get the configuration infomation, follow this:
```java
KafkaConfiguration configuration = (KafkaConfiguration) getConfiguration(KafkaConfiguration.class);
RedisConfiguration redisConfiguration = (RedisConfiguration) ConfigurationHolder.getConfiguration(RedisConfiguration.class);
ApplicationConfiguration applicationConfiguration = (ApplicationConfiguration) ConfigurationHolder.getConfiguration(ApplicationConfiguration.class);
String brokerList = configuration.get("kafka.broker.list");
String redisHost = redisConfiguration.get("redis.host");
String port = applicationConfiguration.get("cicada.port");
LOGGER.info("Configuration brokerList=[{}],redisHost=[{}] port=[{}]",brokerList,redisHost,port);
```
### External configuration file
Configuration files can also be read in multiple environments, just add VM parameters, also ensure that the parameter name and file name are consistent.
```shell
-Dapplication.properties=/xx/application.properties
-Dkafka.properties=/xx/kakfa.properties
-Dredis.properties=/xx/redis.properties
```
## Custom interceptor
Implement `top.crossoverjie.cicada.example.intercept.CicadaInterceptor` interface.
```java
@Interceptor(value = "executeTimeInterceptor")
public class ExecuteTimeInterceptor implements CicadaInterceptor {
private static final Logger LOGGER = LoggerBuilder.getLogger(ExecuteTimeInterceptor.class);
private Long start;
private Long end;
@Override
public boolean before(Param param) {
start = System.currentTimeMillis();
return true;
}
@Override
public void after(Param param) {
end = System.currentTimeMillis();
LOGGER.info("cast [{}] times", end - start);
}
}
```
## Custom exception handle
You can define global exception handle,like this:
```java
@CicadaBean
public class ExceptionHandle implements GlobalHandelException {
private final static Logger LOGGER = LoggerBuilder.getLogger(ExceptionHandle.class);
@Override
public void resolveException(CicadaContext context, Exception e) {
LOGGER.error("Exception", e);
WorkRes workRes = new WorkRes();
workRes.setCode("500");
workRes.setMessage(e.getClass().getName());
context.json(workRes);
}
}
```
## Performance Test
![](https://user-images.githubusercontent.com/15684156/50533885-5dd41900-0b6e-11e9-925f-6ee563664f85.png)
> Test Conditions: 100 threads and 100 connections ;1G RAM/4 CPU
**Nearly 10W requests per second.**
## ChangeLog
### v2.0.2
- fix [#40](https://github.com/TogetherOS/cicada/issues/40)
- add global handle exception interface.
- get bean by class type.
### v2.0.1
- Logo.
- Cookie Support.
- Beautify the log.
### v2.0.0
- Fixed [#12](https://github.com/TogetherOS/cicada/issues/12) [#22](https://github.com/TogetherOS/cicada/issues/22) [#28](28)
- Flexible routing ways.
- Pluggable `IOC` beanFactory.
### v1.0.3
- Fixed [#9](https://github.com/TogetherOS/cicada/issues/9)
- Fixed [#8](https://github.com/TogetherOS/cicada/issues/8),Multiple response ways.
- Refactoring core code and add `Cicada Context`.
- Elegant closing service.
### v1.0.2
- Fixed [#6](https://github.com/TogetherOS/cicada/issues/6)
- Customize the configuration file.
- Using flexible.
- Refactor the code.
## Contact author
> crossoverJie#gmail.com
![qrcode_for_gh_3a954a025f10_258.jpg](https://i.loli.net/2019/07/09/5d245f3e955ce61699.jpg)
## Special thanks
- [Netty](https://github.com/netty/netty)
- [blade](https://github.com/lets-blade/blade)