diff --git a/blade-core/src/main/java/com/hellokaton/blade/Blade.java b/blade-core/src/main/java/com/hellokaton/blade/Blade.java
index b7dafc70..7a45d4d3 100644
--- a/blade-core/src/main/java/com/hellokaton/blade/Blade.java
+++ b/blade-core/src/main/java/com/hellokaton/blade/Blade.java
@@ -30,14 +30,12 @@
import com.hellokaton.blade.mvc.hook.WebHook;
import com.hellokaton.blade.mvc.http.HttpMethod;
import com.hellokaton.blade.mvc.http.session.SessionManager;
-import com.hellokaton.blade.mvc.route.DynamicMapping;
import com.hellokaton.blade.mvc.route.RouteMatcher;
-import com.hellokaton.blade.mvc.route.mapping.dynamic.RegexMapping;
-import com.hellokaton.blade.mvc.route.mapping.dynamic.TrieMapping;
import com.hellokaton.blade.mvc.ui.template.DefaultEngine;
import com.hellokaton.blade.mvc.ui.template.TemplateEngine;
import com.hellokaton.blade.options.CorsOptions;
import com.hellokaton.blade.options.HttpOptions;
+import com.hellokaton.blade.options.StaticOptions;
import com.hellokaton.blade.server.NettyServer;
import com.hellokaton.blade.server.Server;
import lombok.AccessLevel;
@@ -54,6 +52,8 @@
import java.util.function.Consumer;
import java.util.stream.Collectors;
+import static com.hellokaton.blade.mvc.BladeConst.ENV_KEY_FAVICON_DIR;
+
/**
* Blade Core
*
@@ -78,13 +78,6 @@ public class Blade {
*/
private final Set packages = new LinkedHashSet<>(BladeConst.PLUGIN_PACKAGE_NAME);
- /**
- * All static resource URL prefixes,
- * defaults to "/favicon.ico", "/robots.txt", "/static/", "/upload/", "/webjars/",
- * which are located under classpath
- */
- private final Set statics = new HashSet<>(BladeConst.DEFAULT_STATICS);
-
/**
* The default IOC container implementation
*/
@@ -121,7 +114,8 @@ public class Blade {
private final RouteMatcher routeMatcher = new RouteMatcher();
private CorsOptions corsOptions = null;
- private final HttpOptions httpOptions = HttpOptions.create();
+ private HttpOptions httpOptions = HttpOptions.create();
+ private StaticOptions staticOptions = StaticOptions.create();
/**
* Blade environment, which stores the parameters of the application.properties configuration file
@@ -280,6 +274,17 @@ public TemplateEngine templateEngine() {
return this.templateEngine;
}
+ /**
+ * setting favicon dir, default is /static
+ *
+ * @param faviconDir favicon dir
+ * @return blade instance
+ */
+ public Blade faviconDir(String faviconDir) {
+ this.setEnv(ENV_KEY_FAVICON_DIR, faviconDir);
+ return this;
+ }
+
/**
* Get RouteMatcher
*
@@ -294,6 +299,21 @@ public Blade http(Consumer consumer) {
return this;
}
+ public Blade http(HttpOptions httpOptions) {
+ this.httpOptions = httpOptions;
+ return this;
+ }
+
+ public Blade staticOptions(Consumer consumer) {
+ consumer.accept(this.staticOptions);
+ return this;
+ }
+
+ public Blade staticOptions(StaticOptions staticOptions) {
+ this.staticOptions = staticOptions;
+ return this;
+ }
+
public Blade cors(CorsOptions corsOptions) {
this.corsOptions = corsOptions;
return this;
@@ -307,6 +327,10 @@ public HttpOptions httpOptions() {
return this.httpOptions;
}
+ public StaticOptions staticOptions() {
+ return this.staticOptions;
+ }
+
/**
* Register bean to ioc container
*
@@ -329,29 +353,6 @@ public Blade register(@NonNull Class> cls) {
return this;
}
- /**
- * Add multiple static resource file
- * the default provides the static, upload
- *
- * @param folders static resource directory
- * @return blade
- */
- public Blade addStatics(@NonNull String... folders) {
- this.statics.addAll(Arrays.asList(folders));
- return this;
- }
-
- /**
- * Set whether to show the file directory, default doesn't show
- *
- * @param fileList show the file directory
- * @return blade
- */
- public Blade showFileList(boolean fileList) {
- this.environment.set(BladeConst.ENV_KEY_STATIC_LIST, fileList);
- return this;
- }
-
/**
* Get ioc bean
*
@@ -415,16 +416,6 @@ public Class> bootClass() {
return this.bootClass;
}
- /**
- * Get blade statics list.
- * e.g: "/favicon.ico", "/robots.txt", "/static/", "/upload/", "/webjars/"
- *
- * @return return statics
- */
- public Set getStatics() {
- return this.statics;
- }
-
/**
* When set to start blade scan packages
*
@@ -686,8 +677,8 @@ public Blade start(Class> mainCls, String... args) {
try {
//TODO: add support for Create and Delete
if (event.equals(StandardWatchEventKinds.ENTRY_MODIFY)) {
- Path destPath = FileChangeDetector.getDestPath(filePath, environment);
- Files.copy(filePath, destPath, StandardCopyOption.REPLACE_EXISTING);
+ Path destPath = FileChangeDetector.getDestPath(filePath, environment, staticOptions);
+ Files.copy(filePath, Objects.requireNonNull(destPath), StandardCopyOption.REPLACE_EXISTING);
}
} catch (IOException e) {
log.error("Exception when trying to copy updated file");
diff --git a/blade-core/src/main/java/com/hellokaton/blade/kit/reload/FileChangeDetector.java b/blade-core/src/main/java/com/hellokaton/blade/kit/reload/FileChangeDetector.java
index 4f018c1e..45e0c9f9 100644
--- a/blade-core/src/main/java/com/hellokaton/blade/kit/reload/FileChangeDetector.java
+++ b/blade-core/src/main/java/com/hellokaton/blade/kit/reload/FileChangeDetector.java
@@ -2,12 +2,16 @@
import com.hellokaton.blade.Environment;
import com.hellokaton.blade.mvc.BladeConst;
+import com.hellokaton.blade.options.StaticOptions;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
@@ -19,18 +23,18 @@ public class FileChangeDetector {
private final WatchService watcher;
private final Map pathMap = new HashMap<>();
- public FileChangeDetector(String dirPath) throws IOException{
+ public FileChangeDetector(String dirPath) throws IOException {
watcher = FileSystems.getDefault().newWatchService();
registerAll(Paths.get(dirPath));
}
- private void register(Path dir) throws IOException{
+ private void register(Path dir) throws IOException {
WatchKey key = dir.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
- pathMap.put(key,dir);
+ pathMap.put(key, dir);
}
- private void registerAll(Path dir) throws IOException{
- Files.walkFileTree(dir, new SimpleFileVisitor(){
+ private void registerAll(Path dir) throws IOException {
+ Files.walkFileTree(dir, new SimpleFileVisitor() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
register(dir);
@@ -39,22 +43,22 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) th
});
}
- public void processEvent(BiConsumer, Path> processor){
- for(;;){
+ public void processEvent(BiConsumer, Path> processor) {
+ for (; ; ) {
WatchKey key;
- try{
+ try {
key = watcher.take();
- }catch (InterruptedException e) {
+ } catch (InterruptedException e) {
return;
}
Path dir = pathMap.get(key);
- for (WatchEvent> event: key.pollEvents()){
+ for (WatchEvent> event : key.pollEvents()) {
WatchEvent.Kind kind = event.kind();
- Path filePath = dir.resolve(((WatchEvent)event).context());
+ Path filePath = dir.resolve(((WatchEvent) event).context());
- if(Files.isDirectory(filePath)) continue;
- log.info("File {} changes detected!",filePath.toString());
+ if (Files.isDirectory(filePath)) continue;
+ log.info("File {} changes detected!", filePath.toString());
//copy updated files to target
processor.accept(kind, filePath);
}
@@ -62,23 +66,18 @@ public void processEvent(BiConsumer, Path> processor){
}
}
- public static Path getDestPath(Path src, Environment env){
- String templateDir = env.get(BladeConst.ENV_KEY_TEMPLATE_PATH,"/templates");
- Optional staticDir = env.get(BladeConst.ENV_KEY_STATIC_DIRS);
+ public static Path getDestPath(Path src, Environment env, StaticOptions staticOptions) {
+ String templateDir = env.get(BladeConst.ENV_KEY_TEMPLATE_PATH, "/templates");
List templateOrStaticDirKeyword = new ArrayList<>();
templateOrStaticDirKeyword.add(templateDir);
- if(staticDir.isPresent()){
- templateOrStaticDirKeyword.addAll(Arrays.asList(staticDir.get().split(",")));
- }else{
- templateOrStaticDirKeyword.addAll(BladeConst.DEFAULT_STATICS);
- }
+ templateOrStaticDirKeyword.addAll(staticOptions.getPaths());
- List result = templateOrStaticDirKeyword.stream().filter(dir -> src.toString().indexOf(dir)!=-1).collect(Collectors.toList());
- if(result.size()!=1){
+ List result = templateOrStaticDirKeyword.stream().filter(dir -> src.toString().contains(dir)).collect(Collectors.toList());
+ if (result.size() != 1) {
log.info("Cannot get dest dir");
- return null;
+ return null;
}
- String key = (String)result.get(0);
+ String key = result.get(0);
log.info(BladeConst.CLASSPATH + src.toString().substring(src.toString().indexOf(key)));
return Paths.get(BladeConst.CLASSPATH + src.toString().substring(src.toString().indexOf(key)));
}
diff --git a/blade-core/src/main/java/com/hellokaton/blade/mvc/BladeConst.java b/blade-core/src/main/java/com/hellokaton/blade/mvc/BladeConst.java
index a72b7b79..5919b71f 100644
--- a/blade-core/src/main/java/com/hellokaton/blade/mvc/BladeConst.java
+++ b/blade-core/src/main/java/com/hellokaton/blade/mvc/BladeConst.java
@@ -17,7 +17,6 @@
import com.hellokaton.blade.kit.StringKit;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -38,8 +37,6 @@ public interface BladeConst {
String INTERNAL_SERVER_ERROR_HTML = "500 Internal Server Error
";
String DEFAULT_THREAD_NAME = "_(:3」∠)_";
List PLUGIN_PACKAGE_NAME = new ArrayList<>(Collections.singletonList("com.hellokaton.blade.plugin"));
- List DEFAULT_STATICS = new ArrayList<>(
- Arrays.asList("/favicon.ico", "/robots.txt", "/static", "/upload", "/webjars/"));
String PROP_NAME = "classpath:application.properties";
@@ -53,17 +50,17 @@ public interface BladeConst {
String ENV_KEY_TASK_THREAD_COUNT = "app.task.thread-count";
String ENV_KEY_CONTEXT_PATH = "app.context-path";
String ENV_KEY_REQUEST_LOG = "app.request-log";
+ String ENV_KEY_FAVICON_DIR = "app.favicon-dir";
String ENV_KEY_HTTP_MAX_CONTENT = "http.max-content-size";
String ENV_KEY_GZIP_ENABLE = "http.gzip.enabled";
String ENV_KEY_SESSION_ENABLED = "http.session.enabled";
String ENV_KEY_SESSION_KEY = "http.session.key";
String ENV_KEY_SESSION_TIMEOUT = "http.session.timeout";
- String ENV_KEY_HTTP_CACHE_TIMEOUT = "http.cache.timeout";
String ENV_KEY_HTTP_REQUEST_COST = "http.request.cost";
String ENV_KEY_PAGE_404 = "mvc.view.404";
String ENV_KEY_PAGE_500 = "mvc.view.500";
- String ENV_KEY_STATIC_DIRS = "mvc.statics";
- String ENV_KEY_STATIC_LIST = "mvc.statics.show-list";
+ String ENV_KEY_STATIC_LIST = "static.show-list";
+ String ENV_KEY_STATIC_CACHE_SECONDS = "static.cache-seconds";
String ENV_KEY_TEMPLATE_PATH = "mvc.template.path";
String ENV_KEY_SERVER_ADDRESS = "server.address";
String ENV_KEY_SERVER_PORT = "server.port";
@@ -88,6 +85,7 @@ public interface BladeConst {
String REQUEST_TO_STATIC_ATTR = "_to_static";
+ String FAVICON_PATH = "/favicon.ico";
String NEW_LINE = "\r\n";
int BANNER_PADDING = 60;
diff --git a/blade-core/src/main/java/com/hellokaton/blade/mvc/route/RouteMatcher.java b/blade-core/src/main/java/com/hellokaton/blade/mvc/route/RouteMatcher.java
index 8863f81c..dd09b35b 100644
--- a/blade-core/src/main/java/com/hellokaton/blade/mvc/route/RouteMatcher.java
+++ b/blade-core/src/main/java/com/hellokaton/blade/mvc/route/RouteMatcher.java
@@ -159,7 +159,7 @@ public List getBefore(String path) {
.flatMap(Collection::stream)
.sorted(Comparator.comparingInt(Route::getSort))
.filter(route -> route.getHttpMethod() == HttpMethod.BEFORE)
- .filter(route -> matchesPath(route.getPath(), cleanPath))
+ .filter(route -> matchesPath(route.getRewritePath(), cleanPath))
.collect(Collectors.toList());
this.giveMatch(path, collect);
@@ -178,7 +178,7 @@ public List getAfter(String path) {
.flatMap(Collection::stream)
.sorted(Comparator.comparingInt(Route::getSort))
.filter(route -> route.getHttpMethod() == HttpMethod.AFTER)
- .filter(route -> matchesPath(route.getPath(), cleanPath))
+ .filter(route -> matchesPath(route.getRewritePath(), cleanPath))
.collect(Collectors.toList());
this.giveMatch(path, afters);
diff --git a/blade-core/src/main/java/com/hellokaton/blade/mvc/ui/ResponseType.java b/blade-core/src/main/java/com/hellokaton/blade/mvc/ui/ResponseType.java
index d8b0a7ae..68aaadd8 100644
--- a/blade-core/src/main/java/com/hellokaton/blade/mvc/ui/ResponseType.java
+++ b/blade-core/src/main/java/com/hellokaton/blade/mvc/ui/ResponseType.java
@@ -12,6 +12,7 @@ public enum ResponseType {
XML(HttpConst.CONTENT_TYPE_XML),
TEXT(HttpConst.CONTENT_TYPE_TEXT),
HTML(HttpConst.CONTENT_TYPE_HTML),
+ VIEW(HttpConst.CONTENT_TYPE_HTML),
STREAM(HttpConst.CONTENT_TYPE_STREAM),
PREVIEW(""),
;
diff --git a/blade-core/src/main/java/com/hellokaton/blade/options/StaticOptions.java b/blade-core/src/main/java/com/hellokaton/blade/options/StaticOptions.java
new file mode 100644
index 00000000..4f3044df
--- /dev/null
+++ b/blade-core/src/main/java/com/hellokaton/blade/options/StaticOptions.java
@@ -0,0 +1,46 @@
+package com.hellokaton.blade.options;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+@Getter
+@Setter
+public class StaticOptions {
+
+ public static final int DEFAULT_CACHE_SECONDS = 86400 * 30;
+ public static final Set DEFAULT_STATICS = new HashSet<>(
+ Arrays.asList("/favicon.ico", "/robots.txt", "/static", "/webjars/"));
+
+ private boolean showList;
+ private Set paths = DEFAULT_STATICS;
+ private int cacheSeconds = DEFAULT_CACHE_SECONDS;
+
+ public static StaticOptions create() {
+ return new StaticOptions();
+ }
+
+ public StaticOptions showList() {
+ this.showList = true;
+ return this;
+ }
+
+ public StaticOptions addStatic(String staticPath) {
+ this.paths.add(staticPath);
+ return this;
+ }
+
+ public StaticOptions removeStatic(String staticPath) {
+ this.paths.remove(staticPath);
+ return this;
+ }
+
+ public StaticOptions cacheSeconds(int cacheSeconds) {
+ this.cacheSeconds = cacheSeconds;
+ return this;
+ }
+
+}
diff --git a/blade-core/src/main/java/com/hellokaton/blade/server/HttpServerHandler.java b/blade-core/src/main/java/com/hellokaton/blade/server/HttpServerHandler.java
index f584b472..b1435e42 100644
--- a/blade-core/src/main/java/com/hellokaton/blade/server/HttpServerHandler.java
+++ b/blade-core/src/main/java/com/hellokaton/blade/server/HttpServerHandler.java
@@ -59,10 +59,12 @@ public class HttpServerHandler extends SimpleChannelInboundHandler
public static final FastThreadLocal WEB_CONTEXT_THREAD_LOCAL = new FastThreadLocal<>();
- private final StaticFileHandler staticFileHandler = new StaticFileHandler(WebContext.blade());
+ static final StaticFileHandler staticFileHandler = new StaticFileHandler(WebContext.blade());
+
+ static final RouteMatcher routeMatcher = WebContext.blade().routeMatcher();
+
private final RouteMethodHandler routeHandler = new RouteMethodHandler();
private final Set notStaticUri = new LRUSet<>(128);
- private final RouteMatcher routeMatcher = WebContext.blade().routeMatcher();
private boolean recordRequestLog() {
return WebContext.blade().environment()
@@ -174,10 +176,16 @@ private boolean isStaticFile(HttpMethod method, String uri) {
return false;
}
- if (WebContext.blade().getStatics().stream().noneMatch(s -> s.equals(uri) || uri.startsWith(s))) {
+ if (FAVICON_PATH.equals(uri)) {
+ return true;
+ }
+
+ Set paths = WebContext.blade().staticOptions().getPaths();
+ if (paths.stream().noneMatch(s -> s.equals(uri) || uri.startsWith(s))) {
notStaticUri.add(uri);
return false;
}
+
return true;
}
diff --git a/blade-core/src/main/java/com/hellokaton/blade/server/HttpServerInitializer.java b/blade-core/src/main/java/com/hellokaton/blade/server/HttpServerInitializer.java
index be8c6f0e..42ebda4e 100644
--- a/blade-core/src/main/java/com/hellokaton/blade/server/HttpServerInitializer.java
+++ b/blade-core/src/main/java/com/hellokaton/blade/server/HttpServerInitializer.java
@@ -5,6 +5,7 @@
import com.hellokaton.blade.kit.DateKit;
import com.hellokaton.blade.options.CorsOptions;
import com.hellokaton.blade.options.HttpOptions;
+import com.hellokaton.blade.options.StaticOptions;
import com.hellokaton.blade.server.decode.FullHttpRequestDecode;
import com.hellokaton.blade.server.decode.HttpObjectAggregatorDecode;
import io.netty.channel.ChannelInitializer;
@@ -34,11 +35,11 @@
public class HttpServerInitializer extends ChannelInitializer {
private final HttpServerHandler httpServerHandler;
-
private final SslContext sslCtx;
private CorsConfig corsConfig;
private int maxContentSize;
private boolean enableGzip;
+
public static volatile String date = DateKit.gmtDate(LocalDateTime.now());
@@ -46,10 +47,12 @@ public HttpServerInitializer(SslContext sslCtx, Blade blade, ScheduledExecutorSe
this.sslCtx = sslCtx;
this.httpServerHandler = new HttpServerHandler();
this.mergeCorsConfig(blade.corsOptions());
+ this.mergeStaticOptions(blade.staticOptions(), blade.environment());
this.mergeHttpOptions(blade.httpOptions(), blade.environment());
service.scheduleWithFixedDelay(() -> date = DateKit.gmtDate(LocalDateTime.now()), 1000, 1000, TimeUnit.MILLISECONDS);
}
+
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
@@ -114,6 +117,24 @@ private void mergeCorsConfig(CorsOptions corsOptions) {
this.corsConfig = corsConfigBuilder.build();
}
+ private void mergeStaticOptions(StaticOptions staticOptions, Environment environment) {
+ int cacheSeconds = staticOptions.getCacheSeconds();
+ if (cacheSeconds > 0 && StaticOptions.DEFAULT_CACHE_SECONDS != cacheSeconds) {
+ environment.set(ENV_KEY_STATIC_CACHE_SECONDS, cacheSeconds);
+ } else {
+ cacheSeconds = environment.getInt(ENV_KEY_STATIC_CACHE_SECONDS, StaticOptions.DEFAULT_CACHE_SECONDS);
+ staticOptions.setCacheSeconds(cacheSeconds);
+ }
+
+ boolean showList = staticOptions.isShowList();
+ if (showList) {
+ environment.set(ENV_KEY_STATIC_LIST, true);
+ } else {
+ showList = environment.getBoolean(ENV_KEY_STATIC_LIST, Boolean.FALSE);
+ staticOptions.setShowList(showList);
+ }
+ }
+
private void mergeHttpOptions(HttpOptions httpOptions, Environment environment) {
this.maxContentSize = httpOptions.getMaxContentSize();
this.enableGzip = httpOptions.isEnableGzip();
diff --git a/blade-core/src/main/java/com/hellokaton/blade/server/NettyServer.java b/blade-core/src/main/java/com/hellokaton/blade/server/NettyServer.java
index 9d09748c..4f131fec 100644
--- a/blade-core/src/main/java/com/hellokaton/blade/server/NettyServer.java
+++ b/blade-core/src/main/java/com/hellokaton/blade/server/NettyServer.java
@@ -361,11 +361,6 @@ private void initConfig() {
// print banner text
this.printBanner();
- String statics = environment.get(ENV_KEY_STATIC_DIRS, "");
- if (StringKit.isNotBlank(statics)) {
- blade.addStatics(statics.split(","));
- }
-
String templatePath = environment.get(ENV_KEY_TEMPLATE_PATH, "templates");
if (templatePath.charAt(0) == NettyHttpConst.CHAR_SLASH) {
templatePath = templatePath.substring(1);
diff --git a/blade-core/src/main/java/com/hellokaton/blade/server/RouteMethodHandler.java b/blade-core/src/main/java/com/hellokaton/blade/server/RouteMethodHandler.java
index 25d6b8ab..968ae680 100644
--- a/blade-core/src/main/java/com/hellokaton/blade/server/RouteMethodHandler.java
+++ b/blade-core/src/main/java/com/hellokaton/blade/server/RouteMethodHandler.java
@@ -44,15 +44,13 @@
/**
* Http Server Handler
*
- * @author biezhi
- * 2017/5/31
+ * @author hellokaton
+ * 2022/5/9
*/
@Slf4j
public class RouteMethodHandler implements RequestHandler {
private final RouteMatcher routeMatcher = WebContext.blade().routeMatcher();
- private final StaticFileHandler staticFileHandler = new StaticFileHandler(WebContext.blade());
-
private final boolean hasBeforeHook = routeMatcher.hasBeforeHook();
private final boolean hasAfterHook = routeMatcher.hasAfterHook();
@@ -130,7 +128,7 @@ public HttpResponse onView(ViewBody body) {
public HttpResponse onStatic(StaticFileBody body) {
request.attribute(REQUEST_TO_STATIC_ATTR, body.path());
try {
- staticFileHandler.handle(webContext);
+ HttpServerHandler.staticFileHandler.handle(webContext);
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -231,16 +229,34 @@ private void routeHandle(RouteContext context) {
Path path = target.getClass().getAnnotation(Path.class);
- boolean responseJson = this.setResponseType(context, path);
+ ResponseType responseType = ResponseType.EMPTY;
+ if (null != path && !ResponseType.EMPTY.equals(path.responseType())) {
+ responseType = path.responseType();
+ }
+ ResponseType routeResponseType = context.route().getResponseType();
+ if (null != routeResponseType && !ResponseType.EMPTY.equals(routeResponseType)) {
+ responseType = routeResponseType;
+ }
+
+ boolean responseJson = ResponseType.JSON.equals(responseType);
+ if (responseJson) {
+ if (!context.isIE()) {
+ context.contentType(HttpConst.CONTENT_TYPE_JSON);
+ } else {
+ context.contentType(HttpConst.CONTENT_TYPE_HTML);
+ }
+ } else if (null != responseType && !ResponseType.EMPTY.equals(responseType)
+ && !ResponseType.PREVIEW.equals(responseType)) {
+ context.contentType(responseType.contentType());
+ }
int len = actionMethod.getParameterTypes().length;
MethodAccess methodAccess = BladeCache.getMethodAccess(target.getClass());
- Object returnParam = methodAccess.invoke(
- target, actionMethod.getName(), len > 0 ?
- context.routeParameters() : null);
+ Object[] args = len > 0 ? context.routeParameters() : null;
+ Object returnParam = methodAccess.invoke(target, actionMethod.getName(), args);
if (null == returnParam) {
return;
}
@@ -250,9 +266,15 @@ private void routeHandle(RouteContext context) {
return;
}
if (returnType == String.class) {
- context.body(
- ViewBody.of(new ModelAndView(returnParam.toString()))
- );
+ if (ResponseType.VIEW.equals(responseType)) {
+ context.body(
+ ViewBody.of(new ModelAndView(returnParam.toString()))
+ );
+ } else if (ResponseType.HTML.equals(responseType)) {
+ context.html(returnParam.toString());
+ } else if (ResponseType.TEXT.equals(responseType)) {
+ context.text(returnParam.toString());
+ }
return;
}
if (returnType == ModelAndView.class) {
@@ -266,29 +288,6 @@ private void routeHandle(RouteContext context) {
}
}
- private boolean setResponseType(RouteContext context, Path path) {
- ResponseType responseType = ResponseType.EMPTY;
- if (null != path && !ResponseType.EMPTY.equals(path.responseType())) {
- responseType = path.responseType();
- }
- ResponseType routeResponseType = context.route().getResponseType();
- if (null != routeResponseType && !ResponseType.EMPTY.equals(routeResponseType)) {
- responseType = routeResponseType;
- }
- boolean responseJson = ResponseType.JSON.equals(responseType);
- if (responseJson) {
- if (!context.isIE()) {
- context.contentType(HttpConst.CONTENT_TYPE_JSON);
- } else {
- context.contentType(HttpConst.CONTENT_TYPE_HTML);
- }
- } else if (null != routeResponseType && !ResponseType.EMPTY.equals(routeResponseType)
- && !ResponseType.PREVIEW.equals(routeResponseType)) {
- context.contentType(routeResponseType.contentType());
- }
- return responseJson;
- }
-
/**
* Invoke WebHook
*
diff --git a/blade-core/src/main/java/com/hellokaton/blade/server/StaticFileHandler.java b/blade-core/src/main/java/com/hellokaton/blade/server/StaticFileHandler.java
index 68e347c6..3d11fcf9 100644
--- a/blade-core/src/main/java/com/hellokaton/blade/server/StaticFileHandler.java
+++ b/blade-core/src/main/java/com/hellokaton/blade/server/StaticFileHandler.java
@@ -54,8 +54,7 @@
import java.util.regex.Pattern;
import static com.hellokaton.blade.kit.BladeKit.*;
-import static com.hellokaton.blade.mvc.BladeConst.HTTP_DATE_FORMAT;
-import static com.hellokaton.blade.mvc.BladeConst.REQUEST_TO_STATIC_ATTR;
+import static com.hellokaton.blade.mvc.BladeConst.*;
import static io.netty.handler.codec.http.HttpResponseStatus.*;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_0;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
@@ -81,11 +80,11 @@ public class StaticFileHandler implements RequestHandler {
/**
* default cache 30 days.
*/
- private final int httpCacheSeconds;
+ private final int staticFileCacheSeconds;
public StaticFileHandler(Blade blade) {
this.showFileList = blade.environment().getBoolean(BladeConst.ENV_KEY_STATIC_LIST, false);
- this.httpCacheSeconds = blade.environment().getInt(BladeConst.ENV_KEY_HTTP_CACHE_TIMEOUT, 86400 * 30);
+ this.staticFileCacheSeconds = blade.environment().getInt(BladeConst.ENV_KEY_STATIC_CACHE_SECONDS, 86400 * 30);
}
/**
@@ -98,7 +97,7 @@ public void handle(WebContext webContext) throws Exception {
Request request = webContext.getRequest();
ChannelHandlerContext ctx = webContext.getChannelHandlerContext();
- if (!com.hellokaton.blade.mvc.http.HttpMethod.GET.name().equals(request.method())) {
+ if (!HttpMethod.GET.name().equals(request.method())) {
sendError(ctx, METHOD_NOT_ALLOWED);
return;
}
@@ -114,6 +113,12 @@ public void handle(WebContext webContext) throws Exception {
} else {
uri = URLDecoder.decode(request.uri(), "UTF-8");
}
+
+ if (FAVICON_PATH.equals(uri)) {
+ String dir = WebContext.blade().getEnv(ENV_KEY_FAVICON_DIR, "/static");
+ uri = dir + uri;
+ }
+
String method = StringKit.padRight(request.method(), 6);
String cleanURL = getCleanURL(request, uri);
@@ -386,7 +391,7 @@ private boolean writeJarResource(ChannelHandlerContext ctx, Request request,
private boolean executeHttp304(ChannelHandlerContext ctx, Request request, long size, long lastModified) {
String ifModifiedSince = request.header(HttpConst.HEADER_IF_MODIFIED_SINCE);
- if (StringKit.isNotEmpty(ifModifiedSince) && httpCacheSeconds > 0) {
+ if (StringKit.isNotEmpty(ifModifiedSince) && staticFileCacheSeconds > 0) {
Date ifModifiedSinceDate = format(ifModifiedSince, HTTP_DATE_FORMAT);
@@ -436,11 +441,11 @@ private void setDateAndCacheHeaders(HttpResponse response, File fileToCache) {
response.headers().set(HttpHeaderNames.DATE, dateFormatter.format(time.getTime()));
// Add cache headers
- if (httpCacheSeconds > 0) {
- time.add(Calendar.SECOND, httpCacheSeconds);
+ if (staticFileCacheSeconds > 0) {
+ time.add(Calendar.SECOND, staticFileCacheSeconds);
response.headers().set(HttpHeaderNames.EXPIRES, dateFormatter.format(time.getTime()));
- response.headers().set(HttpHeaderNames.CACHE_CONTROL, "private, max-age=" + httpCacheSeconds);
+ response.headers().set(HttpHeaderNames.CACHE_CONTROL, "private, max-age=" + staticFileCacheSeconds);
response.headers().set(
HttpHeaderNames.LAST_MODIFIED, dateFormatter.format(new Date(fileToCache.lastModified())));
}
diff --git a/blade-core/src/test/java/com/hellokaton/blade/BladeTest.java b/blade-core/src/test/java/com/hellokaton/blade/BladeTest.java
index f9a20848..6e99b7d0 100644
--- a/blade-core/src/test/java/com/hellokaton/blade/BladeTest.java
+++ b/blade-core/src/test/java/com/hellokaton/blade/BladeTest.java
@@ -8,6 +8,7 @@
import com.hellokaton.blade.mvc.http.HttpSession;
import com.hellokaton.blade.mvc.ui.template.TemplateEngine;
import com.hellokaton.blade.options.HttpOptions;
+import com.hellokaton.blade.options.StaticOptions;
import com.hellokaton.blade.types.BladeClassDefineType;
import com.mashape.unirest.http.Unirest;
import netty_hello.Hello;
@@ -120,11 +121,14 @@ public void testRegister() {
@Test
public void testAddStatics() {
Blade blade = Blade.create();
- blade.addStatics("/assets/", "/public");
+ blade.staticOptions(options -> {
+ options.addStatic("/assets/");
+ options.addStatic("/assets/");
+ });
- assertEquals(7, blade.getStatics().size());
- assertEquals(Boolean.TRUE, blade.getStatics().contains("/assets/"));
- assertEquals(Boolean.FALSE, blade.getStatics().contains("/hello/"));
+ assertEquals(7, blade.staticOptions().getPaths().size());
+ assertEquals(Boolean.TRUE, blade.staticOptions().getPaths().contains("/assets/"));
+ assertEquals(Boolean.FALSE, blade.staticOptions().getPaths().contains("/hello/"));
}
@Test
@@ -194,8 +198,8 @@ public void testThreadName() {
@Test
public void testShowFileList() {
Blade blade = Blade.create();
- blade.showFileList(false);
- assertEquals(Boolean.FALSE, blade.environment().getBooleanOrNull(ENV_KEY_STATIC_LIST));
+ blade.staticOptions(StaticOptions::showList);
+ assertEquals(Boolean.FALSE, blade.staticOptions().isShowList());
}
@Test
diff --git a/blade-examples/src/main/java/com/example/Application.java b/blade-examples/src/main/java/com/example/Application.java
index 54af0d7f..e4e5ee0f 100644
--- a/blade-examples/src/main/java/com/example/Application.java
+++ b/blade-examples/src/main/java/com/example/Application.java
@@ -17,6 +17,7 @@
import com.hellokaton.blade.mvc.ui.ResponseType;
import com.hellokaton.blade.mvc.ui.RestResponse;
import com.hellokaton.blade.options.CorsOptions;
+import com.hellokaton.blade.options.HttpOptions;
import com.hellokaton.blade.security.limit.LimitOptions;
import lombok.extern.slf4j.Slf4j;
@@ -71,6 +72,11 @@ public String index(Request req) {
return token;
}
+ @GET(value = "home", responseType = ResponseType.VIEW)
+ public String home() {
+ return "home.html";
+ }
+
@POST
public String verifyToken(Request req) {
System.out.println("token = " + req.header("X-CSRF-TOKEN"));
@@ -110,7 +116,7 @@ public static void main(String[] args) {
Blade.create()
.cors(corsOptions)
-// .http(HttpOptions::enableSession)
+ .http(HttpOptions::enableSession)
.get("/base/:uid", ctx -> {
ctx.text(ctx.pathString("uid"));
})
diff --git a/blade-examples/src/main/resources/static/favicon.ico b/blade-examples/src/main/resources/static/favicon.ico
new file mode 100644
index 00000000..259de9cb
Binary files /dev/null and b/blade-examples/src/main/resources/static/favicon.ico differ
diff --git a/blade-examples/src/main/resources/templates/home.html b/blade-examples/src/main/resources/templates/home.html
index e4f405c3..dab65bc1 100644
--- a/blade-examples/src/main/resources/templates/home.html
+++ b/blade-examples/src/main/resources/templates/home.html
@@ -3,9 +3,10 @@
+
Title
-
+ This is home page.