Java学习_JavaWeb

不定期补充、修正、更新;欢迎大家讨论和指正

概述

Java Web,是用Java技术来解决相关web互联网领域的技术栈。web包括:web服务端和web客户端两部分。Java在客户端的应用有Java Applet,不过使用得很少,Java在服务器端的应用非常的丰富,比如Servlet,JSP、第三方框架等等。Java技术对Web领域的发展注入了强大的动力.
Internet上供外界访问的Web资源分为:静态web资源(如html 页面):指web页面中供人们浏览的数据始终是不变。动态web资源:指web页面中供人们浏览的数据是由程序产生的,不同时间点访问web页面看到的内容各不相同。静态web资源开发技术:HTML、CSS。动态web资源开发技术:JavaScript、JSP/Servlet、ASP、PHP等。在Java中,动态web资源开发技术统称为Java Web。
——摘自百度百科

先了解一下用户访问页面到获取数据的大致流程。
1.比如用户想要打开百度搜索,首先要在浏览器地址栏输入百度的网址(www.baidu.com),浏览器在B/S架构中作为客户端。

2.(www.baidu.com)只是百度服务器的域名,而网络是不能直接通过域名来访问的,而是通过IP地址来访问,所以中间还通过DNS(域名解析服务器)来解析域名,客户端会向域名服务器来询问(www.baidu.com)的IP地址,然后用IP地址来连接百度服务器。

3.客户端终于和百度服务器(常见的服务器有Apache、Nginx等)建立起了链接,用户在搜索框输入想搜索的东西,点击确认后,浏览器会向服务器通过Http/Https协议向百度服务器发送Request(请求),当然Http/Https协议只是计算机网络结构的应用层协议,往下还经过TCP/IP协议等,这里屏蔽细节。

4.百度服务器接受到请求,会分析请求的URL(uniform resource locator,统一资源定位系统),就是下面一长串的
www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=淘宝……
因为光连上服务器不行啊,服务器还得知道你想访问什么资源。如果是静态资源,服务器找到相应资源经过处理就直接Response(响应)把浏览器需要的资源返回,如果是动态资源,服务器还得连接到数据库。

5.浏览器得到服务器Response的资源后,经过一系列处理渲染,呈现给用户。

下面博客比较详细些,浏览器中按F12可以进入开发者模式,可以看到从服务器请求到的资源,后面也会用得上。
用户访问网站详细流程
在这里插入图片描述
在这里插入图片描述

Tomcat

在这里插入图片描述

Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以处理浏览器等Web客户端的请求并返回相应响应,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。目前最主流的三个Web服务器是Apache、 Nginx 、IIS。
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。一般来说Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。也就是说一般Apache适合静态页面,Tomcat适合动态页面——摘自百度百科
简而言之TomCat是Servlet的容器。
Apache与Tomcat有什么关系和区别

先提前下好Tomcat,了解下原生态Tomcat是如何部署项目的,然后在IDEA整合

Tomcat 下载、安装、配置图文教程
Tomcat 部署项目的三种方法
IntelliJ IDEA整合Tomcat服务器

Servlet

Servlet(Server Applet)是Java Servlet的简称,是Sun公司主推的B/S架构,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。除此之外还有ASP、PHP、JSP等其他动态生成技术。
Servlet的作用就是当我们访问URL时,服务器会将访问的URL映射到Servlet程序中,由Servlet程序来处理请求,然后再通过服务器响应客户端。

创建Web项目,一般目录结构如下图。Maven导入依赖

在这里插入图片描述

 <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

Servlet接口有默认的实现类HttpServlet,创建自定义的类来继承HttpServlet
我们要做的就是重写doGet和doPost方法(Http请求有get和post两种方法),方法中有两个参数,看到Request和Response已经很明显知道这个方法的作用了
就是处理请求和返回结果(响应)
public class MyServlet1 extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    }
}
我们现在给客户端返回响应,响应的内容是向客户端即浏览器页面打印Servlet test,我们的功能比较简单,干脆Post和Get请求都调用doGet方法。

在这里插入图片描述

