Java实现基于NIO的多线程Web服务器实例
代码地址:https://github.com/iyuanyb/webserver
实现了
静态、动态资源获取;
Cookie、Session、HTTP长连接,及Session和HTTP长连接的定时清除;
类似SpringMVC的注解式编程,如@RequestMapping@RequestParam等,方法中可以根据参数名从前台获取数据,可以传递对象,也支持级联属性,如:
//GET/page?pageSize=10&pageNum=1HTTP/1.1 @RequestMapping("/page") Stringpage(@RequestParam(value="pageSize",defaultValue="10")IntegerpageSize,IntegerpageNum){...} /** *POST/loginHTTP/1.1 *... *user.name=admin&user.passwd=admin&user.data.val=ok ******** *User类:Stringname;Stringpasswd;Datadata; *Data类:Stringval; */ @RequestMapping("/login",method=HttpMethod.POST) Stringlogin(Useruser){...}
方法可以返回一个字符串表示模板路径,模板使用正则实现,仅可以从request和session域中获取属性值,如${request.user.id};
日志记录(使用java.util.logging内置日志记录器,自定义了日志格式):服务器运行相关日志(server-n.log),HTTP请求日志(access-n.log)。
API汇总:
@Controller
@RequestMapping
@RequestParam
@RequestHeader
@CookieValue
HttpRequest
HttpResponse
HttpSession
Cookie
HttpMethod
使用方法
导入jar包(见release)即可使用相关注解,还需要在classpath下创建一个webapp目录,表示静态web资源的根路径。然后在主类的main方法中调用BootStrap.run(),由于扫描控制器是通过遍历目录实现的,所以项目不支持打包,必须以class文件的形式发布。参数配置需要在classpath中提供一个server-config.properties配置文件即可,包含如下配置项:
#服务器端口 PORT=80 #存储日志文件的路径 LOG_FILE_STORAGE_PATH=E:\\ #连接过期时间,单位毫秒 CONNECTION_EXPIRY_TIME=30000 #清理过期连接的周期,单位毫秒 CONNECTION_CLEANING_CYCLE=30000 #Session过期时间,单位毫秒 SESSION_EXPIRY_TIME=30000 #清理过期Session的周期,单位毫秒 SESSION_CLEANING_CYCLE=30000 #监听客户端读事件的线程数目 POLLER_THREAD_COUNT=2 #处理具体请求的线程池的大小 REQUEST_PROCESSOR_THREAD_COUNT=4
演示
项目结构
EchoController.java
packagecom.test; //导包省略... @Controller//只有被@Controller标记的才会被认为是控制器 //支持在类上使用@RequestMapping注解, publicclassEchoController{ //线程安全 privatestaticfinalDateTimeFormatterformatter=DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm:ss"); @RequestMapping("/echo")//映射到"/echo" publicStringecho(HttpRequestrequest,@RequestParam(value="msg",defaultValue="输入为空")Stringmsg){ LocalDateTimelocalDateTime=LocalDateTime.ofEpochSecond(request.getSession().getLastAccessedTime()/1000,0,ZoneOffset.ofHours(8)); request.setAttribute("lastAccessedTime",localDateTime.format(formatter)); request.setAttribute("msg",msg); return"test.html";//要渲染的的模板路径(classpath:webapp/test.html) } publicstaticvoidmain(String[]args){ BootStrap.run(); } }
test.html
Test Echo:${request.msg}
LastAccessedTime:${request.lastAccessedTime}