JavaWeb基础

JavaWeb

1、简介

在Sun的Java Servlet规范中,对Java Web应用作了这样定义:“Java Web应用由一组Servlet、HTML页、类、以及其它可以被绑定的资源构成。它可以在各种供应商提供的实现Servlet规范的 Servlet容器 中运行。”
  Java Web应用中可以包含Servlet、JSP、实用类、静态文档如HTML、图片等描述Web应用的信息(web.xml)

  1. 静态web资源(如html 页面):指web页面中供人们浏览的数据始终是不变。
  2. 动态web资源:指web页面中供人们浏览的数据是由程序产生的,不同时间点访问web页面看到的内容各不相同

image-20210528010212317

2、Servlet

2.1 Servlet简介

Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。我们把把实现了Servlet接口的Java程序叫做,Servlet

Servlet 在 Web 应用程序中的位置:

image-20210514134858835

2.2 创建第一Servlet程序

Serlvet接口Sun公司有两个默认的实现类:HttpServletGenericServlet

HttpServlet抽象类

HttpServlet抽象类是继承于GenericServlet抽象类而来的。使用HttpServlet抽象类时,还需要借助分别代表Servlet请求和Servlet响应的HttpServletRequest和HttpServletResponse对象。

HttpServlet抽象类覆盖了GenericServlet抽象类中的Service( )方法,并且添加了一个自己独有的Service(HttpServletRequest request,HttpServletResponse方法。

image-20210514141848393

编写一个Servlet程序

image-20210514142738920

下面是具体的实现:

  • 实现Servlet接口:
public class HelloServlet extends HttpServlet {	//继承与HttpServlet,拥有Servlet的所有方法
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        
        PrintWriter writer = resp.getWriter();	//响应流
        writer.print("<h1>Hello World</h1>");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  • Servlet映射:每一个Servlet都需要有一个注册和映射,才可以连接到服务器上。
<servlet>
        <!--给Servlet取名,取什么都可以-->
        <servlet-name>helloservlet</servlet-name>
        <!--Servlet的全限类名,即Servlet在项目中的位置-->
        <servlet-class>com.vxzx.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <!--取与上面name一样的名字-->
        <servlet-name>helloservlet</servlet-name>
        <!--在浏览器中通过该url找到Servlet,即url地址 记得前面加 "/"-->
        <url-pattern>/servlet</url-pattern>
    </servlet-mapping>
  • 启动Tomcat,开始测试;

注意:

  • 默认路径;( /* )

  • 一个Servlet可以指定一个映射路径;

  • 一个Servlet可以指定多个映射路径;

  • 一个Servlet可以指定通用映射路径;(例如:使用url/* 代表url路径后的所有路径都可以访问)

2.3 Servlet原理

  • 客户端发送请求至服务器
  • 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
  • 服务器将响应返回客户端

image-20210528010513399

2.3.1 Servlet生命周期

一般来说,Servlet经历了3个时期:出生:init、运行:service、死亡:destroy;

  • .init( ),当Servlet第一次被请求时,Servlet容器就会开始调用这个方法来初始化一个Servlet对象出来,但是这个方法在后续请求中不会在被Servlet容器调用,该方法只会执行一次。
  • service( )方法,每当请求Servlet时,Servlet容器就会调用这个方法。该方法在Servlet的周期内可以无限次调用。
  • destory,当要销毁Servlet时,Servlet容器就会调用这个方法。在卸载应用程序或者关闭Servlet容器时,就会发生这种情况,一般在这个方法中会写一些清除代码。
public class ServletDate extends HttpServlet {
    @Override
    public void init() throws ServletException {
        System.out.println("Servlet正在初始化");
    }

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("Servlet正在提供服务");
    }

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

2.4 ServletContext

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

有了ServletContext对象,就可以共享从应用程序中的所有资料处访问到的信息,并且可以动态注册Web对象。前者将对象保存在ServletContext中的一个内部Map中。****保存在ServletContext中的对象被称作属性。

2.4.1 共享数据:

在该Servlet中保存数据,可以在另外一个Servlet中拿到数据:getServletContext()

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("hello servlet");
		//this.getServletContext()   Servlet上下文
        ServletContext context = this.getServletContext();
        //自定义需要传输的数据:
        String username = "vxzx";
        //将一个数据保存在ServletContext中,名字为username,值为:username对象.
        context.setAttribute("username",username);
    }
}
public class Get extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       ServletContext context = this.getServletContext();
        String username = (String)context.getAttribute("username");
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter os = resp.getWriter();
        os.print("<h1>" + username + "</h1>");
    }

接下来在web.xml中配置注册Servlet、映射:

  <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.vxzx.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>get</servlet-name>
        <servlet-class>com.vxzx.Get</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>get</servlet-name>
        <url-pattern>/get</url-pattern>
    </servlet-mapping>

测试结果:

在 /get 界面也可以显示出 /hello里面的数据(username);

2.4.2 获取初始化参数

在Servlet中还可以获取web.xml里面定义好的初始化数据;getInitParameter()

web.xml中定义初始化数据:

<!--    配置一些web的初始化参数:-->
    <context-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306</param-value>
    </context-param>
public class ServletDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       	ServletContext context = this.getServletContext();
        String url = context.getInitParameter("url");	
        PrintWriter os = resp.getWriter();
        os.print(url);
    }

配置xml文件中的Servlet;

测试结果:显示 ---> jdbc:mysql://localhost:3306

2.4.3 请求转发

在Servlet中还可以其他Servlet的数据请求转发到本页面来;getRequestDispatcher()

public class ServletDemo04 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        //转发的请求路径:
       	RequestDispatcher rd = context.getRequestDispatcher("/url");
        //调用forword实现请求转发:
        rd.forward(req, resp);
        //请求响应的将会是上面demo03的数据
    }

配置xml文件中的Servlet;

测试结果:显示 ---> jdbc:mysql://localhost:3306

注意:使用请求转发,该url是不会发生任何改变的。

2.4.4 读取资源文件

在Servlet中还可以读取配置文件的资源(例如:properties);

1、创建定义配置文件 db.properties:

username=root
password=123456

2、读取properties资源文件:

public class ServletDemo05 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //读取target里面的properties的数据:
        //需要一个文件流读取数据:
       InputStream is = this.getServletContext().getResourceAsStream("/WEBINF/classes/db.properties");
        Properties prop = new Properties();
        prop.load(is);		//将获取到的数据流加载到prop中
        //获取properties里面的数据:
        String user = prop.getProperty("uername");
        String pwd = prop.getProperty("password");
        //输出数据:
        PrintWriter os = resp.getWriter();
        os.print(user + ":" + pwd);
    }

配置xml文件中的Servlet;

测试结果:显示 ---> root:123456

2.5 HttpServletResponse

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

image-20210518191553226

  • 获取客户端请求的信息,使用HttpServletRequest;
  • 响应给客户端一些信息,使用HttpServletResponse;

2.5.1 浏览器中跳转下载文件

具体步骤:

  • 获取下载文件的地址;
  • 设置下载文件名;
  • 设置浏览器支持下载我们需要下载的文件;
  • 获取输入流;inputstream
  • 设置缓冲区存放输入流获取到的数据;
  • 通过请求得到OutputStream将缓冲区中的数据输出到客户端!
public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String realPath = "G:\\StudyData\\java\\JavaWeb\\java-02-maven\\response\\target\\classes\\林.jpg";
        System.out.println("下载文件的路径:" + realPath);

        String FileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
        resp.setHeader("Content-Disposition","attachment; filename=" +URLEncoder.encode(FileName,"utf-8"));
        FileInputStream fis = new FileInputStream(realPath);
        int len = 0;
        byte[] buff = new byte[1024];
        ServletOutputStream out = resp.getOutputStream();
        while ((len = fis.read(buff)) != -1){
            out.write(buff,0,len);
        }
        out.close();
        fis.close();
}

配置web.xml里面的servlet;

2.5.2 实现重定向

B一个web资源收到客户端A请求后,B他会通知A客户端去访问另外一个web资源C,这个过程叫重定向

常见场景:

  • 用户登录

image-20210518192957743

测试代码:

  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*本质:
        resp.setHeader("Location","/res/down");
        resp.setStatus(302);
        * */

        resp.sendRedirect("/res/down");         //重定向
        System.out.println("重定向成功!");
    }

2.5.3 简单实现登录重定向

html界面:
        <%--设置页面编码,防止乱码--%>
    <%@ page contentType="text/html; charset=utf-8"%>
    <%--${pageContext.request.contextPath}指当前项目--%>
    <form action="${pageContext.request.contextPath}/login" method="get">
        用户名:<input type="text" name="username"/> <br/>
        密码:<input type="password" name="password"/> <br/>
        <input type="submit" value="登陆"/>
    </form>
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws 					ServletException, IOException {
        System.out.println("进入请求!");

        //处理请求:
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("username:" + username + "\n" + "password:" + password);

        //重定向,无论什么类型的,都可以重定向,页面的需要加上后缀
        resp.sendRedirect("/res/req.jsp");
    }

最后记得在web.xml配置servlet。

2.6 HttpServletRequest

HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息;

2.6.1 获取参数和请求转发

其中,获取参数的方法:getParameter()getParameterValues()

下面是一个简易的注册页面的代码实现:

html页面:
    <div align="center">
       <form action="${pageContext.request.contextPath}/login" method="post">
           用户名: <input type="text" name="username"/> <br/>
           密 码: <input type="password" name="password"/><br/>
           性别:
           <input type="radio" name="sex" value="男">男
           <input type="radio" name="sex" value="女">女 <br/>
           爱好:
           <input type="checkbox" name="hobby" value="篮球">篮球
           <input type="checkbox" name="hobby" value="足球">足球
           <input type="checkbox" name="hobby" value="跑步">跑步<br/>
           <input type="submit" value="登陆"/>
       </form>
   </div>
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //解决后台接收数据乱码问题:
        req.setCharacterEncoding("utf-8");

        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String sex = req.getParameter("sex");
        String[] hobbies = req.getParameterValues("hobby");

        System.out.println(username);
        System.out.println(password);
        System.out.println(sex);
//        System.out.println(Arrays.toString(hobbies));
        for (int i = 0; i < hobbies.length; i++) {
            System.out.print(hobbies[i] + ";");
        }
        System.out.println();

        //重定向转发:
//        resp.sendRedirect("/req/Success.jsp");
        //通过请求转发:到自定义页面Success.jsp
        req.getRequestDispatcher("/Success.jsp").forward(req,resp);
    }

3、Cookie & Session

3.1 会话机制

Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是CookieSession。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。

例如:用户在浏览器打开多个链接,访问多个资源,最后关闭浏览器,这过程就叫做会话。

  • cookie:客户端技术(请求,响应);
    • 服务端给客户端一个数据包,客户端下次登陆直接带上这个数据包就可以直接登陆。
  • session:服务器技术,可以保存用户会话信息,可以将信息、数据保存在session中;
    • 服务器会登记你登陆过的信息,下次就会自动匹配到你的信息。

我们常见的使用场景:网站登陆后,下次不需要再输入账号和密码登陆,可直接访问。

通过上面,我们已经知道Cookie通过在客户端记录信息确定用户身份,他的作用大概也就是保存在客户端,用来记录用户身份信息等。。。。

Cookie的特点:

  • 每一个cookie文件大小:4kb , 如果超过4kb浏览器不识别
  • 一个web站点(web项目):发送20个
  • 一个浏览器保存总大小:300个
  • cookie 不安全,可能泄露用户信息。浏览器支持禁用cookie操作
  • 默认情况生命周期:与浏览器会话一样,当浏览器关闭时cookie销毁的

创建一个Cookie程序:

1、从请求中获取一个Cookie信息:

//Cookie,服务器从客户端请求得到Cookie:
Cookie[] cookies = request.getCookies();		//返回数组,Cookie有多个
//判断Cookie是否存在:
if(cookies != null){
    for(i=0; i<cookies.lenght; i++){
        Cookie cookie = cookies[i];
         //获取cookie的名字:
        if(cookie.getName().equal("name")){
            //获取cookie的值:
            String value = cookie.getValue();
            response.getWriter.writer(value);
        }
    }
}else{
    System.out.println("第一次访问:");
}

2、服务器响应给客户端cookie:

 //服务器给客户端响应一个Cookie:
Cookie cookie = new Cookie("name","VXZX");		//以键值对的方式存放内容
cookie.setMaxAge(24*60*60);						//设置cookie存在的时间
response.add(cookie);							//发送回浏览器端

注意:cookie创建后不能再插入其他的键值对,但是可以对其进行修改,cookie.setvalue(key,value)

以下是完整的程序:

//第一次访问该web的时间:
public class CookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决中文乱码问题:
        resp.setContentType("text/html");
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        PrintWriter out = resp.getWriter();

        Cookie[] cookies = req.getCookies();       
        if (cookies != null){
            out.write("上次访问的时间是:");
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                if (cookie.getName().equals("LoginTime")){
                    String value = cookie.getValue();
                    Long LoginTime = Long.parseLong(value);
                    Date date = new Date(LoginTime);
                    out.write(date.toLocaleString());
                }
            }
        }else {
            out.write("第一次访问:");
        }
        
        Cookie cookie = new Cookie("LoginTime",String.valueOf(System.currentTimeMillis()));
        cookie.setMaxAge(24*60*60);
        resp.addCookie(cookie);
    }
}

