24.整理JavaWeb

原生JDBC的操作数据库的流程

  1. Class.forName()加载数据库连接驱动
  2. DriverManager.getConnection()获取数据连接对象
  3. 根据SQL获取sql会话对象,有两种方式Statement和PreparedStatement
  4. 执行SQL,执行SQL前如果有参数值就设置参数值setXXX()
  5. 处理结果集,关闭结果集,关闭会话,关闭连接

基础代码:

public static Connection getConnection() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/mydb1";
        return DriverManager.getConnection(url, "root", "123");
    }
    @Test
    public void insert() throws Exception {
        Connection con = getConnection();
        Statement stmt = con.createStatement();
        String sql = "insert into user values('zhangSan', '123')";
        stmt.executeUpdate(sql);
        System.out.println("插入成功!");
    }
    @Test
    public void update() throws Exception {
        Connection con = getConnection();
        Statement stmt = con.createStatement();
        String sql = "update user set password='456' where username='zhangSan'";
        stmt.executeUpdate(sql);
        System.out.println("修改成功!");
    }
    @Test
    public void delete() throws Exception {
        Connection con = getConnection();
        Statement stmt = con.createStatement();
        String sql = "delete from user where username='zhangSan'";
        stmt.executeUpdate(sql);
        System.out.println("删除成功!");
    }
    @Test
    public void query() throws Exception {
        Connection con = getConnection();
        Statement stmt = con.createStatement();
        String sql = "select * from user";
        ResultSet rs = stmt.executeQuery(sql);
        while(rs.next()) {
            String username = rs.getString(1);
            String password = rs.getString(2);
            System.out.println(username + ", " + password);
        }
    }

代码规范化(关闭结果集,会话,连接):

@Test
public void query() {
        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
                con = getConnection();
                stmt = con.createStatement();
                String sql = "select * from user";
                rs = stmt.executeQuery(sql);
                while(rs.next()) {
                        String username = rs.getString(1);
                        String password = rs.getString(2);
                        System.out.println(username + ", " + password);
                }
        } catch(Exception e) {
                throw new RuntimeException(e);
        } finally {
                try {
                        if(rs != null) rs.close();
                        if(stmt != null) stmt.close();
                        if(con != null) con.close();
                } catch(SQLException e) {}
        }
}

为什么要使用PreparedStatement

  • PreparedStatement接口继承于Statement,其实例包含已经编译的sql语句,所以执行速度要比Statement更快(db具有缓存机制,相同的预编译语句再次被调用不会再次需要编译),并且它作为子类继承了Statement所有的功能
  • Statement需要不断的拼接但是PreparedStatement不会,提高了代码的可读性和可维护性
  • 最重要的一点是它可以防止sql注入问题,极大程度提高了安全性

http长连接和短连接的区别

  • HTTP协议有HTTP/1.0版本和HTTP/1.1版本。HTTP1.1默认保持长连接(HTTP persistent connection,也翻译为持久连接),数据传输完成了保持TCP连接不断开(不发RST包、不四次握手),等待在同域名下继续用这个通道传输数据;相反的就是短连接。
  • 在 HTTP/1.0 中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。从HTTP/1.1起,默认使用的是长连接,用以保持连接特性。

http常见的状态码

  • 200 ok
  • 301 Moved Permanent,请求的URL已经移走了,Response中应该携带一个Location URL,说明资源现在所处的位置
  • 302 重定向
  • 400 Bad Request 客户端请求有语法错误,不能被服务器所理解
  • 401 Unauthorized 请求未经授权
  • 403 Forbidden 服务器收到请求 但是拒绝提供服务
  • 404 Not Found 请求资源不存在
  • 500 Internal Server Error 服务器发生不可预期的错误
  • 503 Server Unavailable 服务器当前不能处理客户端请求,一段时间后可能恢复正常

Get和Post的区别

  • get请求的数据会附加在URL之后(就是把数据防止在HTTP协议头中),使用?分割URL和传输数据,参数之间使用&相连,Post请求提交的数据会放在HTTP包的包体中
  • get方式提交的数据由于浏览器对URL的长度的限制,所以提交的数据根据不同的浏览器也会有不同的上限(比如IE是2083字节),在具体的协议中Get请求的长度其实是没有限制的,Post就更不用说了
  • Post请求的安全性比Get高,使用Get请求提交密码和账号将明文出现在URL上,别人就可以拿到你的 私密信息,除此之外Get提交数据还有可能造成Cross-site request forgery攻击
  • "Get是向服务器发索取数据的一种请求,Post是向服务器提交数据的一种请求"这句话是错误的,两者只是发送机制不同,并不是一个取一个发
  • GET请求会被浏览器主动cache,而POST不会,除非手动设置
  • GET请求只能进行url编码,而POST支持多种编码方式
  • GET在浏览器回退时是无害的,而POST会再次提交请求

