Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/taketoday/today-web
😐 A Java library for building web applications
https://github.com/taketoday/today-web
framework high-performance java java-web lightweight servlet springmvc
Last synced: 3 months ago
JSON representation
😐 A Java library for building web applications
- Host: GitHub
- URL: https://github.com/taketoday/today-web
- Owner: TAKETODAY
- License: gpl-3.0
- Archived: true
- Created: 2018-08-16T12:42:47.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2023-05-10T01:23:41.000Z (over 1 year ago)
- Last Synced: 2024-09-28T08:40:12.153Z (3 months ago)
- Topics: framework, high-performance, java, java-web, lightweight, servlet, springmvc
- Language: Java
- Homepage: https://taketoday.cn/articles/1553922073210.html
- Size: 2.84 MB
- Stars: 33
- Watchers: 2
- Forks: 5
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
moved to https://github.com/TAKETODAY/today-infrastructure/tree/master/today-web
# TODAY Web
🍎 A Java library for building web applications
![Java8](https://img.shields.io/badge/JDK-8+-success.svg)
[![GPLv3](https://img.shields.io/badge/License-GPLv3-blue.svg)](./LICENSE)
[![Author](https://img.shields.io/badge/Author-TODAY-blue.svg)](https://github.com/TAKETODAY)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/811723d275dc409ba6a823c9e08a5b3b)](https://app.codacy.com/app/TAKETODAY/today-web?utm_source=github.com&utm_medium=referral&utm_content=TAKETODAY/today-web&utm_campaign=Badge_Grade_Dashboard)
[![Java CI](https://github.com/TAKETODAY/today-web/workflows/Java%20CI/badge.svg)](https://github.com/TAKETODAY/today-web/actions)## 背景
先不看
本人从2016年大一开始学Java,准确的说是高三最后的几周开始的. 果然兴趣是最好的老师, 在大一下学期自己独自一人从前端到后台写了我的个人网站:TODAY BLOG 。 从注册域名到备案再到网站成功上线,我遇到过的困难数不计其数。因为感兴趣所以我坚持了下来。第一个版本使用的纯Servlet写的。
后来了解到Java有很多开源框架可以简化我的开发。于是又投入到新一轮的学习之中...... 学了Struts2后自己学着写了一个小框架:TODAY Web 1.0 ,几百行搞定从解析xml定义的action到处理对应的请求。学了Spring MVC后,我写了此项目:TODAY Web 2.0。
## 安装
```xml
cn.taketoday
today-web
3.0.2.RELEASE```
- [Maven Central](https://search.maven.org/artifact/cn.taketoday/today-web/3.0.0.RELEASE/jar)## 案例
- [DEMO](https://github.com/TAKETODAY/today-web-demo)## 文档
- [Wiki](https://gitee.com/I-TAKE-TODAY/today_web/wikis)## 使用说明
### 函数式路由
```java
@Component
@ResponseBody
public class FunctionController {public String function(RequestContext request) {
return "body:" + request.method() + " requestURI -> " + request.requestURI();
}public String test(RequestContext request) {
return "body:" + request.method() + " test -> " + request.requestURI();
}public void script(RequestContext request) throws IOException {
ModelAndView modelAndView = new ModelAndView();
request.modelAndView(modelAndView);modelAndView.setContentType("text/html;charset=UTF-8");
modelAndView.setView(new StringBuilder("alert('HELLO, 你好 script');"));
}
}@Configuration
//@EnableDefaultMybatis
//@EnableRedissonCaching
public class WebMvcConfig implements WebMvcConfiguration {@Autowired
private FunctionController functionController;@Override
public void configureFunctionHandler(FunctionHandlerRegistry registry) {registry.get("/function", functionController::function);
registry.get("/function/test", functionController::test);
registry.get("/function/script", functionController::script);registry.get("/function/error/500", (context) -> {
context.sendError(500);
});
}
}
```### 注解路由
```java
//@Controller
@RestController
@RequestMapping("/users")
public class UserController {
@GET("index")
@POST("post")
@PUT("articles/{id}")
......
@RequestMapping("/users/{id}")
@RequestMapping(value = "/**", method = {RequestMethod.GET})
@RequestMapping(value = "/*.html", method = {RequestMethod.GET})
@RequestMapping(value = {"/index.action", "/index.do", "/index"}, method = RequestMethod.GET)
@Interceptor({LoginInterceptor.class, ...})
public (String|List>|Set>|Map>|void|File|Image|...) \\w+ (request, request, session,servletContext, str, int, long , byte, short, boolean, @Session("loginUser"), @Header("User-Agent"), @Cookie("JSESSIONID"), @PathVariable("id"), @RequestBody("users"), @Multipart("uploadFiles") MultipartFile[]) {
service...
return >;
}
}```
### ViewController
```java
@Configuration
public class WebMvcConfig implements WebMvcConfiguration {@Override
public void configureViewController(ViewControllerHandlerRegistry registry) {
registry.addViewController("/github", "redirect:https://github.com");
registry.addRedirectViewController("/login.do", "/login");
registry.addViewController("/login.action")
.setAssetsPath("redirect:/login");
}
}```
### 静态资源
```java
@Singleton
@Profile("dev")
public ResourceHandlerRegistry devRsourceMappingRegistry(@Env("site.uploadPath") String upload,
@Env("site.assetsPath") String assetsPath) //
{
final ResourceHandlerRegistry registry = new ResourceHandlerRegistry();registry.addResourceMapping("/assets/**")//
.addLocations(assetsPath);registry.addResourceMapping("/upload/**")//
.addLocations(upload);registry.addResourceMapping("/logo.png")//
.addLocations("file:///D:/dev/www.yhj.com/webapps/assets/images/logo.png");registry.addResourceMapping("/favicon.ico")//
.addLocations("classpath:/favicon.ico");return registry;
}@Singleton
@Profile("prod")
public ResourceHandlerRegistry prodResourceMappingRegistry() {final ResourceHandlerRegistry registry = new ResourceHandlerRegistry();
registry.addResourceMapping(LoginInterceptor.class)//
.setPathPatterns("/assets/admin/**")//
.setOrder(Ordered.HIGHEST_PRECEDENCE)//
.addLocations("/assets/admin/");return registry;
}@Override
public void configureResourceHandler(ResourceHandlerRegistry registry) {registry.addResourceMapping(LoginInterceptor.class)//
.setPathPatterns("/assets/admin/**")//
.setOrder(Ordered.HIGHEST_PRECEDENCE)//
.addLocations("/assets/admin/");
}
```### 自定义参数转换器
```java
@Singleton
public class UserSessionParameterResolver implements OrderedParameterResolver {
private final WebSessionManager sessionManager;public UserSessionParameterResolver(WebSessionManager sessionManager) {
this.sessionManager = sessionManager;
}@Override
public boolean supports(MethodParameter parameter) {
return parameter.isAnnotationPresent(UserSession.class);
}@Override
public Object resolveParameter(final RequestContext context, final MethodParameter parameter) throws Throwable {
final WebSession session = sessionManager.getSession(context, false);
if (session != null) {
final Object attribute = session.getAttribute(Constant.USER_INFO);
if (attribute != null) {
return attribute;
}
}
throw new UnauthorizedException();
}@Override
public int getOrder() {
return HIGHEST_PRECEDENCE;
}}
@Singleton
@Order(Ordered.HIGHEST_PRECEDENCE)
public class PageableMethodArgumentResolver implements ParameterResolver {private static final String PARAMETER_SIZE = "size";
private static final String PARAMETER_CURRENT = "page";private int maxListSize;
private int defaultListSize;@Override
public boolean supports(MethodParameter parameter) {
return parameter.isAssignableTo(Pageable.class);
}@Override
public Object resolveParameter(RequestContext request, MethodParameter parameter) throws Throwable {
return new RequestContextPageable(request, defaultListSize, maxListSize);
}public int getMaxListSize() {
return maxListSize;
}public void setMaxListSize(int maxListSize) {
this.maxListSize = maxListSize;
}public int getDefaultListSize() {
return defaultListSize;
}public void setDefaultListSize(int listSize) {
this.defaultListSize = listSize;
}public final static class RequestContextPageable implements Pageable {
private final int maxListSize;
private final int defaultListSize;private Integer size;
private Integer current;
private final RequestContext request;public RequestContextPageable(RequestContext request, int listSize, int maxListSize) {
this.request = request;
this.defaultListSize = listSize;
this.maxListSize = maxListSize;
}@Override
public int getCurrent() {if (current == null) {
final String parameter = request.getParameter(PARAMETER_CURRENT);
if (StringUtils.isEmpty(parameter)) {
current = 1;
}
else if ((current = Integer.valueOf(parameter)) <= 0) {
throw new IllegalArgumentException("only 'page > 0'");
}
}
return current.intValue();
}@Override
public int getSize() {
if (size == null) {
int s;
final String parameter = request.getParameter(PARAMETER_SIZE);
if (StringUtils.isEmpty(parameter)) {
s = defaultListSize;
}
else {
s = Integer.parseInt(parameter);
if (s <= 0) {
throw new IllegalArgumentException("only 'size > 0'");
}
if (s > maxListSize) {
throw DemoUtils.accessForbidden();
}
}
return size = s;
}
return size.intValue();
}}
}
@Component
public class DateConverter implements Converter {
@Override
public Date convert(String source) throws ConversionException {
...
}
}```
### 也可以通过xml文件配置简单视图
```xml
```
### 登录实例```java
@Controller
public class UserController {/*
*/
// @GET("login")
@RequestMapping(value = "/login" , method = RequestMethod.GET)
public String login() {
return "/login/login";//支持jsp,FreeMarker,Thymeleaf,自定义视图
}
@Logger("登录")
//@POST("/login")
//@RequestMapping(value = "/login" , method = RequestMethod.POST)
@ActionMapping(value = "/login", method = RequestMethod.POST)
public String login(HttpSession session, RedirectModel redirectModel, @Valid User user, Errors error) {
if (error.hasErrors()) {
System.err.println(error.getAllErrors());
redirectModel.attribute("msg", error.getAllErrors().toString());
return "redirect:/login";
}
User login = userService.login(user);
if (login == null) {
redirectModel.attribute("userId", user.getUserId());
redirectModel.attribute("msg", "登录失败");
return "redirect:/login";
}
redirectModel.attribute("msg", "登录成功");
session.setAttribute(USER_INFO, login);
return "redirect:/user/info";
}
}
```### 文件下载,支持直接返回给浏览器图片
```java
@RequestMapping(value = {"/download"}, method = RequestMethod.GET)
public File download(String path) {
return new File(path);
}
``````java
@GET("/display")
public final BufferedImage display(HttpServletResponse response) throws IOException {
response.setContentType("image/jpeg");
return ImageIO.read(new File("D:/taketoday.cn/webapps/upload/logo.png"));
}@GET("captcha")
public final BufferedImage captcha(HttpServletRequest request) throws IOException {
BufferedImage image = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics graphics = image.getGraphics();
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, IMG_WIDTH, IMG_HEIGHT);
Graphics2D graphics2d = (Graphics2D) graphics;
drawRandomNum(graphics2d, request);
return image;
}
```### 文件上传,支持多文件
```java
@RequestMapping(value = { "/upload" }, method = RequestMethod.POST)
public final String upload(@Multipart MultipartFile uploadFile) throws IOException {String upload = "D:/www.yhj.com/webapps/upload/";
String path = upload + uploadFile.getFileName();
File file = new File(path);
uploadFile.save(file);return "/upload/" + uploadFile.getFileName();
}@POST({"/upload/multi"})
public final String multiUpload(HttpServletResponse response, @Multipart MultipartFile[] files) throws IOException {String upload = "D:/www.yhj.com/webapps/upload/";
for (MultipartFile multipartFile : files) {
String path = upload + multipartFile.getFileName();
File file = new File(path);
System.out.println(path);
if (!multipartFile.save(file)) {
return "alert('upload error !')";
//response.getWriter().print("alert('upload error !')");
}
}
//response.getWriter().print("alert('upload success !')");
return "alert('upload success !')";
}
```## 🙏 鸣谢
本项目的诞生离不开以下开源项目:
* [Freemarker](https://github.com/apache/freemarker): Apache Freemarker
* [Slf4j](https://github.com/qos-ch/slf4j): Simple Logging Facade for Java
* [Spring](https://github.com/spring-projects/spring-framework): Spring Framework
* [EL](https://github.com/TAKETODAY/today-expression): Java Unified Expression Language
* [FastJSON](https://github.com/alibaba/fastjson): A fast JSON parser/generator for Java
* [Lombok](https://github.com/rzwitserloot/lombok): Very spicy additions to the Java programming language
* [Today Context](https://github.com/TAKETODAY/today-context): A Java library for dependency injection and aspect oriented programing
* [Hibernate Validator](https://github.com/hibernate/hibernate-validator): Hibernate Validator - Bean Validation 2.0 (JSR 380) Reference Implementation## 📄 开源协议
请查看 [GNU GENERAL PUBLIC LICENSE](https://github.com/TAKETODAY/today-web/blob/master/LICENSE)