最后,记得需要再web.xml中配置servlet;该步骤与上面一样。

3、手动清除cookie:

上面已经讲过,使用cookie.setMaxAge() 可以设置cookie存在的时间,那么我们就可以用它来清除已存在的cookie。

  • 不设置有效期,关闭浏览器,自动失效;
  • cookie.setMaxAge()设置有效时间为0,即可手动清除cookie;
//新建一个cookie,该cookie需要与要清除的cookie键值对一模一样:
Cookie cookie = new Cookie("name","VXZX");
cookie.setMaxAge(0);		
response.add(cookie);

具体实现:

public class CookieServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("LoginTime",System.currentTimeMillis() + "");
        cookie.setMaxAge(0);
        resp.addCookie(cookie);
    }
}

如果使用中文出现乱码,我们可以用编码解码的方法来解决乱码的问题:

URLEncoder.encode("中文","utf-8")					//编码
URLDecoder.decode(cookie.getValue(),"UTF-8")	  //解码

3.3 Session***

session的简介:

  • 服务器会给每一个用户(浏览器)创建一个Seesion对象;
  • 一个Seesion独占一个浏览器,只要浏览器没有关闭,这个Session就存在;
  • 用户登录之后,整个网站它都可以访问!--> 保存用户的信息;保存购物车的信息…..