接下来就是让我们自定义的Servlet程序与URL作映射(在web.xml中作映射),这样当我们访问服务器的URL时,服务器会让Servlet处理我们的请求和响应
?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
         
   	<!--   自定义Servlet类的位置,servlet-name可以任意,不过还是跟类名一致比较好 -->
	<servlet>
        <servlet-name>myServlet1</servlet-name>
        <servlet-class>com.jojo.servlet.MyServlet1</servlet-class>
    </servlet>
	
	<!-- 将URL和Servlet程序作映射,这里映射的是/1,也就是说当我们访问http://localhost:8080/web/1时,我们的请求会发送给
		com.jojo.servlet.MyServlet1这个类作处理 -->
	<servlet-mapping>
        <servlet-name>myServlet1</servlet-name>
        <!-- 1前面的/不能省略,它表示是当前Web项目部署的路径,可以把它等价为http://localhost:8080/web/ -->
        <url-pattern>/1</url-pattern>
    </servlet-mapping>
接下来启动Tomcat服务器,地址栏输入http://localhost:8080/web/1

在这里插入图片描述

为了更深入了解我们可以追本溯源到最开始的类和接口

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ServletContext

了解了大概思路,我们现在来使用Servlet一些常用API
先看HttpServlet自身提供的方法

在这里插入图片描述
在这里插入图片描述

很多方法看名字就知道怎么用了,没什么好讲的,比较重要的是getServletContext(),返回ServletContext类。
在Web容器启动时,会为每个Web程序创建一个ServletContext对象,它代表当前Web应用。
ServletContext是全局的,所以可以在不同的Servlet共享数据
public class MyServlet1 extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        PrintWriter writer = resp.getWriter();

        ServletContext servletContext = this.getServletContext();
        String m1 = "Can you see that?";
        servletContext.setAttribute("message",m1);//以键值对的形式向Context保存信息


    }
public class MyServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();

        String message = (String)servletContext.getAttribute("message");//获取Context信息
		
		PrintWriter writer = resp.getWriter();
        writer.println(message);
    }
}
配置好映射,输入MyServlet2映射的URL(如果没出来可能是MyServlet1没执行就先执行MyServlet2,所以要先打开MyServlet1映射的URL)

在这里插入图片描述

servletContext有请求转发的方法(地址栏URL不变,但是页面改变)

public class MyServlet1 extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

       RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/2");
       //注意2前面的/不能省略,它表示是当前Web项目部署的路径,可以把它等价为http://localhost:8080/web/
       requestDispatcher.forward(req,resp);//因为是将请求转发,所以参数是自身的Request和Response


    }        
public class MyServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.println("Hello");
    }
}
如下图,MyServlet2向浏览器页面打印Hello,映射的路径是/2,MyServlet1通过请求转发将页面跳转到/2上,但是地址栏URL并没有改变

在这里插入图片描述

Request

Request是请求,所以主要功能就是接受客户端发送过来的数据

Java Web之request常用API

Response

Response是响应,所以主要功能就是向客户端发送数据

比如最开始就是用的 PrintWriter getWriter()方法, 可以向浏览器页面打印字符
另一个是ServletOutputStream getOutputStream() ,可以向浏览器页面输出流

void setStatus(int var1),设置HTTP状态码,比如常见的404

void sendRedirect(String var1),重定向,比较重要的方法。和servletContext.getRequestDispatcher()的作用相似,但是自身URL也变为目标URL

转发主要是将浏览器的请求交给另外一个servlet或jsp来处理,借助request对象完成,在服务器内部跳转,浏览器的地址并不发生改变,并且浏览器并不知道服务器内部发生了跳转,整个过程只会发生一次请求,转发的调用者和被调用者都可以共享request对象和response对象。
转发的优点一是安全性高,在内部发生跳转,浏览器地址不变;二是节省资源,转发只需要一次请求,就可以访问至少两个servlet或jsp页面。在实际开发中,转发用到的较多。
转发的缺点是只能在同一web应用内使用,不能转发到外部的url地址。

重定向是指服务器通知浏览器向一个新的地址发送请求,由response对象完成,可以重定向到新的servlet(服务器内部),也可以重定向到外部url(外部应用),浏览器地址发生改变,浏览器知道发生了跳转,整个过程会产生两次请求,重定向的调用者和被调用者不能共享request对象和response对象。
重定向的优点是不限制应用范围,可以重定向到服务器内部其他资源,也可以是外部的应用。
重定向的缺点是耗费请求资源,重定向整个过程发生了两次的请求,一个是资源消耗上比转发大,效率也比转发低;另外,因为浏览器的地址发生了变化,相对转发来讲,安全性没有转发高。
Servlet(四):转发与重定向、路径问题