重定向和请求转发的区别

转发过程: 客户浏览器发送http请求----》web服务器接受此请求–》调用内部的一个方法在容器内部完成请求处理和转发动作----》将目标资源发送给客户;在这里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的转发行为是浏览器只做了一次访问请求。

重定向过程: 客户浏览器发送http请求----》web服务器接受后发送302状态码响应及对应新的location给客户浏览器–》客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址----》服务器根据此请求寻找资源并发送给客户。在这里 location可以重定向到任意URL,既然是浏览器重新发出了请求,则就没有什么request传递的概念了。在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的。重定向行为是浏览器做了至少两次的访问请求的。

本质区别:转发是服务器行为,重定向是客户端行为

重定向的特点:两次请求,浏览器地址发生变化,可以访问自己web之外的资源,传输的数据会丢失

请求转发特点:一次请求,浏览器地址不变,访问的是自己本身的web资源,传输的数据不会丢失

Cookie和Session的区别

cookie和session都是用来跟踪浏览器用户身份的会话方式, cookie数据保存在客户端,session数据保存在服务端。

  • Cookie是web服务器发送给浏览器的一块信息,浏览器会在本地一个文件中给每个web服务器存储Cookie,以后浏览器再给特定的web服务器发送请求时,同时会发送所有为服务器储存的cookie
  • 在这里插入图片描述
  • Session是存储在web服务器端的一块信息,Session对象存储特定用户会话所需的属性以及配置信息,当用户在应用程序的web页之间跳转的时候,存储在session对象中的变量不会丢失,而是在整个用户会话中一致存在下去; 简单的说,当你登陆一个网站的时候,如果web服务器端使用的是session,那么所有的数据都保存在服务器上,客户端每次请求服务器的时候会发送当前会话sessionid,服务器根据当前sessionid判断相应的用户数据标志,以确定用户是否登陆或具有某种权限。由于数据是存储在服务器上面,所以你不能伪造。
  • 在这里插入图片描述

其区别在于:

  1. cookie数据存放在客户的浏览器上,session数据放在服务器上
  2. cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session
  3. session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用COOKIE
  4. 单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能超过3K。
  5. 所以:将登陆信息等重要信息存放为SESSION;其他信息如果需要保留,可以放在COOKIE中
     

单点登录如何实现?

这里写图片描述

在单点登录的过程中,如果cookie被禁用了怎么办

单点登录的原理是后端生成一个sessionID,然后设置到cookie,后面的所有请求浏览器都会带上cookie,然后服务端从cookie里获取sessionID,再查询到用户信息。所以,保持登录的关键不是cookie,而是通过cookie保存和传输的sessionID,其本质是能获取用户信息的数据。除了cookie,还通常使用HTTP请求头来传输。但是这个请求头浏览器不会像cookie一样自动携带,需要手工处理。

jsp和servlet有什么区别

  • JSP的本质就是Servlet,JVM只能识别java类,不能识别JSP代码,Web容器将JSP代码变异成能够识别的Java类
  • JSP更擅长与页面显示,Servlet更擅长逻辑控制
  • Servlet中没有内置对象,JSP的内置对象都是通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到
  • Jsp是Servlet的一种简化,使用Jsp只需要完成程序员需要输出到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器完成。而Servlet则是个完整的Java类,这个类的Service方法用于生成对客户端的响应

JSP的内置对象有哪些

  • request:封装客户端的请求,其中包含来自GET或POST请求的参数;
  • response:封装服务器对客户端的响应;
  • pageContext:通过该对象可以获取其他对象;
  • session:封装用户会话的对象;
  • application:封装服务器运行环境的对象;
  • out:输出服务器响应的输出流对象;
  • config:Web应用的配置对象;
  • page:JSP页面本身(相当于Java程序中的this);
  • exception:封装页面抛出异常的对象