使用场景:

  • 保存一个登录用户的信息;
  • 购物车信息;
  • 在整个网站中经常会使用的数据,我们将它保存在Session中;

创建一个session程序:

//请求获取session:
HttpSession session = request.getSession();
//给session存入数据:(可以存放字符串也可以存放对象)
session.setAttribute("name","vxzx");
session.setAttribute("name1",new Person("姓名","年龄"));    //存放一个Person对象
//最后可以再任意页面通过getAttribute()获取到该session中的数据;

具体实现:

1、存放数据到session中

public class SessionDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        //得到session:
        HttpSession session = req.getSession();
        //给session里面存放数据:	--Person()对象需要自己创建--
        session.setAttribute("username",new  Person("VXZX",11));
        //获取session的id:
        String id = session.getId();
        //判断是否为新创建的session:
         if (session.isNew()){
             resp.getWriter().write("第一次创建session:" + id);
         }else {
             resp.getWriter().write("session已存在:" + id);
         }
    }
}

最后,记得需要再web.xml中配置servlet;

2、获取session中存放的数据:

public class SessionDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        
        HttpSession session = req.getSession();
        Person username = (Person) session.getAttribute("username");
        resp.getWriter().write(username.toString());
    }
}

3、移除session:

我们可以通过自己来控制session的有效时间,来将session移除,节省内存空间。

