page contents

Java Web 入门最佳学习路径教程

本文讲述了Java Web 入门最佳学习路径教程!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

attachments-2023-08-POkJzj5t64cda78e08645.png

本文讲述了Java Web 入门最佳学习路径教程!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

回顾自己的 Java 学习之路,最初跟着网络上学习 Java 教程,虽然说语法和基础知识掌握了个大概,再后来开始用 netty 做 web 容器开发项目,后来凭借之前开发经验结合 netty 的 api 还总结成了个一个轻量级的的框架。

「https://github.com/zhoumengkang/netty-restful-server」

优势是足够的小,基本秒启动,而且性能不错,适合小型项目使用;劣势不够开放只能自己运转,不符合 Servlet 标准。

「我想肯定很多人和我一样有同样的困惑,碎片知识吸收按吨算,但是总感觉没有入门。」

经过不断的东冲西撞最终摸索出一条比较适合有其他 web 语言开发经验的人学习 Java 的路径,所以计划总结成一个系列,自己巩固知识的同时也分享给其他人,赠人玫瑰手有余香。

目前 SpringBoot 是 Java Web 开发和 Java 微服务标准,Spring 是建立在 Servlet 协议标准之上的。毫不夸张的说「Servlet 技术是 Java Web 开发的原点」,所以我决定从这里开始讲起。

用 C/C++ 或者其他脚本语言做 Web 开发时,通常会以 CGI 或者 FastCGI 协议标准来做后端开发,web 服务器和 CGI 程序不是同一个进程, Java 做 Web 开发时,则是 Servlet ,Web 服务器进程和执行业务逻辑的 Servlet 程序在同一个进程。

为了做类比,我觉得有必要先说下  CGI 的开发模式。

学习 CGI

这里参考我之前的博客 https://mengkang.net/668.html

有兴趣的朋友可以看下 CGI 1.1 协议 ,这里不仅定义了很多标准的环境变量,URI 规则、请求的方法(GET/POST等)返回值 header 值等,可以说我们的所有 Web 开发的基石。

「那么 CGI 程序是怎么提供服务的呢?」

客户端访问某个 URL 地址之后,通过 GET/POST/PUT 等方式提交数据,并通过 HTTP 协议向 Web 服务器发出请求,服务器端的 HTTP Daemon(守护进程)将 HTTP 请求里描述的信息通过标准输入 stdin 和环境变量(environment variable)传递给主页指定的 CGI 程序,并启动此应用程序进行处理(包括对数据库的处理),处理结果通过标准输出 stdout 返回给 HTTP Daemon 守护进程,再由 HTTP Daemon 进程通过 HTTP 协议返回给客户端。

上面的这段话理解可能还是比较抽象,下面我们就通过一次GET请求为例进行详细说明。

attachments-2023-08-TlAJhUfJ64cda7227d1e9.png

Web Server

下面用代码来实现图中表述的功能。Web 服务器启动一个 socket 监听服务,然后在本地执行 CGI 程序。后面有比较详细的代码解读。

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#include <string.h>

    

#define SERV_PORT 9003

 

char* str_join(char *str1, char *str2);

char* html_response(char *res, char *buf);

   

int main(void)