jsp的四种作用域

  • page代表与一个页面相关的对象和属性。
  • request代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web组件;需要在页面显示的临时数据可以置于此作用域。
  • session代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中。
  • application代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。

Session的工作原理

session是一个存在服务器上的类似于一个散列表格的文件。里面存有我们需要的信息,在我们需要用的时候可以从里面取出来。类似于一个大号的map吧,里面的键存储的是用户的sessionid,用户向服务器发送请求的时候会带上这个sessionid。这时就可以从中取出对应的值了

如果禁用了Cookie,Session还能用吗?

Cookie与 Session,一般认为是两个独立的东西,Session采用的是在服务器端保持状态的方案,而Cookie采用的是在客户端保持状态的方案。但为什么禁用Cookie就不能得到Session呢?因为Session是用Session ID来确定当前对话所对应的服务器Session,而Session ID是通过Cookie来传递的,禁用Cookie相当于失去了Session ID,也就得不到Session了

如果禁用了Cookie的解决办法:

  • 设置php.ini配置文件中的“session.use_trans_sid = 1”,或者编译时打开打开了“--enable-trans-sid”选项,让PHP自动跨页传递Session ID。
  • 手动通过URL传值、隐藏表单传递Session ID。
  • 用文件、数据库等形式保存Session ID,在跨页过程中手动调用。

如何避免sql注入问题

  • PreparedStatement
  • 使用正则表达式过滤传入的参数
  • 字符串过滤
  • JSP中添加判断代码
  • Mybatis中使用#而不是$

简述tcp和udp的区别

  • TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
  • TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。
  • Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信
  • 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
  • TCP对系统资源要求较多,UDP对系统资源要求较少

为什么TCP要三次握手,两次握手不行吗?

为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤。

如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认

OSI七层参考模型都有哪些 TCP/IP实现了哪些层(红色)

  • 应用层:网络服务与最终用户的一个接口。
  • 表示层:数据的表示、安全、压缩。
  • 会话层:建立、管理、终止会话。
  • 传输层:定义传输数据的协议端口号,以及流控和差错校验。
  • 网络层:进行逻辑地址寻址,实现不同网络之间的路径选择。
  • 数据链路层:建立逻辑连接、进行硬件地址寻址、差错校验等功能。
  • 物理层:建立、维护、断开物理连接。

TCP/IP其实是把应用表示和会话层合在一起作为应用空间合并为应用层

TCP三次握手

三次握手(Three-way Handshake)其实就是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号(ISN)为后面的可靠性传送做准备。实质上其实就是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号,交换TCP窗口大小信息。

三次握手的其中一个重要功能是客户端和服务端交换 ISN(Initial Sequence Number),以便让对方知道接下来接收数据的时候如何按序列号组装数据。如果 ISN 是固定的,攻击者很容易猜出后续的确认号,因此 ISN 是动态生成的

其具体过程如下,一开始客户端处于Closed状态,服务器处于Listen状态

第一次握手:客户端发送一个SYN报文,并且指明客户端的初始化序列号(图中的seq,也就是ISN),此时客户端处于SYN_SENT状态,首部的同步SYN=1,初始序列号seq=x.SYN=1的报文不能携带数据,但要消耗掉一个序列号

第二次握手:服务器收到客户端发送的报文后,会恢复自己的SYN报文作为回答,并且也指定了自己的初始化序列号,同时会把客户端的序列号+1作为ACK的值,表示自己已经收到了客户端的SYN报文,此时服务此处于SYN_RCVD状态 

第三次握手:客户端收到SYN报文之后,会发送一个ACK报文,也是一样的把服务器的ISN+1作为ACK的值,表示已经收到了服务端的报文,此时客户端处于ESTABLISHED的状态,服务器收到ACK报文之后,也变为ESTABLISHED状态,此时双方已经建立起了连接

ä¸æ¬¡æ¡æ.png

 三次握手的过程可以携带数据吗

第一次和第二次不可以,第三次可以携带数据,假如第一次握手可以携带数据,如果有人要恶意攻击服务器,那他每次都在第一次握手的SYN报文中放入大量的数据,因为攻击者根本就不理服务器的接受,发送能力是否正常,然后疯狂重复发送SYN报文的话,会让服务器花费很多时间,内存空间来接受这些报文

