javaweb




javaweb

1.基础概念

  • 静态web

    • html,css
    • 提供给所有人看的数据始终不会改变
  • 动态web

    • 数据始终都在改变,每个人在不同时间不同地点看到的数据不同(淘宝之类的)

    • Servlet/jsp,asp,php

      在Java中动态资源开发技术统称为javaweb

1.2 web程序

能通过浏览器访问到的程序

  • 我们能访问的任何资源,都存在这个某一个计算机上

  • URL

  • 这个统一的web资源都会放在同一个文件下,web应用程序--》Tomcat

  • 一个web应用由多部分组成(静态web,动态web)

    • html,css,js
    • jsp,servlet
    • java程序
    • jar包
    • 配置文件

    web应用程序写好后想要被访问到:需要一个服务器来统一管理

1.3丶静态web

  • 静态页面的缺点:
    • Web页面无法动态更新,所有用户看到的都是同一个页面
    • 它无法与数据库交互(数据无法持久化,用户无法交互)

1.4丶动态web

缺点:

  • 动态资源出现问题就要重新编写我们的后台程序,重新发布
    • 停机维护

优点:

  • Web页面可以动态更新,所有用户看到的都是同一个页面
  • 它可以与数据库交互(数据能持久化,用户能交互)

2.Tomcat

2.1丶Tomcat基础

(1)Tomcat目录

(2)丶启动和配置

