赞
踩
不定期补充、修正、更新;欢迎大家讨论和指正
Java Web,是用Java技术来解决相关web互联网领域的技术栈。web包括:web服务端和web客户端两部分。Java在客户端的应用有Java Applet,不过使用得很少,Java在服务器端的应用非常的丰富,比如Servlet,JSP、第三方框架等等。Java技术对Web领域的发展注入了强大的动力.
Internet上供外界访问的Web资源分为:
静态web资源(如html 页面):指web页面中供人们浏览的数据始终是不变。
静态web资源采用的开发技术:HTML、CSS、JavaSript(本文不涉及前端知识,但JavaWeb应该要知道的前端知识有HTML+CSS+JS、JQuery、AJAX、Json。
动态web资源:指web页面中供人们浏览的数据是由程序产生的,不同用户、不同时间点访问web页面看到的内容各不相同。比如不同的用户登入自己淘宝,其购物车都是不同的。
动态web资源开发技术:JSP/Servlet、ASP、PHP等。
在Java中,动态web资源开发技术统称为Java Web。了解过Java发展历史就知道,Java语言的前身Oak在当时消费品市场上并不算成功,但随着1995年互联网潮流的兴起,Oak迅速找到了最适合自己发展的市场定位并蜕变成为Java语言,成就了今天的Java,所以JavaWeb是Java极其重要的技术栈。
在访问互联网页面时,大致经过以下步骤
比如用户想要打开百度搜索,首先要在浏览器地址栏输入百度的网址(www.baidu.com),浏览器在B/S架构中作为客户端。
(www.baidu.com)只是百度服务器的域名,而服务器是不能直接通过域名来访问的,而是通过IP地址来访问,所以中间还通过DNS(域名解析服务器)来解析域名,客户端会向域名服务器来询问(www.baidu.com)的IP地址,然后用IP地址来连接百度服务器。
客户端终于和百度服务器(常见的服务器有Apache、Nginx等)建立起了链接,用户在搜索框输入想搜索的东西,点击确认后,浏览器会向服务器通过Http/Https协议向百度服务器发送Request(请求),当然Http/Https协议只是计算机网络结构的应用层协议,往下还经过TCP/IP协议等,这里屏蔽细节。
百度服务器接受到请求,会分析请求的URL(uniform resource locator,统一资源定位系统),就是下面一长串的
www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=淘宝……
因为光连上服务器不行啊,服务器还得知道你想访问什么资源。如果是静态资源,服务器找到相应资源经过处理就直接Response(响应)把浏览器需要的资源返回,如果是动态资源,服务器还得连接到数据库等更复杂的业务。
浏览器得到服务器Response的资源后,经过一系列处理渲染,呈现给用户。
下面博客比较详细些,Chrome浏览器中按F12可以进入开发者模式,可以看到从服务器请求到的资源,后面也会用得上。
用户访问网站详细流程
在后续IDEA来创建web工程,其目录结构应当如下图(约定大于配置)
Servlet(Server Applet)是Java Servlet的简称,是Sun公司主推的B/S架构,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。除此之外还有ASP、PHP、JSP等其他动态生成技术。
Servlet是JavaWeb的三大组件(Servlet、Filter、Listener)中最重要的组件,其最主要的的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:接收请求数据Request;处理请求;完成响应Response。
下面来简单实现一个Servlet功能
导入Servlet相关依赖
<!-- 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仅是一个接口,根据上面所说Servlet的主要功能是处理请求,所以以下方法比较符合的只有service()方法了
实现该方法,这段代码的作用是向浏览器屏幕打印消息
接下来就是让我们自定义的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>myServlet</servlet-name> <servlet-class>com.jojo.servlet.MyServlet</servlet-class> </servlet> <!-- 将URL和Servlet程序作映射,这里映射的是/1,也就是说当我们访问http://localhost:8080/web/1时,我们的请求会发送给 com.jojo.servlet.MyServlet1这个类做处理,至于http://localhost:8080/web取决于你是如何自定义Tomcat部署路径的 --> <servlet-mapping> <servlet-name>myServlet</servlet-name> <!-- 1前面的/不能省略,它表示是当前Web项目部署的路径,可以把它等价为http://localhost:8080/web/ --> <url-pattern>/1</url-pattern> </servlet-mapping> </web-app>
当然要实现该功能还需要服务器的支持,Tomcat是Javaweb中常用的服务器,现在我们只需要知道它是服务器,Servlet的容器就行,后面会提到。
启动Tomcat服务器,地址栏输入http://localhost:8080/web/1(因为是在本机测试,所以ip地址使用localhost或127.0.0.1,Tomcat服务器的默认端口号为8080,/web是我设置的整个web工程部署路径,直接访问该路径一般访问的是index.jsp的资源
http://localhost:8080/web 是该web工程的完整路径
接下来访问该工程下的/1路径的资源,可以看到浏览器打印了"Hello Servlet",说明该路径确实由相应的Servlet经过处理
我们知道Http请求主要有两种Get和Post(OPTIONS, PUT, DELETE, TRACE ,CONNECT这些先不说)
Post相比于Get能携带的数据更多,更安全,一般来说Post用于修改和写入数据,Get一般用于搜索排序和筛选之类的操作(淘宝,支付宝的搜索查询都是get提交)。
那么如何对这两种请求分别作出不同的处理呢,我们先在index.jsp写一个表单,用于发送不同的请求
这里就不创建新的Servlet了,用刚才的MyServlet处理就行
如何得知请求的类型,很显然从两个参数之一ServletRequest做文章就行,但ServletRequest没有相关的方法,因此需要使用其子类HttpServletRequest
HttpServletRequest提供了获取请求方式的方法
修改表单提交方式为post
这样就可以对不同请求方式做出不同的处理了
不过自己来处理还是有些麻烦,事实上,在web项目中,更多的是继承Servlet下的子类HttpServlet来实现自己的Servlet的
该类在service()方法的基础上,提供了doGet()、doPost()、doHead()等所有Http请求的方法,我们只需要重写即可
以下为Servlet继承树,有兴趣的自己研究
Servlet中有三大作用域对象,主要用于以类似键值对的方式共享数据,作用域范围由小到大依次为
application作用域具体的对象是ServletContext,在Web容器启动时,会为每个Web程序创建一个ServletContext对象,它代表当前Web应用。ServletContext是全局的,所以可以在不同的Servlet共享数据。
现在自定义两个Servlet,一个用于向应用作用域中存储数据,另一个从应用作用域取出数据,这就实现了Servlet间数据的共享
public class MyServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
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)
在前面已经大致了解Request一些具体实现类的作用了,只要有请求发送到Tomcat服务器,服务器就会把请求过来的Http协议信息解析好封装到Request实现类中。
以HttpServletRequest类为例,常用的API有
getSession()和getCookies(),Session和Cookie也是web中重要的知识点,后面单独讲
setCharacterEncoding(),设置字符集,避免乱码的情况,一般创建字符编码过滤器来处理
getContextPath(),获得当前web工程的路径,比如我的就是/web,这方法很多地方都有
getAttribute()/setAttribute()/removeAttribute(),前面说了Servlet有三大作用域,request就是其中一个,所以当然有共享数据的方法
getParameter(),获取请求中的参数,很重要的方法,比如在页面中输入账号密码,通过该方法就可以得到相关内容
getRequestDispatcher(),获取请求转发对象,跳转页面的一种方法,稍后和重定向一起讲
当Servlet处理完数据后,就可以通过Response(响应)具体实现类返回给客户端数据了
Servlet中页面的跳转有两种方法:请求转发和重定向
转发主要是将浏览器的请求交给另外一个servlet或jsp来处理,借助request对象完成,在服务器内部跳转,浏览器的地址并不发生改变,并且浏览器并不知道服务器内部发生了跳转,整个过程只会发生一次请求,转发的调用者和被调用者都可以共享request对象和response对象。
转发的优点一是安全性高,在内部发生跳转,浏览器地址不变;二是节省资源,转发只需要一次请求,就可以访问至少两个servlet或jsp页面。在实际开发中,转发用到的较多。
转发的局限性在于只能在同一web应用内使用,不能转发到外部的url地址。
public class MyServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/2");
//注意2前面的/不能省略,它表示是当前Web项目部署的路径,可以把它等价为http://localhost:8080/web/
requestDispatcher.forward(req,resp);//相当于把当前的数据交给另一个Servlet处理,所以需要传递当前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");
}
}
如下图,访问的是/1路径,却是MyServlet2来处理请求,url的地址也没有变化,因为转发时传的是同一个请求,所以request作用域的数据可以共享
重定向是指服务器通知浏览器向一个新的地址发送请求,由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 中,对象的生命周期被定义为该对象从创建直到销毁的整个过程。任何对象都有生命周期,Servlet 也不例外。
与 Servlet 生命周期有关的方法一般有以下三个:
文件的上传和下载是互联网很常见的功能,现在来利用Javaweb来简单实现文件上传的功能。
文件上传主要分为两步:在前端写好传输功能、在后端接收文件并保存
在前端页面用form表单上传,其中
实现相关Servlet,先测试连通性
别忘了映射
URL绑定好Servlet后,就可以写接收文件的代码了
我们先试着接收流对象
成功接收到
尽管我们可以成功接收到流,但是因为分片的缘故,每个片段前面都会附加一些辅助的信息,所以还需要经过解析才能真正获取文件的内容。对于解析文件不仅繁琐而且目前也不会,所以要使用第三方来实现。
这里使用Apache提供的commons-fileupload
导入依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
个人对这些API也不是很熟,建议看尚硅谷的视频了解尚硅谷最新版JavaWeb全套教程,java web零基础入门完整版
文件下载大致步骤如下:
这里以下载图片为例
第二步:通过输入流获取该资源的数据
客户端只需要向服务器发送下载请求,所以用Get请求就行
因为该资源的路径是web工程下,所以只能使用作用域最大的servletContext获取该资源
第三步:设置响应头信息
设置MIME类型,MIME是一种标准,用来表示文档、文件或字节流的性质和格式,就是告诉这个文件是什么类型的文件,比如之前的text/html,这里为image/jpeg, 自行了解。
设置响应头,告诉客户端应该怎么处理下载的资源,比如直接打开还是以附件存储。
这里要使用Content-disposition属性,Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件。
其值disposition-type表示以什么方式下载,如attachment为以附件方式下载,disposition-parm为默认保存时的文件名服务端向客户端游览器发送文件时,如果是浏览器支持的文件类型,一般会默认使用浏览器打开,比如txt、jpg等,会直接在浏览器中显示,如果需要提示用户保存,就要利用Content-Disposition进行一下处理,关键在于一定要加上attachment。
这里以附件形式下载,"attachment; filename="后面可以自定义下载文件的名称
最后一步,通过响应的输出流将数据回传给客户端/
之前使用IO流时,一般是以创建缓冲区的形式,将输入流的数据复制到输出流
在文件上传时使用了第三方工具,这里也可以使用commons-fileupload第三方工具下的IOUtils.copy(),将输入流直接复制给输出流
完整代码如下
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String downloadFile = "/img/wenming.jpg";
ServletContext servletContext = getServletContext();
InputStream is = servletContext.getResourceAsStream(downloadFile);
String mimeType = servletContext.getMimeType(downloadFile);
resp.setContentType(mimeType);
resp.setHeader("Content-Disposition","attachment; filename=" + "civilizationVI.jpg");
ServletOutputStream os = resp.getOutputStream();
IOUtils.copy(is,os);
}
剩下的就是Servlet的常规操作,映射之类的
成功下载
在写完相关的Servlet后,要知道IDEA本身只能执行Java代码,是没有让浏览器访问的功能,所以需要将写好的代码部署在相关的Web服务器上。
大家可能听过三大主流的Web服务器(Apache、 Nginx 、IIS),但Servlet用的服务器在广义上也是Web服务器(提供Web服务都可以叫Web服务器),所以很多地方也叫Web服务器,但作用有很大区别。具体点来说Servlet的是应用服务器,为了避免歧义,后序将这些服务器叫做应用服务器或者Servlet的容器。
前者具体来讲是Http服务器,因为当今Web在应用层使用的协议基本是HTTP协议,所以可以将Http服务器和Web服务器对等,这类服务器侧重于对静态资源的支持,有时也叫静态服务器。后者侧重动态资源,即动态服务器
Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以处理浏览器等Web客户端的请求并返回相应响应,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。目前最主流的三个Web服务器是Apache、 Nginx 、IIS。
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。一般来说Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。也就是说一般Apache适合静态页面,Tomcat适合动态页面。
——摘自百度百科
Apache与Tomcat有什么关系和区别
这里强烈推荐看看
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。