我们可以使用一些几个方法:

  • session.removeAttribute()将指定值的session移除

  • session.invalidate()将session对象销毁

  • setMaxInactiveInterval(int interval) 设置有效时间,单位秒

public class SessionDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        //移除session:
        session.removeAttribute("username");
        //注销session:
        session.invalidate();
    }
}

还可以在web.xml中配置session的有效时间:

	<!--设置session的失效时间 默认:30分钟-->
    <session-config>
    <!-- 20分钟后失效:-->
        <session-timeout>20</session-timeout>
    </session-config>

*Session和cookie的区别:

  • Cookie是把用户的数据写给用户的浏览器,浏览器保存 (可以保存多个)
  • Session把用户的数据写到用户独占Session中,服务器端保存 (保存重要的信息,减少服务器资源的浪费)
  • Session对象由服务创建;

总结:

  • cookie是一种在客户端记录用户信息的技术,因为http协议是无状态的,为了解决这个问题而产生了 cookie。记录用户名等一些应用。。。。
  • session是一种在服务端记录用户信息的技术,一般session用来在服务器端共享数据。

4、JSP

4.1 JSP简介

Java Server Pages : Java服务器端页面,也和Servlet一样,用于动态Web技术!可以再页面中嵌入JAVA代码,为用户提供动态数据;