访问测试:文本是用超链接的方法,将各种不同空间的文字信息组织在一起的网状文本

  • 80
  • Https:安全的
    • 443
  • 3.2 两个时代

    • http1.0
      • HTTP/1.0 客户端与服务器连接后,一次只能获取一个web资源
    • http2.0
      • HTTP/1.1 客户端与服务器连接后,一次能获取多个web资源

    3.3 请求

    客户端--发请求(Request)--服务器

    百度为例:

    请求 URL: https://www.baidu.com/	域名
    请求方法: GET					   请求方式 :Get/Post
    状态代码: 200 OK					状态码
    远程地址: 14.215.177.39:443			主机Ip地址和端口号
    
    Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9			能接收的资源
    Accept-Encoding: gzip, deflate, br					接收的编码
    Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6		语言
    Cache-Control: max-age=0
    Connection: keep-alive
    

    1.请求行

    • 请求行中的请求方式:GET
    • 有哪些方式:GET,Post等
      • get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
      • Post:请求能够携带的参数比较多,大小没限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效

    2.消息头:

    Accept:				告诉浏览器,它所支持的数据类型
    Accept-Encoding: gzip, deflate, br					接收的编码
    Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6		语言
    Cache-Control: max-age=0			缓存控制
    Connection: keep-alive				告诉浏览器,请求完成是断开还是连接
    Host:		主机
    

    3.4 响应

    服务器--响应(Respond)--客户端

    Cache-Control: private					缓存控制
    Connection: keep-alive					连接
    Content-Encoding: gzip					编码
    Content-Type: text/html;charset=utf-8	类型
    

    1.响应体

    Accept:				告诉浏览器,它所支持的数据类型
    Accept-Encoding: gzip, deflate, br					接收的编码
    Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6		语言
    Cache-Control: max-age=0			缓存控制
    Connection: keep-alive				告诉浏览器,请求完成是断开还是连接
    Host:		主机
    Refresh:		告诉客户端,多久刷新一次
    location:让网页重新定位
    

    2.响应状态码(重点):

    200:请求成功

    3**:请求重定向

    • 重定向:你重新到我给你的新位置去;

    4xx:找不到资源 404

    • 资源不存在

    5xx:服务器代码错误 500 502:网关错误

    3.5 常见面试题

    当你的浏览器地址栏输入并回车的一瞬间到页面能够展示回来,经历了什么?

    4.Maven

    为什么要学这个技术?

    1. 在javaweb开发中,需要大量的导包,手动导入太麻烦
    2. 在此基础上Maven诞生了!

    4.1 Maven项目架构管理工具

    我们目前只用来导包

    Maven核心思想:约定大于配置

    • 有约束,不要去违反

    Maven会规定你该如何去编写我们的java代码,必须按照这个规范来;

    4.2 配置环境

    在环境变量中,配置如下配置

    • M2_HOME maven目录下的bin目录
    • MAVEN_HOME maven的目录
    • 在系统的path中配置 %MAVEN_HOME%\bin

    4.3 阿里云镜像

    • 镜像:morris

      • 加速我们的下载
    • 国内推荐阿里云镜像

      
          nexus-aliyun
          central
          Nexus aliyun
      http://maven.aliyun.com/nexus/content/groups/public
      
      

    4.4 本地仓库

    在本地的仓库就会有远程仓库

    建立一个本地仓库:localRepository

    D:\Maven\apache-maven-3.8.4\maven-repo
    

    4.5 在Idea使用Maven

    1. 创建一个Maven项目

    2.此时的Maven仓库多了什么东西?

    3.IDEA里的Maven设置

    4.6.不勾选模板创建一个普通Maven

    4.7 标记文件夹功能

    4.8 在Maven中配置Tomcat

    必须的配置:为什么会有这个问题,因为我们访问一个网站是需要一个文件夹的,IDEA不会给默认**

    4.9 pom.xml(Maven的核心配置文件)

    在配置文件中导入其他包的依赖,Maven的高级之处在于它能够帮你导入这个jar包所依赖的其他jar包

    Maven遇到的问题:

    
    
        
            
                src/main/resources
                
                    **/*.properties
                    **/*.xml
                
                true
            
            
                src/main/java
                
                    **/*.properties
                    **/*.xml
                
                true
            
        
    
    
    

    5.Servlet

    5.1 基础概念

    • Servlet是一种实现动态Web的一门技术

    • 本质:servlet其实就是对请求和响应的封装

    • 你想实现一个Servlet,必须有两个步骤:

      • 编写一个类实现Servlet接口
      • 将这个java类部署到服务器上

      把实现了Servlet接口的java程序叫做 Servlet

    5.2 HelloServlet

    1. 构建一个普通的Maven项目,删掉里面的src目录,用户我们的学习就在这个项目里面建立Moudel,这个空工程的就是Maven主工程

    2. 关于Maven的父子工程的理解:

      1. 父项目会有:

        
                Servlet-01
            
        

        2.子项目会有:

        
         JavaWeb-01-Maven2
          com.LiuDeHen
          1.0-SNAPSHOT
        
        

        注意:这里子项目中没有parent的话后面在子项目里调用包时可能会因为子项目没有指向父项目,而需要用到父项目的包二无法自动导包

      ? 3.就跟继承一样,父项目的java子项目可以直接用

      son extends father
      
    3. Maven环境优化

      1. 修改子项目web.xbl为最新的

        <?xml version="1.0" encoding="UTF-8"?>
               
                
        
      2. 将maven的结构搭建完整(webapps里一般要有java源目录和resources资源目录

    4. 编写一个Servlet程序

      1. 编写一个普通类

      2. 实现Servlet接口,这里我们直接继承HttpServelt

        1. Servlet接口有两个实现类,HttpServlet和GenericServlet
        public class HelloServlet extends HttpServlet {
        //    由于Get和Post只是实现请求的不同方式,可以相互调用,业务逻辑都一样
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                PrintWriter writer = resp.getWriter();    //响应流
                writer.write("helloServlet");
            }
        
            @Override
            protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                super.doPost(req, resp);
            }
        

        3.为什么要继承HttpServlet

        5.编写servlet映射

        ? 为什么需要映射勒,因为servlet就是一个java程序而已,我们想要通过浏览器访问到,必须通过web服务器,所以我们就需要再web服务器里注册映射我们写的servlet,并且再给浏览器一个能够访问的路径

        
          
        
              hello
        
              com.LiuDeHen.servlet.HelloServlet
          
        
            
                hello
        
                /hello
            
        

        运行后会加载到webapp这个包下,然后就会解析web.xml(下面这个图),就会访问到servlet程序

        ? 上图中访问地址前必须必须要有/

    6.配置Tomcat

    注意:配置项目发布路径就可以了

    7.测试

    启动Tomcat会出现一个target

    5.3 Servlet原理

    5.4 Mapping问题

    1. 一个Servlet指定一个映射

       
              hello
      
              /hello
          
      
    2. 一个Servlet指定多个映射

      
              hello
      
              /hello
          
          
              hello
              
              /hello1
          
      
    3. 默认请求路径

      
              hello
              
              /*
          
      
    4. 使用通配符

          
              hello
              
              /hello/*
          
      
      
    5. 指定一些前缀后缀

     
            hello
            
            *.lc
        
    

    6.优先级问题

    ? 假如我定义了一个404报错Servlet,使用的是通配符地址,那么我访问/hello,是访问的hello页面还是404页面?

    肯定是hello页面,固有的映射路径优先级最高,如果找不到才会找默认路径

    5.5 ServletContext

    Web服务器在启动的时候,它会为每一个Web程序都创建一个ServletContext对象,它代表了当前的Web应用,(一个web只有一个ServetContext

    1 共享数据

    我在这个Servlet中保存的数据,可以在另一个Servlet拿到

    注意:响应时要设置响应编码格式不然会出现?

    在当前Servlet设置		
        					ServletContext servletContext = this.getServletContext();
            				servletContext.setAttribute("User","你好");
    在另外一个Servlet获取
            resp.setContentType("text/html");
            resp.setCharacterEncoding("GBK");
            ServletContext servletContext = this.getServletContext();
            Object user = servletContext.getAttribute("User");
            PrintWriter writer = resp.getWriter();
            writer.write(user.toString());
    

    2 获取初始化参数

    设置初始化需要的配置文件

    
        url
        jdbc:mysql//localhost:3306/lc
    x
    
    获取:		
    ServletContext servletContext = this.getServletContext();
            String s=servletContext.getInitParameter("url");
            resp.getWriter().print(s);
    

    3 请求转发

      ServletContext servletContext = this.getServletContext();
      RequestDispatcher dispatcher = servletContext.getRequestDispatcher("/hello");//转发地址
      dispatcher.forward(req,resp);           //调用forword实现请求转发
    

    这个只是转发,并不会改变我们的地址

    4 读取资源文件

    Properties

    • 在java目录下新建properties

    • 在resource下新建properties

      发现:都被导包到同一个路径下(target里的)classes,俗称为classpath

      思路:我们只需要给一个流

      username:root
      pwd:lc20010725
      
       InputStream stream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.Properties");
              Properties p=new Properties();
              p.load(stream);
              String user = p.getProperty("username");
              String pwd = p.getProperty("pwd");
              resp.getWriter().print(user+":"+pwd);
      

      注意:我们读的文件是target里导出的文件

    5.6 HttpServletResponse

    web服务器接收到客户端的请求,针对这个请求,会分别创建一个代表请求的HttpServletRequest,代表响应的HttpServletResponse

    • 如果要获取客户端请求过来的参数:找HttpServletRequest
    • 如果要获取服务器响应的信息:找HttpServletResponse

    常用分类:

    1 向客户端发送消息(ServletResponse里的):

    ServletOutputStream getOutputStream() throws IOException;
    PrintWriter getWriter() throws IOException;
    

    2 向浏览器发送响应头的方法:

    ServletResponse里的:
    	void setCharacterEncoding(String var1);
    
        void setContentLength(int var1);
    
        void setContentLengthLong(long var1);
    
        void setContentType(String var1);
        
    HttpServletResponse里的:
    	void sendRedirect(String var1) throws IOException;
    
        void setDateHeader(String var1, long var2);
    
        void addDateHeader(String var1, long var2);
    
        void setHeader(String var1, String var2);
    
        void addHeader(String var1, String var2);
    
        void setIntHeader(String var1, int var2);
    
        void addIntHeader(String var1, int var2);
    
    

    3 状态码:

    int SC_CONTINUE = 100;
        int SC_SWITCHING_PROTOCOLS = 101;
        int SC_OK = 200;
        int SC_CREATED = 201;
        int SC_ACCEPTED = 202;
        int SC_NON_AUTHORITATIVE_INFORMATION = 203;
        int SC_NO_CONTENT = 204;
        int SC_RESET_CONTENT = 205;
        int SC_PARTIAL_CONTENT = 206;
        int SC_MULTIPLE_CHOICES = 300;
        int SC_MOVED_PERMANENTLY = 301;
        int SC_MOVED_TEMPORARILY = 302;
        int SC_FOUND = 302;
        int SC_SEE_OTHER = 303;
        int SC_NOT_MODIFIED = 304;
        int SC_USE_PROXY = 305;
        int SC_TEMPORARY_REDIRECT = 307;
        int SC_BAD_REQUEST = 400;
        int SC_UNAUTHORIZED = 401;
        int SC_PAYMENT_REQUIRED = 402;
        int SC_FORBIDDEN = 403;
        int SC_NOT_FOUND = 404;
        int SC_METHOD_NOT_ALLOWED = 405;
        int SC_NOT_ACCEPTABLE = 406;
        int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
        int SC_REQUEST_TIMEOUT = 408;
        int SC_CONFLICT = 409;
        int SC_GONE = 410;
        int SC_LENGTH_REQUIRED = 411;
        int SC_PRECONDITION_FAILED = 412;
        int SC_REQUEST_ENTITY_TOO_LARGE = 413;
        int SC_REQUEST_URI_TOO_LONG = 414;
        int SC_UNSUPPORTED_MEDIA_TYPE = 415;
        int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
        int SC_EXPECTATION_FAILED = 417;
        int SC_INTERNAL_SERVER_ERROR = 500;
        int SC_NOT_IMPLEMENTED = 501;
        int SC_BAD_GATEWAY = 502;
        int SC_SERVICE_UNAVAILABLE = 503;
        int SC_GATEWAY_TIMEOUT = 504;
        int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
    
    

    常见应用(*重定向):

    1. 在客户端输入数据
    2. 下载文件
      resp.setCharacterEncoding("UTF-8");
      resp.setContentType("txt/html");
      //        1.找到资源路径
      //        相对路径
      //        String path = this.getServletContext().getRealPath("/WEB-INF/classes/1.txt");
      //        绝对路径
              String path="D:\\JavaWeb-01-Maven2\\Response\\target\\Response\\WEB-INF\\classes\\1.png";
      //        2.获取文件名
              String filename = path.substring(path.lastIndexOf("\\") + 1);
      //        3.想办法让浏览器支持我们下载
              resp.setHeader("Content-disposition","attachment;filename"+ URLEncoder.encode(filename,"UTF-8"));
      //        4.获取下载文件的流
              FileInputStream in = new FileInputStream(path);
      //        5.创建一个缓冲区
              int len=0;
              byte[] buffer = new byte[1024];
      //        6.获取输出流对象
              ServletOutputStream out = resp.getOutputStream();
      //        7.将OutputStream流写到缓存区,再使用响应的输出流将缓存流数据输出到客户端
      //          从输入流中读取一定数量的字节,并将其存储在缓冲区数组
              while ((len=in.read(buffer))>0){
                      out.write(buffer,0,len);
              }
              out.close();
              in.close();
      
      3.验证码功能:

      ? 就不写了,我们要知道响应的传给浏览器信息的时候,编码格式,文件格式,包括上面的下载,也就是要设置它的响应头的内容

      4.实现重定向(重点):

      b收到一个来自客户端a的请求后,它会通知a去访问另外一个web资源c,这就叫重定向

      常见场景:

      • 用户登录

        void sendRedirect(String var1) throws IOException;
        

        测试:

        //        resp.setHeader("location","/Response_war/down");
        //        resp.setStatus(302);
        //       重定向就是由上面两步构成
                resp.sendRedirect("/Response_war/down");
        

        面试题:请你谈谈重定向(拽)和转发(怂)的区别?

        拽哥叫别人自己去,怂逼帮它去

        相同点:

        • 都会跳转页面

        不同点:

        • 转发不改变地址 307

        • 重定向改变地址 302

          总结:转发是一次请求,重定向两次,转发是服务器内部完成,而重定向是在客户端完成

    5.7 HttpServletRequest

    概念:

    HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,Http请求中的所有信息都会封装到HttpServletRequest,通过HttpServletRequest可以获取到客户端的所有信息

    应用:

    1.获取前端的传递参数

     String username = req.getParameter("username");
     String pwd = req.getParameter("pwd");
     String[] hobbies = req.getParameterValues("hobbies");
    

    2.请求转发

     req.getRequestDispatcher("/Succes.jsp").forward(req,resp);
    

    6.Cookie和Session

    6.1 会话

    会话:用户打开一个浏览器,点开很多超链接,访问不同web资源,到关闭浏览器,这就是会话

    有效会话:当一个同学来过教室,下次再来教室里的时候,其他同学就知道你曾经来过,称之为有状态会话

    例子:怎么证明你是中国公民

    你 国家

    1.你有身份证 国家给你的身份证

    2.国家数据库里有你信息 国家数据库里有你信息

    那么在网站上怎么证明你来过呢?

    客户端 服务端

    1.当客户端访问服务端的时候,服务端会给客户端一个信件,客户端下次访问带上信件就可以了 Cookie

    2.服务端登记你来过,下次你来的时候自动匹配你 Session

    6.2 保存会话的两种技术

    Cookie

    • 客户端技术(响应,请求)

    Session

    • 服务器技术,利用这个技术就可以保存用户的会话信息?我们可以把数据放到Session中

    6.3 Cookie(饼干,信件)

    站在面向对象的角度

    1. 客户端去获取Cookie

    2. 服务端去响应给客户端Cookie

      //        获取Cookie,因为Cookie是服务端给客户端,所以客户端去获取(面向对象的角度)
              Cookie[] cookies = req.getCookies();
      //			获取cookie 的key值
      		cookies[i].getName()
      //            获取cookie的 value值
         	    cookies[i].getValue()
      //            新建一个cookie
              Cookie cookie = new Cookie("time",System.currentTimeMillis()+"");
      //        设置到期时间
              cookie.setMaxAge(24*60*60);
      //        服务端给客户端一个Cookie
              resp.addCookie(cookie);
      

      Cookie:一般会保存在本地 用户目录下的 Appdate下

    细节:

    • 一个网站Cookie是否有上限!
    • 一个Cookie只能保存一个信息
    • 一个web站点可以给浏览器发送多个Cookie,最多存放20个Cookie
    • Cookie大小上限4kb
    • 浏览器Cookie上限为300

    删除Cookie:

    • 不设置有效期,关闭浏览器,自动失效
    • 设置有效期为0

    6.4 Session

    什么是Session:

    • 服务器会给每一个用户(浏览器)创建一个Session对象

    • 一个Session独占一个浏览器,只要浏览器没有关闭,Session就一直存在

    • 一访问web程序就会产生一个Session,同一个浏览器只有一个Seesion

      //        获取Session
              HttpSession session = req.getSession();
      //        设置Session(设置类型为object,比Cookie广)
              session.setAttribute("Test",new Test(20,"lc","Code"));
      //        获取ID
              String id = session.getId();
      //        判断这个Session是不是新的
              if(session.isNew()){
                  out.write("Session创建成功,ID"+id);
              }else{
                  out.write("Session已经在服务器中存在,ID"+id);
              }
      
      //        获取name为“Test”的Session
              Test T =(Test)session.getAttribute("Test");
      //        移除那个key为Test的session
              session.removeAttribute("Test");
      
      //        手动注销Session
      //        session.invalidate();
      

      移除和注销是不同的,移除了Session还是那个Session,只是那个属性为Test的Session没有了

      //在配置里注销(自动注销):	 
      
              15
      
      

      而注销

    再一次访问,ID不同因为是另外一个Session了

    总结:Session和Cookie的区别
    	1.Cookie是把数据写到用户的客户端
    	2.Session把用户的数据写到服务端(保存重要信息,减少服务器资源的浪费)
    	3.Session对象由服务器创建,cookie也是由服务器创建给客户端
    

    使用场景:

    • 保存一个登录用户的信息
    • 购物车信息
    • 在网站中经常用到的数据保存到Session

    Session的SessionID是服务端响应了一个Cookie给客户端

    7.JSP

    7.1什么是JSP

    Java Server Pages:java服务端页面,也和Servlet一样,用于动态Web技术!

    最大的特点:

    • 写JSP就像在写HTML
    • 区别:
      • HTML只给用户提供静态数据
      • Jsp页面可以嵌入java代码,为用户提供动态数据

    7.2 JSP原理

    思路:JSP到底怎么执行的!

    • 服务器内部工作
      • 发现页面转换成java程序

    JSP只有在被访问时才会转化为java和class文件

    (重)浏览器向服务器发送请求的时候,不管访问你什么资源,其实都是在访问Servlet!

    Jsp最终也会被转换为JAVA程序

    JSP实质上就是一个Servlet

    看JSP源码

    1.判断请求方式

    2.JSP内置对象

        final javax.servlet.jsp.PageContext pageContext;			//页面上下文
    	javax.servlet.http.HttpSession session = null;				//session
        final javax.servlet.ServletContext application;				//applicationContext
        final javax.servlet.ServletConfig config;					//Config配置
        javax.servlet.jsp.JspWriter out = null;						//out输出
        final java.lang.Object page = this;							//当前页面
        HttpServletRequest request									//请求
        HttpServletResponse response								//响应
    

    3.输出页面前的代码

     response.setContentType("text/html; charset=UTF-8");			//设置响应的类型
          pageContext = _jspxFactory.getPageContext(this, request, response,
          			null, false, 8192, true);
          _jspx_page_context = pageContext;
          application = pageContext.getServletContext();
          config = pageContext.getServletConfig();
          out = pageContext.getOut();
          _jspx_out = out;
    
    

    在java代码中:

    java代码会被原封不动的输出

    而HTML代码就会被输出成:

    out.write("\r\n");
    

    7.3 JSP基础语法

    作为java技术的一种扩张,支持java所有的语法,也有自己的一些扩充的语法

    1.JSP表达式

    <%--JSP表达式
    作用:用来将程序的输出,输出到客户端
    <%= 变量或者表达式%>
    --%>
    <%=1+2%>
    
    
    一般用EL表达式替代
    ${} 跟<%=%>等同
    

    2.JSP脚本片段

    <%--JSP脚本片段--%>
    <%
    int a=7;
    out.print("当前a为:"+a);
    %>
    

    3.JSP脚本片段嵌入HTML

    <%--在代码里嵌入HTML代码--%>
    <%
        for (int i = 0; i <3 ; i++) {
    %>
            

    你好刘超

    <%=1%> <% } %> 为什么能怎么写,java代码在转换后还是java代码,而HTML代码会被转换成out.print("你好刘超“);

    4.JSP声明

    <%--JSP声明--%>
    <%!int a=10;
        static {
            int b;
        }
    %>
    
    Jsp声明会被编译到类里,作用域高
    普通<%%>写的带代码都在jsp.java文件里的JspService方法里,
    

    7.4 JSP指令

    <%@ page errorPage="err/500.jsp" %>
    
    <%--指令
    两个页面合二为一
    --%>
    <%@ include file="comom/Header.jsp"%>
    

    我是内容

    <%@ include file="comom/Footer.jsp"%>
    <%--JSP标签 拼接页面实际还是三个页面 --%>

    我是内容

    7.5 9大内置对象及作用域

    作用域:

    • Pagecontext 存东西 保存的东西只在一个页面中有效
    • Request 存东西 保存的东西在这次请求中有效
    • Response
    • Session 存东西 保存的东西在一次会话中(浏览器从开启到关闭)有效
    • Application(ServletContext) 存东西 凌驾于所有Servlet之上,保存的数据在服务器中,从服务器开启到关闭
    • config(ServletConfig)
    • out
    • page
    • exception
    pageContext.setAttribute("1","a");   存东西  保存的东西只在一个页面中有效
    request.setAttribute("2","b");  	 存东西  保存的东西在这次请求中有效
    session.setAttribute("3","c");		 存东西  保存的东西在一次会话中(浏览器从开启到关闭)有效
    application.setAttribute("4","d");   存东西   凌驾于所有Servlet之上,保存的数据在服务器中,从服务器开启到关闭
    

    作用域:

    request: 从客户端向服务端发送请求,产生得数据,用户用完就不用了,比如:看新闻

    session:从客户端向服务端发送请求,产生得数据,用户用完还有用,比如:购物车,登录

    application:从客户端向服务端发送请求,产生得数据,一个用户用完了,另外一个用户还能用到,比如聊天信息

    7.6 JSP标签,JSTL标签和EL表达式

    EL表达式:${}

    • 获取数据

    • 执行运算

    • 获取web开发得常用对学校

      JSP标签

      
          
          
      
      

    JSTL标签

    JSTL标签库是为了弥补HTML得不足

    
    
        javax.servlet.jsp.jstl
        jstl-api
        1.2
    
    
    
        taglibs
        standard
        1.1.2
    
    

    JSTL使用步骤:

    • 导入taglibs
    • 使用对应方法

    8.JavaBean

    实体类

    javaBean特有得写法

    • 必须要有一个无参构造
    • 属性必须私有化
    • 必须由对应得get/set方法

    一般用来和数据库得字段做映射 ORM

    ORM:对象关系映射

    • 表---》类
    • 字段---》字段
    • 行记录---》对象

    9.MVC三层架构

    什么是MVC:model view controller 模型,视图,控制器

    9.1 早些年的架构

    用户直接访问控制层,控制层直接操作数据库

    servlet -- CRUD --->数据库
        弊端:程序十分臃肿,不利于维护
        Servlet代码中:处理请求,响应,视图跳转,处理JDBC,处理业务代码,处理逻辑代码
        
        架构:没有什么是加一层解决不了的
    

    9.2 三层架构

    Model:

    • 业务处理:业务逻辑()
    • 数据持久层:CRUD(DAO)

    View:

    • 展示数据
    • 提供链接发起Servlet请求(a ,img,from...)

    Controller(Servlet):

    • 接收用户的请求:(req:请求参数,Session信息...)
    • 交给业务层处理对应的代码
    • 控制视图的跳转
    登录--》接收用户的登录请求--》处理用户的请求(获取登录参数username,password)--》交给业务层(判断用户名密码是否正常:事务)--》Dao层查询用户名和密码是否正常--》数据库
    

    10.Filter过滤器(重点)

    filter:过滤器,用来过滤网站的数据

    • 处理中文乱码
    • 登录验证...

    Filter开发步骤:

    1. 导包

    2. 编写过滤器

      1. 导包不要错

      2. 重写3个方法

        //    web服务器服务器启动,就会初始化
            @Override
            public void init(FilterConfig filterConfig) throws ServletException {
                System.out.println("开启过滤器");
            }
        //    chain:链
        //      1过滤的所有代码,在特定的特定请求的时候都会执行
        //      2必须要让过滤器继续执行
            @Override
            public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                            servletRequest.setCharacterEncoding("utf-8");
                            servletResponse.setCharacterEncoding("utf-8");
                            servletResponse.setContentType("text/utf-8;charset=UTF-8");
        //                    让我们的请求继续走,如果不写,程序到这里拦截停止
                            filterChain.doFilter(servletRequest,servletResponse);
        
            }
        //web服务器关闭,才会停止
            @Override
            public void destroy() {
                System.out.println("关闭过滤器");
            }
        

    3.在web.xml中配置FIlter

    
            filter
            com.LiuDeHen.Filter.DemoFilter
        
        
            filter
    
            /select/*
        
    

    11.监听器

    //统计在线人数
    public class ListenerServlet implements HttpSessionListener {
    //    创建Session监听,一旦创建就会触发一次
        @Override
        public void sessionCreated(HttpSessionEvent se) {
            ServletContext context = se.getSession().getServletContext();
            System.out.println(se.getSession().getId());
            Integer l = (Integer) context.getAttribute("OnlineCount");
            if (l==null){
                    l=new Integer(1);
            }else{
                int i=l;
                l=i+1;
            }
            context.setAttribute("OnlineCount",l);
        }
        //    销毁Session监听,一旦销毁就会触发一次
        @Override
        public void sessionDestroyed(HttpSessionEvent se) {
            ServletContext context = se.getSession().getServletContext();
            se.getSession().invalidate();
            Integer l = (Integer) context.getAttribute("OnlineCount");
            if (l==null){
                l=new Integer(0);
            }else{
                int i=l;
                l=i--;
            }
            context.setAttribute("OnlineCount",l);
        }
    

    在xml里注册监听器

       
        com.LiuDeHen.Listener.ListenerServlet
    
    

    12.过滤器和监听器常见应用

    监听器:GUI经常用到

    过滤器:

    用户登录之后才能进入主页!

    1. 用户登录之后,向Session中放入用户的数据
    2. 进入主页的时候判断用户是否已经登录,要求:在过滤器中实现
    @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest req=(HttpServletRequest) servletRequest;
            HttpServletResponse resp=(HttpServletResponse) servletResponse;
    
            if (req.getSession().getAttribute("username_ID")==null){
                resp.sendRedirect("/login.jsp");
            }
            filterChain.doFilter(servletRequest,servletResponse);
        }
    

    13 JDBC复习

    基础配置

    什么是JDBC:java连接数据库

    需要jar包支持:

    • java.sql
    • javax.sql
    • mysql驱动(必须导入)

    实验环境搭建:

    CREATE DATABASE JDBC
    USE JDBC;
    CREATE TABLE users(
    id INT PRIMARY KEY,
    `name` VARCHAR(40),
    `password` VARCHAR(40),
    email VARCHAR(60),
    birthday DATE
    );
    INSERT INTO users(id,`name`,`password`,email,birthday)
    VALUES(1,'张三','123','24@11.com','2021-9-2');
    INSERT INTO users(id,`name`,`password`,email,birthday)
    VALUES(2,'张si','123','24@11.com','2021-9-2');
    INSERT INTO users(id,`name`,`password`,email,birthday)
    VALUES(3,'张wu','123','24@11.com','2021-9-2');
    SELECT * FROM users
    

    导入数据库依赖:

    
                mysql
                mysql-connector-java
                5.1.49
            
    

    JDBC步骤:

    1. 加载驱动
    2. 连接数据库,代表数据库
    3. 拿到操作数据库的对象Statem
    4. 编写sql
    5. 执行sql
    6. 关闭连接
    //        配置信息
            String url="jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSl=true";
            String username="root";
            String password="lc20010725";
    //        加载驱动
            Class.forName("com.mysql.jdbc.Driver");
    //        获取连接
            Connection connection = DriverManager.getConnection(url, username, password);
    //        操作数据库的对象statement;
            Statement statement = connection.createStatement();
    //          编写sql
            String sql="select * from users";
    //        执行sql,返回结果集
            ResultSet resultSet = statement.executeQuery(sql);
    //         取出数据
            while (resultSet.next()){
                System.out.println("id"+resultSet.getObject("id"));
                System.out.println("name"+resultSet.getObject("name"));
                System.out.println("password"+resultSet.getObject("password"));
                System.out.println("email"+resultSet.getObject("email"));
                System.out.println("birthday"+resultSet.getObject("birthday"));
            }
    //        关闭连接
            resultSet.close();
            statement.close();
            connection.close();
    

    预编译sql

            //        1配置信息
            String url="jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSl=true";
            String username="root";
            String password="lc20010725";
    //        2加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            //        3获取连接
            Connection connection = DriverManager.getConnection(url, username, password);
            //          4编写sql
            String sql="insert into users(id,name,password,email,birthday) values (?,?,?,?,?)";
            //        5预编译
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,1);//给第一个占位符填充
            preparedStatement.setString(2,"lc");
            preparedStatement.setString(3,"123");
            preparedStatement.setString(4,"12@qq.com");
            preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));
    //6执行sql
            int i = preparedStatement.executeUpdate();
            if (i>0){
                System.out.println("插入成功");
            }
    //        7关闭连接
            preparedStatement.close();
            connection.close();
    

    事务

    要么都成功,要么都失败!

    ACID原则:保证数据的安全性

    开启事务
        事务提交	commit()
        事务回滚  	rollback()
        关闭事务
        
    

    junit单元测试

    依赖

    
               junit
               junit
               4.11
           
    

    @Test只有在方法上有效

     @Test
        public void test(){
            System.out.println("你好");
        }
    
    //        配置信息
            String url="jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSl=true";
            String username="root";
            String password="lc20010725";
            Connection connection=null;
            try {
        //        加载驱动
        Class.forName("com.mysql.jdbc.Driver");
    //        获取连接
        connection = DriverManager.getConnection(url, username, password);
    //    false为开启事务
        connection.setAutoCommit(false);
        String sql="update account set money=money-100 where name='A'";
        connection.prepareStatement(sql).executeUpdate();
    //    制造错误
    //    int i=1/0;
        String sql2="update account set money=money+100 where name='B'";
        connection.prepareStatement(sql2).executeUpdate();
    //    提交事务
        connection.commit();
        System.out.println("提交成功");
    }catch (Exception e){
    //            出现异常就回滚
                try {
                    connection.rollback();
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
    }finally {
                //        关闭连接
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
    
    web