public class MyServlet1 extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
	   ServletContext servletContext = this.getServletContext();
       resp.sendRedirect(servletContext.getContextPath()+"/2");
       //重定向不同于转发,转发是在服务器内部,而重定向外内部都行,如果重定向的是内部,则需要加上应用名
       //比如http://localhost:8080/web/中http://localhost:8080是域名,/web是应用名
       //为了避免直接将应用名写在地址里面,可以使用request(servletContext也行).getContextPath()方法来替代。
       //直接加的话就是"/web/2"

    }        
public class MyServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.println("Hello");
    }
F12开发者模式,可以看到/1的状态码为302(可以简单的理解为该资源原本确实存在,但已经被临时改变了位置)

在这里插入图片描述

Java Response实现文件下载

Session和Cookie

由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。在服务端保存Session的方法很多,内存、数据库、文件都有。

思考一下服务端如何识别特定的客户?这个时候Cookie就登场了。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。有人问,如果客户端的浏览器禁用了 Cookie 怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。3. Cookie其实还可以用在一些方便用户的场景下,设想你某次登陆过一个网站,下次登录的时候不想再次输入账号了,怎么办?这个信息可以写到Cookie里面,访问网站的时候,网站页面的脚本可以读取这个信息,就自动帮你把用户名给填了,能够方便一下用户。这也是Cookie名称的由来,给用户的一点甜头
作者:知乎用户
链接:https://www.zhihu.com/question/19786827/answer/28752144

总结下,Session是服务端技术,用来保存用户的会话信息。Cookie是客户端技术,;Session 的运行依赖 session id,而 session id 是存在 Cookie 中的,也就是说,如果浏览器禁用了 Cookie ,同时 Session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id)

JSP

JSP(Java Server Pages,Java服务器页面)是由Sun Microsystems公司主导创建的一种动态网页技术标准。JSP部署于网络服务器上,可以响应客户端发送的请求,并根据请求内容动态地生成HTML、XML或其他格式文档的Web网页,然后返回给请求者。JSP技术以Java语言作为脚本语言,为用户的HTTP请求提供服务,并能与服务器上的其它Java程序共同处理复杂的业务需求。JSP将Java代码和特定变动内容嵌入到静态的页面中,实现以静态页面为模板,动态生成其中的部分内容。HTML只能给用户提供静态的页面,而JSP页面可以嵌入Java代码,所以具有一定的动态性。

JSP的底层实现其实还是Servlet,我们找到Tomcat下JSP的工作目录(路径太绕了,看看就行)
在这里插入图片描述
JSP导入了Servlet的包,继承了HttpJspBase,但是还不知道HttpJspBase是什么东西
在这里插入图片描述
查询HttpJspBase,发现继承了HttpServlet。所以JSP的底层还是Servlet,因为只要浏览器访问服务器,不管访问什么资源,其实都是访问Servlet
在这里插入图片描述

语法

JSP 语法

导入依赖
        <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>
脚本代码:<% 代码片段 %>

在这里插入图片描述
在这里插入图片描述

有些人可能会困惑out是什么,我们查看Tomcat下的JSP源码,JSP定义了一些属性

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

关注到javax.servlet.jsp.JspWriter out = null; JspWriter类继承于IO的Writer,所以out的用处显而易见了,在后续中我们会常用到pageContext等对象,与out类似,都是JSP源码中内置属性
在这里插入图片描述

还可以用循环打印多个HTML标签,就是语法有点奇葩
在这里插入图片描述
在这里插入图片描述

JSP指令:<%@  代码  %>;JSP指令用来设置与整个JSP页面相关的属性。

比如我们要在页面正常显示中文,我们需要在 JSP 文件头部添加以下代码:
<%@ page language=“java” contentType="text/html; charset=UTF-8 pageEncoding=“UTF-8”%>
在这里插入图片描述
除了page,还有include、taglib 自行了解
在这里插入图片描述

JSP注释:<%--  注释的东西 --%>

在这里插入图片描述

JSP表达式:<%= 代码 %>;