4.2 JSP的执行原理

JSP的核心其实是将我们编写的JSP页面,会自动编译成.java文件,而这个.java文件中有继承了HttpServlet类的所有方法;所以浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!

image-20210518123844107

4.2.1 JSP的生命周期

  • 初始化阶段:加载与JSP对应的servlet类,创建其实例,并调用它的初始化方法。
  • 执行阶段:调用与JSP对应的servlet实例的服务方法。
  • 销毁阶段:用与JSP对应的servlet实例的销毁方法,然后销毁servlet实例。JSP
//初始化
  public void _jspInit() {
      System.out.println("正在初始化JSP");
  }
//JSPService
  public void _jspService(.HttpServletRequest request,HttpServletResponse response) {
      System.out.println("正在加载JSP服务");
  }
//销毁
  public void _jspDestroy() {
      System.out.println("正在销毁JSP");
  }

4.2.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;               //page:当前
HttpServletRequest request                        //请求
HttpServletResponse response                      //响应

4.2 JSP基础语法

4.2.1 JSP表达式(<%= %>)

<%--JSP表达式
  作用:用来将程序的输出,输出到客户端
  <%= 变量或者表达式%>
   使用该表达式,java语言式子后面不用加上;
--%>
<%=new Date()%>

测试代码:

<body>
    <%  int i = 10;%>
    <% System.out.println(i);%>
    <% out.print(i); %>
    <h1>这是一个JSP页面</h1>
    <% out.print(new Date());%>
<%--  JSP表达式,将程序输出到客户端  --%>
    <%=new Date()%>
</body>

4.2.2 JSP脚本片段(<% %>)

 <%--jsp脚本片段--%>
  <%
    int sum = 0;
    for (int i = 1; i <=100 ; i++) {
      sum+=i;
    }
    out.println("<h1>Sum="+sum+"</h1>");
  %>

测试代码:

<body>
    <%--JSP脚本片段--->在代码嵌入HTML元素: --%>
    <%
        for (int j = 1; j <= 5; j++) {
    %>
    <h1>JSP页面! <%=j%></h1>				
    <% }%>
</body>

4.2.3 JSP声明(<%! %>)

<%!
        static {
            System.out.println("Loading Servlet!");
        }
        private int globalvar = 0;
        public void speak(){
            System.out.println("use this is method!");
        }
%>
<% this.speak();%>

JSP声明:会被编译到作用域更高的JSP生成Java的类中!其他的,就会被生成到_jspService方法中!

4.2.4 JSP指令

<%@page args.... %>			可以使页面跳转等操作
<%@include file=""%>		可以把其他页面包含进来本页面等操作

可以在web.xml中配置自定义错误的页面,当发生错误时,就会跳转到自定义的页面。

<!-- 自定义错误页面: -->
    <error-page>
        <error-code>404</error-code>
        <location>/error/error02.jsp</location>
    </error-page>
    <error-page>
        <error-code>500</error-code>
        <location>/error/error01.jsp</location>
    </error-page>

设置好错误页面之后,只要网站发生404错误或者500错误就会跳转到error目录下的页面。

测试代码:

 <%-- 使用JSP指令,将两个页面合二为一:   --%>
    <%@ include file="header.jsp"%>
        <h1>MAIN主页面</h1>
    <%@ include file="bottom.jsp"%>
<%-- 使用JSP标签,将两个页面拼接在一起,本质上还是三个页面:   --%>
	<jsp:include page="header.jsp"></jsp:include>
        <h1>MAIN主页面</h1>
    <jsp:include page="bottom.jsp"></jsp:include>

4.3 JSP九大内置对象

  • PageContext: 存数据
  • Request: 存数据
  • Response:
  • Session: 存数据
  • Application [ServletContext] 存数据
  • config [servletConfig]
  • out
  • page
  • exception
<%--内置对象:--%>
<body>
<%
    pageContext.setAttribute("data1","单车");   //保存的数据再一个页面中有效
    request.setAttribute("data2","摩托车");     //数据再一次请求中有效
    session.setAttribute("data3","汽车");       //数据再一次会话中有效,从打开浏览器到关闭
    application.setAttribute("data4","火车");   //数据只在服务器中有效,从打开服务器到关闭
%>
<%
    String data1 = (String) pageContext.findAttribute("data1");
    String data2 = (String) pageContext.findAttribute("data2");
    String data3 = (String) pageContext.findAttribute("data3");
    String data4 = (String) pageContext.findAttribute("data4");
    String data5 = (String) pageContext.findAttribute("data5");
%>
<%--使用EL表达式输出: ${} --%>
<h1>${data1}</h1>
<h1>${data2}</h1>
<h1>${data3}</h1>
<h1>${data4}</h1>
<h1>${data5}</h1>
<h1><%=data5%></h1>      <%--会在页面显示出null--%>
</body>

request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!

session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;

application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据。

4.4 JSP标签、JSTL标签、EL表达式

首先,需要先配置jar包:

<!--JSTL表达式依赖 -->
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl-api</artifactId>
            <version>1.2</version>
        </dependency>
<!--standard标签库 -->
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
  • EL表达式: ${}

    • 获取数据
    • 执行运算
    • 获取web开发的常用对象
  • JSP标签

 <%-- JSP标签: 拼接页面,本质还是三个页面  --%>
    <jsp:include page="header.jsp"></jsp:include>
    <h1>MAIN主页面</h1>
    <jsp:include page="bottom.jsp"></jsp:include>
--------------------------------------------------------------------
<%--设置参数,再jsptag2中取出:--%>
    <jsp:forward page="jsptag2.jsp">
        <jsp:param name="username" value="vxzx"/>
        <jsp:param name="passwd" value="123456"/>
    </jsp:forward>
