Web开发入门

3 篇文章 0 订阅

1 Web基础

1.1 javaee和javase

javase: java桌面程序,控制台控制,,多线程,IO,网络(socket), gui界面

javaee:java web程序。浏览器控制

1.2 软件的结构

一般软件结构有两种B/S和C/S两种。

C/S(Client-Server 桌面应用程序->客户端-服务端):

特征:需要下载安装包才能运行,服务端升级时客户端也得升级。

典型应用:QQ、LOL等

B/S(Browser-Server 浏览器-服务端)

特征:不需要安装特定的客户端,服务端升级,客户端无需升级

典型应用:淘宝、天猫

JavaWeb程序就是b/s结构。

1.3 服务器

从物理上来说,服务器就是一台PC机器。

web服务器:PC机器安装一个具有web服务的软件

数据库服务器:PC机器安装一个具有数据管理服务的软件

邮件服务器:PC机器安装一个具有发送邮件服务的软件

作用:把本地的资源共享给外部访问

 

1.4 内网与外网的区别?

外网、内网是两种Internet的接入方式。 内网通俗的说就是局域网LAN网,外网通俗的说就是与因特网相通的WAN广域网或 MAN 城域网路。内网和外网是相对而言的。一般外网的范围比内网大,也可以外网、内网是两种Internet的接入方式。
  内网通俗的说就是局域网LAN网,外网通俗的说就是与因特网相通的WAN广域网或 MAN 城域网路。内网和外网是相对而言的。一般外网的范围比内网大,也可以说内网是外网的子网。
  外网(广域网)上的每一台电脑(或其他网络设备)都有一个或多个广域网IP地址(或者说公网、外网IP地址),广域网IP地址不能重复;局域网(LAN)上的每一台电脑(或其他网络设备)都有一个或多个局域网IP地址(或者说私网、内网IP地址),局域网IP地址是局域网内部分配的,不同局域网的IP地址可以重复,不会相互影响。
 

1.5 外网映射工具

   在做一些支付项目、微信开发、或对接第三方接口的时候,有些回调操作,可能会需要外网访问。

   那么我们在做本地开发的时候,外网无法访问到本地?

   怎么解决这个问题呢?

   就会用到外网映射工具,常用外网映射工具netapp(免费)、花生壳等。

  参考资料: https://natapp.cn/article/natapp_newbie

1.6 DNS解析

使用域名转换成IP地址,先读取本地HOST文件,本地文件没有从当前电信网管获取对应IP。

2 Servlet核心

2.1 生命周期

init(浏览器第一次访问时初始化Servlet)->service(服务器处理请求,一次请求处理一次,servlet单例设计模式)->destroy(服务器关闭时销毁Servlet)。

 

2.2 源码分析

Tomtcat内部代码运行:

                          1)通过映射找到到servlet-class的内容,字符串: com.itmayiedu.a_servlet.FirstServlet

                          2)通过反射构造FirstServlet对象

                                            2.1 得到字节码对象

                                            Class clazz = class.forName("com.itmayiedu.a_servlet.FirstServlet");

                                            2.2 调用无参数的构造方法来构造对象

                                            Object obj = clazz.newInstance();     ---1.servlet的构造方法被调用

                          3)创建ServletConfig对象,通过反射调用init方法

                                            3.1 得到方法对象

                                            Method m = clazz.getDeclareMethod("init",ServletConfig.class);

                                            3.2 调用方法

                                            m.invoke(obj,config);             --2.servlet的init方法被调用

                          4)创建request,response对象,通过反射调用service方法

                                            4.1 得到方法对象

                                       Methodm m =clazz.getDeclareMethod("service",HttpServletRequest.class,HttpServletResponse.class);

                                            4.2 调用方法

                                            m.invoke(obj,request,response);  --3.servlet的service方法被调用

                          5)当tomcat服务器停止或web应用重新部署,通过反射调用destroy方法

                                            5.1 得到方法对象

                                            Method m = clazz.getDeclareMethod("destroy",null);

                                            5.2 调用方法

                                            m.invoke(obj,null);            --4.servlet的destroy方法被调用

doGet怎么执行?

其实就是先进入HttpServlet的service方法,然后判断请求方式执行对应的方法。

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException var9) {
                    ifModifiedSince = -1L;
                }

                if (ifModifiedSince < lastModified / 1000L * 1000L) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
            this.doTrace(req, resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }

    }

2.3 线程安全

不安全。因为servlet是单例的

@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    private int i=1;
    public IndexServlet(){
        System.out.println("构造函数IndexServlet");
    }
    @Override
    public void init() throws ServletException {
        System.out.println("初始化IndexServlet");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            System.out.println("处理IndexServlet");
            resp.setCharacterEncoding("utf-8");
            resp.getWriter().write("这是第"+i+"次");
            i++;
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void destroy() {
        System.out.println("销毁IndexServlet");
    }
}

同时两次访问127.0.0.1:8080/index后看到控制台输出:

构造函数IndexServlet
初始化IndexServlet
处理IndexServlet
处理IndexServlet

而浏览器都是:

这是第1次

===>线程不安全,多个线程同时共享一个全局变量。

解决办法:

1)把使用到共享数据的代码块进行同步(使用synchronized关键字进行同步)

2)建议在servlet类中尽量不要使用成员变量。如果确实要使用成员,必须同步。而且尽量缩小同步代码块的范围。(哪里使用到了成员变量,就同步哪里!!),以避免因为同步而导致并发效率降低。

3 cookie和session

3.1 Cookie

3.1.1 特点

Cookie技术:保存在浏览器客户端的数据

3.1.2 技术核心

 Cookie类:用于存储会话数据

1)构造Cookie对象

 Cookie(java.lang.String name, java.lang.String value)