{

    int lfd, cfd;

    struct sockaddr_in serv_addr,clin_addr;

    socklen_t clin_len;

    char buf[1024],web_result[1024];

    int len;

    FILE *cin;

  

    if((lfd = socket(AF_INET,SOCK_STREAM,0)) == -1){

        perror("create socket failed");

        exit(1);

    }

      

    memset(&serv_addr, 0, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;

    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    serv_addr.sin_port = htons(SERV_PORT);

  

    if(bind(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)

    {

        perror("bind error");

        exit(1);

    }

  

    if(listen(lfd, 128) == -1)

    {

        perror("listen error");

        exit(1);

    }

     

    signal(SIGCLD,SIG_IGN);

   

    while(1)

    {

        clin_len = sizeof(clin_addr);

        if ((cfd = accept(lfd, (struct sockaddr *)&clin_addr, &clin_len)) == -1)

        {

            perror("接收错误\n");

            continue;

        }

 

        cin = fdopen(cfd, "r");

        setbuf(cin, (char *)0);

        fgets(buf,1024,cin); //读取第一行

        printf("\n%s", buf);

 

        //============================ cgi 环境变量设置演示 ============================

         

        // 例如 "GET /user.cgi?id=1 HTTP/1.1";

 

        char *delim = " ";

        char *p;

        char *method, *filename, *query_string;

        char *query_string_pre = "QUERY_STRING=";

 

        method = strtok(buf,delim);         // GET

        p = strtok(NULL,delim);             // /user.cgi?id=1 

        filename = strtok(p,"?");           // /user.cgi

         

        if (strcmp(filename,"/favicon.ico") == 0)

        {

            continue;

        }

 

        query_string = strtok(NULL,"?");    // id=1

        putenv(str_join(query_string_pre,query_string));

 

        //============================ cgi 环境变量设置演示 ============================

 

        int pid = fork();

  

        if (pid > 0)

        {

            close(cfd);

        }

        else if (pid == 0)

        {

            close(lfd);

            FILE *stream = popen(str_join(".",filename),"r");

            fread(buf,sizeof(char),sizeof(buf),stream);

            html_response(web_result,buf);

            write(cfd,web_result,sizeof(web_result));

            pclose(stream);

            close(cfd);

            exit(0);

        }

        else

        {

            perror("fork error");

            exit(1);

        }

    }

   

    close(lfd);

       

    return 0;

}

 

char* str_join(char *str1, char *str2)

{

    char *result = malloc(strlen(str1)+strlen(str2)+1);

    if (result == NULL) exit (1);

    strcpy(result, str1);

    strcat(result, str2);

   

    return result;

}

 

char* html_response(char *res, char *buf)

{

    char *html_response_template = "HTTP/1.1 200 OK\r\nContent-Type:text/html\r\nContent-Length: %d\r\nServer: mengkang\r\n\r\n%s";

 

    sprintf(res,html_response_template,strlen(buf),buf);

     

    return res;

}

如上代码中的重点:


66~81行找到CGI程序的相对路径(我们为了简单,直接将其根目录定义为Web程序的当前目录),这样就可以在子进程中执行 CGI 程序了;同时设置环境变量,方便CGI程序运行时读取;


94~95行将 CGI 程序的标准输出结果写入 Web 服务器守护进程的缓存中;


97行则将包装后的 html 结果写入客户端 socket 描述符,返回给连接Web服务器的客户端。


CGI 程序(user.c)

#include <stdio.h>

#include <stdlib.h>

// 通过获取的 id 查询用户的信息

int main(void){

 

    //============================ 模拟数据库 ============================

    typedef struct 

    {

        int  id;

        char *username;

        int  age;

    } user;

 

    user users[] = {

        {},

        {

            1,

            "mengkang.zhou",

            18

        }

    };

    //============================ 模拟数据库 ============================

 

 

    char *query_string;

    int id;

 

    query_string = getenv("QUERY_STRING");

     

    if (query_string == NULL)

    {

        printf("没有输入数据");

    } else if (sscanf(query_string,"id=%d",&id) != 1)

    {

        printf("没有输入id");

    } else

    {

        printf("用户信息查询<br>学号: %d<br>姓名: %s<br>年龄: %d",id,users[id].username,users[id].age);

    }

     

    return 0;

}

将上面的 CGI 程序编译成gcc user.c -o user.cgi,放在上面web程序的同级目录。


代码中的第28行,从环境变量中读取前面在Web服务器守护进程中设置的环境变量,是我们演示的重点。

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

想高效系统的学习Java编程语言,推荐大家关注一个微信公众号:Java圈子。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Java入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2023-03-2AoKIjPQ64014b4ad30a3.jpg

  • 发表于 2023-08-05 09:36
  • 阅读 ( 149 )
  • 分类:Java开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
王昭君
王昭君

209 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1316 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章