--------------------------------------------------------------------
<%--取出jsptag的参数:--%>
<h1>This is jsptag2!</h1>
用户名:<%=request.getParameter("username")%>
密码:<%=request.getParameter("passwd")%>
  • JSTL标签

核心标签 (掌握部分):

image-20210528001011578

首先需要引入核心标签库的语法:

<%--引入JSTL核心标签库:--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

c:if

<h3>if测试:</h3>
<form action="coreif.jsp" method="get">
<%-- EL表达式获取表单中的数据:  *** param.参数名 ***   --%>
    <input type="text" name="username" value="${param.username}">
    <input type="submit" value="提交">
</form>

<%--判断提交名字是管理员,则提交成功:--%>
<c:if test="${param.username =='admin'}" var="isAdmin">
    <c:out value="欢迎管理员"/>
</c:if>
<c:out value="${isAdmin}"/>
</body>

EL表达式获取表单中的数据------> ${param.参数名}

c:forEach

<body>
    <%
        ArrayList<String> list = new ArrayList<>();
        list.add(0,"张三");
        list.add(1,"李四");
        list.add(2,"王五");
        list.add(3,"赵六");
        request.setAttribute("list",list);
    %>
    
    <c:forEach var="list" items="${list}" begin="0" end="4" step="3">
        <h1><c:out value="${list}"/></h1><br>
    </c:forEach>
</body>

var , 每一次遍历出来的变量
items, 要遍历的对象
begin, 哪里开始
end, 到哪里
step, 步长

5、JavaBean

JavaBean 是一种JAVA语言写成的*可重用*组件**。为写成JavaBean,类必须是*具体的和公共的*,并且具有*无参数的**构造器*。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,*set和get方法获取*

JavaBean的特定写法:

  • 需要拥有一个无参构造器:
  • 需要有get和set方法;
  • 属性必须私有化;

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

ORM :对象关系映射:

  • 表--->类
  • 字段-->属性
  • 行记录---->对象

先封装一个people类:

//实体类一般都与数据库中的表结构--对应:
public class People {
    private int id;
    private int age;
    private String name;
    private String address;

    public People() {
    }
    public People(int id, int age, String name, String address) {
        this.id = id;
        this.age = age;
        this.name = name;
        this.address = address;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
       	return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
<jsp:useBean id="people" class="com.vxzx.servlet.People" scope="page"/>
<!-- <jsp:useBean id="bean 的名字(id)" class="bean 编译的类" scope="bean 的作用域" typeSpec/> 
	 <jsp:setProperty name="bean 的 id" property="属性名"  value="value"/>
  	 <jsp:getProperty name="bean 的 id" property="属性名"/>
-->
<body>
    <%
//        People people = new People();
    //等价于下面的jsp:useBean语句;
//        people.setId(1);
//        people.setAddress("广州");
//        people.setAge(18);
//        people.setName("VXZ");
//
//        people.getId();
//        people.getAddress();
//        people.getAge();
//        people.getName();
    %>
    <jsp:useBean id="people" class="com.vxzx.servlet.People" scope="page"/>

    <jsp:setProperty name="people" property="id" value="1"/>
    <jsp:setProperty name="people" property="address" value="广州"/>
    <jsp:setProperty name="people" property="age" value="18"/>
    <jsp:setProperty name="people" property="name" value="VXZ"/>

    id号:<jsp:getProperty name="people" property="id"/>
    地址:<jsp:getProperty name="people" property="address"/>
    年龄:<jsp:getProperty name="people" property="age"/>
    姓名:<jsp:getProperty name="people" property="name"/>
</body>

6、MVC三层架构

image-20210528003509700

Model

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

View

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

Controller (Servlet)

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

7、Filter**

Filter也称之为过滤器,它是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。

image-20210528003821307

实现Filter接口,重写对应的方法即可:

//Chain : 链
    /*
    1. 过滤中的所有代码,在过滤特定请求的时候都会执行
    2. 必须要让过滤器继续同行
        chain.doFilter(request,response);
     */    
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Filter开启服务:");
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");

        System.out.println("使用chain前:");
        filterChain.doFilter(servletRequest,servletResponse); //必须执行,不然会卡在这里不会进行下一步
        System.out.println("使用chain后:");
    }

此条语句必写,不然不会继续执行下一步:

filterChain.doFilter(request,response);

配置xml:

    <!--过滤器配置,具体写法跟servlet差不多:-->
    <filter>
        <filter-name>UseFilter</filter-name>
        <filter-class>com.vxzx.pojo.UseFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>UseFilter</filter-name>
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>

8、监听器

监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。

//统计网站在线人数 : 统计session
public class OnlineCountListener implements HttpSessionListener {

    //创建session监听: 看你的一举一动
    //一旦创建Session就会触发一次这个事件!
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();
        System.out.println(se.getSession().getId());

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
        if (onlineCount==null){
            onlineCount = new Integer(1);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count+1);
        }
        ctx.setAttribute("OnlineCount",onlineCount);
    }

    //销毁session监听
    //一旦销毁Session就会触发一次这个事件!
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
        if (onlineCount==null){
            onlineCount = new Integer(0);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count-1);
        }
        ctx.setAttribute("OnlineCount",onlineCount);
   }
    /*
    Session销毁:
    1. 手动销毁  getSession().invalidate();
    2. 自动销毁
     */
}

在xml中配置:

<!--注册监听器-->
<listener>
    <listener-class>com.kuang.listener.OnlineCountListener</listener-class>
</listener>

9、JDBC(复习)

image-20210528005252623

需要jar包的支持:

  • java.sql
  • javax.sql
  • mysql-conneter-java… 连接驱动(必须要导入)

数据库创建:

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,'张三','123456','zs@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'李四','123456','ls@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'王五','123456','ww@qq.com','2000-01-01');

Maven中导入数据依赖:

<!--mysql的驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

JDBC 固定步骤:

  1. 加载驱动
  2. 连接数据库,代表数据库
  3. 向数据库发送SQL的对象Statement : CRUD
  4. 编写SQL (根据业务,不同的SQL)
  5. 执行SQL
  6. 关闭连接

定义一个properties文件:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=true&useSSL=true
user=root
password=123456

basedao.java:封装jdbc工具类

public Basedao {
    private static driver = null;
    private static url = null;
    private static user = null;
    private static pwd = null;
    static {
        Properties properties = new Properties();
       Inputstream is = Basedao.class.getClassLoader().getResourceAsStream("jdbc.properties");
    	properties.load(is);
       	driver = properties.getproperties("driver");
       	url = properties.getproperties("url");
        user = properties.getproperties("user");
        pwd = properties.getproperties("password");
    }
    public Connection getConnection(){
        Connection connection = null;
        Class.forname(driver);
        connection = MangerDriver.getConnection(url,user,pwd);
        return connection;
    }
    public ResultSet execute(Connection connection,String sql,prepareStatement pst,
                            Object[] params,ResultSet rs){
        pst = connection.prepareStatement(sql);
        for(int i=0; i<params.length; i++){
            pst.setObject(i+1,params[i]);
        }
        rs = pst.executeQuery();
        return rs;
    }
    public ResultSet execute(Connection connection,String sql,PrepareStatement pst,
                            Object[] params){
        pst = connection.prepareStatement(sql);
        for(int i =0;i<params.length;i++){
            pst.setObject(i+1,params[i]);
        }
        int j = pst.executeUpdate();
        return j;
    }
    public void CloseConnection(Connection con,PrepareStatement pst,ResultSet rs){
        if(con != null){
            con.close();
        }
        if(pst != null){
            pst.close();
        }
        if(rs != null){
            rs.close();
        }
    }
}
posted @ 2021-05-28 01:11  VXZX  阅读(90)  评论(0)    收藏  举报