2)设置cookie

 void setPath(java.lang.String uri)   :设置cookie的有效访问路径

void setMaxAge(int expiry) : 设置cookie的有效时间

void setValue(java.lang.String newValue) :设置cookie的值

3)发送cookie到浏览器端保存

void response.addCookie(Cookie cookie)  : 发送cookie

4)服务器接收cookie

 Cookie[] request.getCookies()  : 接收cookie

3.1.3 Cookie原理

1)服务器创建cookie对象,把会话数据存储到cookie对象中。

new Cookie("name","value");

2)  服务器发送cookie信息到浏览器

 response.addCookie(cookie);

举例: set-cookie: name=eric  (隐藏发送了一个set-cookie名称的响应头)

3)浏览器得到服务器发送的cookie,然后保存在浏览器端。

4)浏览器在下次访问服务器时,会带着cookie信息

举例: cookie: name=eric  (隐藏带着一个叫cookie名称的请求头)

5)服务器接收到浏览器带来的cookie信息

 request.getCookies();

3.1.4 Cookie的细节

1)void setPath(java.lang.String uri)   :设置cookie的有效访问路径。有效路径指的是cookie的有效路径保存在哪里,那么浏览器在有效路径下访问服务器时就会带着cookie信息,否则不带cookie信息。

2)void setMaxAge(int expiry) : 设置cookie的有效时间。

正整数:表示cookie数据保存浏览器的缓存目录(硬盘中),数值表示保存的时间。

负整数:表示cookie数据保存浏览器的内存中。浏览器关闭cookie就丢失了!!

零:表示删除同名的cookie数据

3)Cookie数据类型只能保存非中文字符串类型的。可以保存多个cookie,但是浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。

3.2 Session

3.2.1 引入

Cookie的局限:

   1)Cookie只能存字符串类型。不能保存对象

   2)只能存非中文。

   3)1个Cookie的容量不超过4KB。

如果要保存非字符串,超过4kb内容,只能使用session技术!!!

Session特点:会话数据保存在服务器端。(内存中)

3.2.2 Session技术核心

HttpSession类:用于保存会话数据

  1)创建或得到session对象

HttpSession getSession() 

 HttpSession getSession(boolean create) 

2)设置session对象

void setMaxInactiveInterval(int interval)  设置session的有效时间

void invalidate()      销毁session对象

 java.lang.String getId()  得到session编号

 3)保存会话数据到session对象

void setAttribute(java.lang.String name, java.lang.Object value)  保存数据

 java.lang.Object getAttribute(java.lang.String name)  获取数据

void removeAttribute(java.lang.String name) 清除数据

3.2.3 Session原理

问题: 服务器能够识别不同的浏览者!!!

现象:

前提: 在哪个session域对象保存数据,就必须从哪个域对象取出!!!!

浏览器1:(给s1分配一个唯一的标记:s001,把s001发送给浏览器)

1)创建session对象,保存会话数据

HttpSession session = request.getSession();   --保存会话数据 s1

 浏览器1  的新窗口(带着s001的标记到服务器查询,s001->s1,返回s1)  

 1)得到session对象的会话数据

HttpSession session = request.getSession();   --可以取出  s1

新的浏览器1:(没有带s001,不能返回s1)

 1)得到session对象的会话数据

   HttpSession session = request.getSession();   --不可以取出  s2

浏览器2:(没有带s001,不能返回s1)

1)得到session对象的会话数据

HttpSession session = request.getSession();  --不可以取出  s3

代码解读:HttpSession session = request.getSession();

1)第一次访问创建session对象,给session对象分配一个唯一的ID,叫JSESSIONID

new HttpSession();

2)把JSESSIONID作为Cookie的值发送给浏览器保存

Cookie cookie = new Cookie("JSESSIONID", sessionID);

response.addCookie(cookie);

3)第二次访问的时候,浏览器带着JSESSIONID的cookie访问服务器

4)服务器得到JSESSIONID,在服务器的内存中搜索是否存放对应编号的session对象。

if(找到){

           return map.get(sessionID);

            }

            Map<String,HttpSession>]

            <"s001", s1>

            <"s001,"s2>

5)如果找到对应编号的session对象,直接返回该对象

 6)如果找不到对应编号的session对象,创建新的session对象,继续走1的流程

结论:通过JSESSIONcookie值在服务器找session对象!!!!!

3.2.4 Sesson细节

1)java.lang.String getId()  : 得到session编号

 2)两个getSession方法:

 getSession(true) / getSession()  : 创建或得到session对象。没有匹配的session编号,自动创建新的session对象。

getSession(false):  得到session对象。没有匹配的session编号,返回null

  3)void setMaxInactiveInterval(int interval)  : 设置session的有效时间

                 session对象销毁时间:

                          3.1 默认情况30分服务器自动回收

                           3.2 修改session回收时间

                            3.3 全局修改session有效时间

                                                            

<!-- 修改session全局有效时间:分钟 -->

    <session-config>

       <session-timeout>1</session-timeout>

    </session-config>

                        3.4.手动销毁session对象

                            void invalidate()     : 销毁session对象

 4)如何避免浏览器的JSESSIONID的cookie随着浏览器关闭而丢失的问题

                                           

/**

        * 手动发送一个硬盘保存的cookie给浏览器

        */

       Cookie c = new Cookie("JSESSIONID",session.getId());

       c.setMaxAge(60*60);

       response.addCookie(c);

  总结:

           1)会话管理: 浏览器和服务器会话过程中的产生的会话数据的管理。

           2)Cookie技术:

                       new Cookie("name","value")

                       response.addCookie(coookie)

                       request.getCookies()

           3)Session技术

                       request.getSession();

                       setAttrbute("name","会话数据");

                        getAttribute("会话数据")

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值