一个JSP表达式中包含的脚本语言表达式,先被转化成String,然后插入到表达式出现的地方。由于表达式的值会被转化成String,所以您可以在一个文本行中使用表达式而不用去管它是否是HTML标签。表达式元素中可以包含任何符合Java语言规范的表达式,但是不能使用分号来结束表达式。也就是说JSP表达式的内容直接显示在浏览器页面上,可以省略out。
在这里插入图片描述

在这里插入图片描述

JSP声明:<%! declaration; [ declaration; ]+ ... %>

一个声明语句可以声明一个或多个变量、方法,供后面的Java代码使用。在JSP文件中,您必须先声明这些变量和方法然后才能使用它们。
相当于声明了全局变量
在这里插入图片描述

查看JSP源码,发现声明的变量直接作为类的属性而不是在代码块中
在这里插入图片描述
在这里插入图片描述

JSP行为<jsp:action_name attribute="value" />

JSP行为标签使用XML语法结构来控制servlet引擎。它能够动态插入一个文件,重用JavaBean组件,引导用户去另一个页面,为Java插件产生相关的HTML等等。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

JSTL

JSP 标准标签库(JSTL)

Filter和Listener

Filter(过滤器)实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理
在这里插入图片描述

例如Web常会遇到中文乱码的问题,我们可以在Servlet程序中添加req(resp).setCharacterEncoding(“utf-8”),但资源多之后这种方法无疑是很麻烦的,我们可以利用过滤器先将请求处理好字符编码再发送给Servlet或者处理好响应的字符编码再发回浏览器。
过滤器和后面的监听器使用大致流程和Servlet差不多——实现接口,在配置文件中作好映射

public class CharacterFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {//init会随着服务器启动而初始化
        System.out.println("Filter initialize successful");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        System.out.println("character encoding successful");
        chain.doFilter(request, response);//doFilter必须要写,因为此过滤器处理完后要将工作传递给下一个过滤器或者Servlet等
    }

    @Override
    public void destroy() {//过滤器会随服务器关闭而销毁
        System.out.println("Filter destroy successful");

    }
}
	<filter>
        <filter-name>characterFilter</filter-name>
        <filter-class>com.jojo.filter.CharacterFilter</filter-class>
    </filter>
    
    <filter-mapping>
    	<!-- 要对哪些Servlet程序进行过滤 -->
        <filter-name>characterFilter</filter-name>
        <servlet-name>myServlet1</servlet-name>
        <servlet-name>myServlet2</servlet-name>
        <servlet-name>cookieServlet</servlet-name>
    </filter-mapping>

在这里插入图片描述
在这里插入图片描述

Listener(监听器)就是用来监听各种事件的,比如我们点击程序右上角的关闭按钮,就是一个事件,系统根据事件关闭程序相关进程,点击鼠标也是一个事件等等,还有有些网站会记录访问量也可以用监听器来实现。监听器主要在图像化界面应用比较多,而且可以实现的接口繁多(因为什么操作都可以算作一个事件),所以了解就行。
javaweb之listener详解

MVC

MVC是一种框架设计模式,经典MVC模式中,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。其中,View的定义比较清晰,就是用户界面。
V即View视图是指用户看到并与之交互的界面。比如由html元素组成的网页界面,或者软件的客户端界面。MVC的好处之一在于它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,它只是作为一种输出数据并允许用户操纵的方式。
M即model模型是指模型表示业务规则。在MVC的三个部件中,模型拥有最多的处理任务。被模型返回的数据是中立的,模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
C即controller控制器是指控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。
——摘自百度百科
在JavaWeb中,可以分为
dao层:数据访问层,操作数据库,对数据进行增删改查,使用JDBC
service层:业务逻辑层,对数据进行处理,使用Servlet、监听器等
web层:表示层,给页面传递数据,提供用于操作、使用前端技术如HTML、CSS,还有JSP动态页面技术
在这里插入图片描述
也可以分为在这里插入图片描述
在后续学习和工作我们会接触流行的MVC框架比如SSM(Spring+SpringMVC+MyBatis)、SSH(Spring+Struts+Hibernate)

项目实战

SMBMS(超市账单管理系统)是比较好的练手项目,可以利用MVC思想整合之前所学的JBDC、Servlet等知识,了解一个Web项目的整个流程。

【狂神说Java】JavaWeb入门到实战-smbms

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页