对于第三次的话,客户端已经是ESTABLISHED状态了,对于客户端来说连接已经建立起来了,并且也直到服务器的接受发送能力是正常的了,所以能携带数据也没有什么毛病

TCP四次挥手

四次挥手是因为TCP的半关闭造成的,所谓的半关闭,其实就是TCP提供了连接的一端在结束他的发送后还能接收来自另一端数据的能力

第一次挥手:客户端发送一个FIN报文,报文中会指定一个序列号,此时客户端处于FIN_WAIT1状态,即发出连接释放报文段(FIN=1,序列号seq=u),并且停止再阿松数据,主动关闭TCP连接,进入FIN_WAIT1状态(终止等待1)等待服务端的确认

第二次挥手:服务端收到FIN之后,会发送ACK报文,把客户端的序列号值+1作为ACK报文的序列号值,表明已经收到了客户端的保卫呢,此时服务端处于CLOSE_WAIT状态

第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发送FIN报文,并且指定一个学列好,此时服务端处于LAST_ACK的状态

第四次挥手:客户端收到FIN报文之后,一样发送一个ACK作为应答,并且把服务端的序列号+1作为自己ACK报文的序列号值,此时客户端处于TIME_WAIT状态,需要过一整子以确保服务端收到自己的ACK报文之后(等待2MSL)才会进入Closed状态,服务端收到ACK报文之后就关闭连接了处于CLOSED状态

image.png

挥手为什么需要四次,三次不行吗?

 因为当服务端收到客户端的SYN连接请求报文之后,可以直接发送SYN+ACK报文,其中ACK是用来应答的,SYN是用来同步的,但是关闭连接的时候,当服务端收到FIN报文的时候,很可能不会立即关闭SOCKET,所以只能先回复一个ACK,告诉客户端你的FIN包我收到了,只有等到服务端所有的报文都发送完了,才可以发送FIN包,因此不能一起发送,所以需要四次挥手

第四次挥手释放连接的时候,等待2MSL的意义

MSL是Maximum Segment Lifetime的英文缩写,可译为“最长报文段寿命”,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。

网络有可能是不可靠的,有可能最后一个ACK丢失了,这个时间就是用来重发可能丢失的ACK报文的

如何实现跨域

public class MyCorsConfiguration {
    @Bean
    public CorsWebFilter corsWebFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
 
        CorsConfiguration corsConfiguration = new CorsConfiguration();
 
        // 配置跨域
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.setAllowCredentials(true);
 
        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsWebFilter(source);
    }
}

监听器,过滤器,拦截器,servlet的区别

web.xml的加载顺序是:context-param->listener->filter->servlet

监听器(listener):

  • 在request,session,application三个对象创建消亡或者往其中增删改属性时自动执行指定代码的功能组件
  • 生命周期:随web应用的启动而启动,只初始化一次,随web应用的停止而销毁
  • 作用:做一些初始化的内容添加工作,设置一些基本的内容,比如一些参数或者固定的对象等

 过滤器(filter):

  • 拦截请求,filter能在一个请求到达控制层之前预处理用户的请求,也可以在离开控制层时处理http响应,进行一些设置以及逻辑判断,然后再传入servelt或者struts的action进行业务逻辑,基于函数回调
  • 生命周期:随web应用启动而启动,,只初始化一次,以后就可以拦截相关的请求,只有当你的web应用停止或者重新部署的时候才销毁
  • 作用:对请求或者响应进行统一设置统一编码,简化操作,进行逻辑判断,比如用户是否已经登录,有无权限访问页面,过滤掉非法的url

拦截器(interceptor):

拦截器是在面向切面编程中使用的,基于java的反射机制,在一个业务逻辑前后调用另一个方法

servelt:

是一种运行服务器端的java程序,具有独立于平台和协议的特性,并且可以动态的生成web页面,它工作在客户端请求和服务器响应的中间层

当在浏览器输入一个网址,所需要经理的全部过程

服务器上输入一个地址:www.baidu.com后回车,浏览器会根据输入的URL到DNS服务器查询对应的IP地址和域名;返回到客户端,客户端在根据查找到的域名和IP建立TCP连接,连接到对应的百度服务器,向服务器发送HTTP Request(请求),服务端接受到请求包并进行处理,并调用自身服务,返回HTTP Response(响应) 客户端接到响应的时候开始渲染这个Response包里的主体body,等接受完所有内容后自动断开该TCP连接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值