1、Web项目流程
1、总的来说,Tomcat服务器负责两件事,一个是接受浏览器的请求,一个是将结果数据返回到浏览器。通过顶层协议http。
具体过程:
浏览器通过http协议发送请求到服务端,tomcat通过请求(网址解析)到指定位置找到项目目录,找到对应的servlet对象,根据请求的方式调用servlet对象的方法,然后由控制层 接收请求并对请求进行分析,根据分析结果把请求分发给业务层 处理,持久层 是与外界数据存储进行交互的封装。视图层 将返回数据渲染通过response返回给浏览器进行显示
各层的作用:
控制层:接收来自浏览器的请求,进行请求的分析,分发请求。单例,保证线程安全
业务层:业务的处理
持久层:数据的存取。存储和加载
视图层:处理结果数据,将数据渲染回浏览器显示
2、Tomcat
1、Tomcat概念
- Tomcat是一个web容器,所有的 J2EE WEB程序可以在此处运行。
- Tomcat服务器是一个符合J2EE标准的WEB服务器,而J2EE的EJB程序无法在此运行
- 如果要运行可以选择能够运行EJB程序的容器:WebLogic、WebSphere
- Tomcat用Java语言开发,实现了一个Servlet引擎和JSP引擎,因而它支持Java Servlet 和 JSP
2、Tomcat主要目录结构
- bin : 存放启动和关闭tomcat脚本
- conf : 包含不同的配置文件,server.xml(Tomcat的主要配置文件),web.xml
- work:存放jsp编译后产生的class文件(jsp要交给java虚拟机去编译,生成.class文件)
- webapp: 存放应用程序实例,以后要部署的应用程序也要放到此目录
- logs:存放日志文件
- lib : 这三个目录主要存放tomcat所需的jar文件
- doc:包含各种Tomcat的文件
3、创建一个简单web项目,通过目录的方式创建,testweb,通过浏览器访问http://localhost:8080/testweb/
4、配置虚目录
将开发程序保存在虚拟目录中,可以保证项目的路径安全和名字安全。像上面的访问web项目,网址直接暴露了项目的所在位置和项目名,通过配置虚拟目录,可以将项目放在电脑本地的任何一个位置,并且为项目名设置一个虚拟的项目名,访问的时候用这个虚拟名字
如:
< Context (配置的虚拟目录) path=“/test” docBase=“f:\testWeb”/> (虚拟目录在硬盘上的绝对路径 )
访问此虚拟目录的名称:http://localhost:8080/test
5、jsp运行架构
文件格式为jsp —会转化为class文件:
jsp由动态代码+静态代码构成。浏览器处理静态代码和服务器处理动态代码组成。Tomcat处理动态代码,启动tomcat—用户通过浏览器发送请求—通过请求找到项目目录—将字节码加载到虚拟机 ,虚拟机进行加载—tomcat将动态代码处理结果嵌入到静态代码中通过http协议将结果返回给浏览器
文件格式为html —不会转化为class文件:
直接交给浏览器去处理静态代码。
3、包含操作include
-
在JSP中如果要想实现包含的操作,有两种做法:指令包含、标签包含
-
指令包含:也叫作静态包含
<%@include file="incl.jsp"%>
<%@include file="incl.txt"%>
<%@include file="incl.inc"%>
静态包含就是将内容进行了直接的替换,就好比程序中定义的变量一样,是在servlet引擎转译时,就把此文件包含了进去(两个文件的源代码整合到一起),所以只生成了一个servlet,两个页面不能有同名的变量 。
先包含后执行!所以不能有同名的变量!
运行效率高一点,耦合性高,不够灵活。
不识别被包含页面类型,当前页面不会向被包含页面传参。
- 标签包含:包含在java范畴。也叫动态包含
<jsp:include page="incl.txt">
<jsp:param name="ref1" value="ZTE"/>
<jsp:param name="ref2" value="ls"/>
</jsp:include>
incl.text:
<h1>PARAM1<%=request.getParameter("ref1")%></h1>
<h1>PARAM2<%=request.getParameter("ref2")%></h1>
代表一行或多行代码。
先执行后包含!
能识别被包含页面,如果是动态页面,当前页面可以向被包含页面传参 。
动态包含在代码的编译阶段,包含和被包含部分是两个独立的部分,只有当运行时,才会动态包含进来,好比方法的调用。
4、JSP中的属性保存
4.1、request
requestDemo01
<!--http://127.0.0.1:8080/test/base/03/requestDemo01.jsp?age=20-->
<%
request.setAttribute("name","ZTE") ;
request.setAttribute("password","123") ;
%>
<jsp:forward page="requestDemo02.jsp"/>
requestDemo02
<%
String name = (String)request.getAttribute("name") ;
String password = (String)request.getAttribute("password") ;
String age=request.getParameter("age");
%>
<h1>###name : <%=name%></h1>
<h1>###password : <%=password%></h1>
<h1>###age : <%=age%></h1>
<jsp:forward page="requestDemo03.jsp"/>
<%--<a href="requestDemo03.jsp">requestDemo03.jsp</a>--%>
requestDemo03
<%
String name = (String)request.getAttribute("name") ;
String password = (String)request.getAttribute("password") ;
String age=request.getParameter("age");
%>
<h1>***name : <%=name%></h1>
<h1>***password : <%=password%></h1>
<h1>***age : <%=age%></h1>
- request是以map集合来存储数据。
- 在requestDemo01中,age=20是来自请求的参数 ,由tomcat自动set到request的参数区。
- request.setAttribute(“”,“”)手动设定属性值到request的属性区 ,(String,Object)
- < jsp:forward page=“requestDemo02.jsp”/> 用户并不知道要跳转,request请求依旧存在,所以在requestDemo02中可以通过request获取到属性和参数。这是服务端实现的跳转,请求没变还是第一次的请求
- 后台服务端跳转到requestDemo03,request依然存在,请求没有结束,继续从request里获取属性还有参数。属性的值需要造型为String,因为setAttribute时value的类型是Object
String name = (String)request.getAttribute("name") ;
String password = (String)request.getAttribute("password") ;
String age=request.getParameter("age");
-
执行完当前页面,response将结果返回到浏览器。用户只发了一次请求,请求的是demo01,用户并不知道页面跳转了两次!
-
当在demo02中,加入<%–requestDemo03.jsp–%> ,这是一个超链接,需要用户点击后跳转,是发起一次新的请求向Demo03,上一次的请求结束,所以获取不到第一次请求的数据
首先会将demo02的页面返回到浏览器(请求结束),然后用户点击超链接跳转到Demo03,发现Demo03中拿不到属性和参数!因为第一次的request请求已经结束了,是通过第二次的请求(requestDemo03.jsp)跳转到demo03,而此时的request是空的,所以当然拿不到参数和属性了。
要想通过request传递数据,必须是服务端跳转
4.2、session
sessionDemo01
<!--http://127.0.0.1:8080/test/base/03/sessionDemo01.jsp?uname=tom&upass=123-->
<%@ page contentType="text/html;charset=gb2312"%>
<%
String name = request.getParameter("uname");
String password = request.getParameter("upass");
if("tom".equals(name)&&"123".equals(password))
session.setAttribute("flag","ok") ;
%>
<%--<jsp:forward page="sessionDemo02.jsp"/>--%>
<a href="sessionDemo02.jsp">取款</a>
sessionDemo02
<%@ page contentType="text/html;charset=gb2312"%>
<%
String flag = (String)session.getAttribute("flag") ;
%>
<h1>flag : <%=flag%></h1>
<%if(flag!=null)
out.print("取款成功");
else
out.print("取款失败");%><br>
<a href="sessionDemo03.jsp">转账</a>
sessionDemo03
<%@ page contentType="text/html;charset=gb2312"%>
<%
String flag = (String)session.getAttribute("flag") ;
%>
<h1>flag : <%=flag%></h1>
<%if(flag!=null)
out.print("转账成功");
else
out.print("转账失败");%><br>
- 用户第一次发起请求时创建session,用户下线后销毁session,只要服务不下线,session唯一且一直存在
- 执行完demo01,将登录成功标识flag存在session里,当客户端跳转到转账时,第一次的request结束,但是session一直存在,demo02从session拿到登录标识,如果为true说明登录成功则可以取款;如果没拿到,就返回取款失败;;demo02执行完,客户端跳转到demo03转账,再次从session拿到登录标识,有就可以进行转账;没有则失败。
- 这就是通过在登录成功后保存登录成功标识到session,在后面的每一次请求都要验证是否登录成功,没有登录的请求不能进行相应的操作。 这样避免没有登录过的请求直接访问内部功能。
request和session
- 传递数据一般就是用request,周期短,请求开始创建请求结束销毁,并且是由服务器决定时长
- session一般用来保存用户登录状态(像上面的例子中保存一个登录成功的标识flag),用户下线销毁。session的存活周期是由用户决定的,用户下线则销毁
-
4.3、application
set属性:
application.setAttribute("name","ZTE") ;
application.setAttribute("password","ls") ;
get属性:
String name = (String)application.getAttribute("name") ;
String password = (String)application.getAttribute("password") ;
- application属性范围值,只要设置一次,则所有的网页窗口 都可以取得数据。即便用户下线,数据依然存在。如果要释放application资源,只能重新启动服务器
- 应用:在线人员统计,在线人员名单列表等
4.4、page
设置属性
pageContext.setAttribute("name","tom") ;
pageContext.setAttribute("password","345") ;
获取属性
String name = (String)pageContext.getAttribute("name") ;
String password = (String)pageContext.getAttribute("password") ;
- 通过pageContext设的属性,该数据只在当前页面 有效,不论是客户端实现跳转还是服务端实现跳转,只要页面变了,数据就会清空!
- 实际上,前面三种都是基于pageContext对象完成的
public abstract void setAttribute(String name, Object value, int scope)
实际上,四种属性范围,都是通过pageContext对象完成的
public static final int APPLICATION_SCOPE
public static final int SESSION_SCOPE
public static final int REQUEST_SCOPE
public static final int PAGE_SCOPE
通过pageContext设置参数时,可以设置范围值,选择是request、session、application、page
如:
pageContext.setAttribute("name","tom",PageContext.APPLICATION_SCOPE) ;
pageContext.setAttribute("password","345",PageContext.APPLICATION_SCOPE) ;
String name = (String)application.getAttribute("name") ;
String password = (String)application.getAttribute("password") ;
- 但是如果要实现跨页的数据传递,一般不会通过pageContext去设置范围属性来实现,而是直接调用对应的内置对象
5、动态编码
1、对于中文该如何处理?
对于静态资源(html)中的中文,我们会在文件的第一行加上
<%@ page contentType="text/html;charset=gbk"%>
但是对于表单提交传来的中文,该如何处理?这就是动态编码造成的中文乱码的解决方法:
第一种,对所有的数据进行再编码----先转化为字节,字节再转化为字符
String name = request.getParameter("uname") ;
byte[] b=name.getBytes("ISO8859-1") ;
name = new String(b) ;
- 适用于表单是post提交,get提交的时候还是会出现乱码。
- 编码通过率高,但是转化比较麻烦,代码量大
第二种,通过调用request的方法
request.setCharacterEncoding("GBK");
- 同样只适用于表单是post提交(不显示参数),get提交依然是乱码
- 代码简洁。但是编码通过率不如第一种方法。不过大多时候采用的是这种
6、多值请求
1、之前都是一个key对应一个value的参数请求,单值请求,多值请求什么时候会发生呢?在复选框的时候,对于同一个属性,对应多个value值
<html>
<body>
<form action="demo04.jsp" method="post">
用户名:<input type="text" name="uname"><br>
兴趣:
<input type="checkbox" name="inst" value="bask">篮球
<input type="checkbox" name="inst" value="swim">游泳
<input type="checkbox" name="inst" value="sing">唱歌
<input type="checkbox" name="inst" value="dancd">跳舞
<input type="checkbox" name="inst" value="read">看书
<br>
<input type="submit" value="提交">
</form>
</body>
</html>
这种情况下,tomcat会将多值的value放在一个字符串数组里,在内存里的常量池开辟空间。
// 接收内容
request.setCharacterEncoding("GBK") ;
String name = request.getParameter("uname") ;
System.out.println("name="+name+"");
String []inst1 = request.getParameterValues("inst") ;
System.out.println("inst1="+inst1);
<%
for(int i=0;i<inst1.length;i++)
{
%>
<%=inst1[i]%>
<%
}
%>
接收内容时,单值请求用getParameter,多值请求用.getParameterValues接收,创建一个字符串数组对象来接受,返回的是字符串数组对象的哈希地址(数组没有重写toString方法,调用的是object的toString方法,输出的是哈希地址)。然后for循环将字符串数组中的值遍历出来!
2、多值请求可能出现的问题
当表单什么都不提交时,对于单值请求,提交空白,会自动填充空字符串,而对于多值请求,因为要设到数组中,数组中如果什么都没有,就是null(空的),当request获取参数的时候,因为values为空,于是不会创建字符串数组对象,返回的是一个null,在遍历时,要调用inst1的属性length,而inst1是null,就会报空指针异常!
代码不健壮!当用户什么都不输时,会出现空指针异常的报错。
生成的http协议,根本没有获取到inst参数,当执行request.getParameterValues("inst)时,根本获取不到,返回的是一个null,for循环中调用null指向的属性,当然就会报空指针异常了!
如何解决?
- 在代码里加入try…catch块来捕获异常
- 优化多值请求代码,提高代码健壮性,如下面
3、优化多值请求
- 拥抱用户需求
- 解决空指针异常的问题
- 提高代码健壮性
接收多值请求
<%@ page contentType="text/html;charset=gbk"%>
<%@ page import="java.util.*"%>
<html>
<body>
<%
// 接收内容
request.setCharacterEncoding("GBK") ;
Enumeration enu = request.getParameterNames() ;
while(enu.hasMoreElements())
{
String name = (String)enu.nextElement() ;
String[] temp= request.getParameterValues(name) ;
%>
<h1><%=name%> --></h1>
<%
for(int i=0;i<temp.length;i++)
{
%>
<%=temp[i]%>
<%
}
}
%>
</body>
</html>
- Enumeration enu = request.getParameterNames() ;
通过request.getParameterNames(),获取所有参数的名字 。不论是单值还是多值,通过这个方法将参数名都拿到。这样一来,即便用户端再添加多少个属性,都不需要修改业务代码。拥抱用户需求。
- 将所有参数名放在一个Enumeration集合中,然后将参数名遍历出来,每遍历一个,通过request.getParameterValues(name)取到该参数的值放到一个字符串数组对象中。然后遍历这个字符串数组,将值输出。
- 解决空指针异常
request.getParameterNames() ,这个方法只会将值不为空的参数名获取到,所以多值参数如果没有设定值根本就不会获取到,也就从根本上解决了为空的问题。
当什么都不输的时候,不会抛异常---- request.getParameterNames();只拿有值的参数名,所以拿到的是单值请求的那几个参数,值是空字符串。不会引起空指针异常。多值请求参数值是null,所以参数名根本没取过来。
8、获取ip地址
<%@ page contentType="text/html;charset=gbk"%>
<html>
<body>
<h1><%=request.getRemoteAddr()%></h1>
</body>
</html>
9、隐藏域
<html>
<body>
<form action="demo06.jsp" method="get">
<input type="text" name="id" value="001"readonly>
<!--<input type="hidden" name="id" value="001">-->
成绩:<input type="text" name="grade" value="58">
<input type="submit" value="提交">
</form>
</body>
</html>
- 将type设为hidden,会将id文本框隐藏
- 添加readonly,会让文本框变为只读,不能修改
10、超链接
<html>
<body>
<a href="demo16.jsp?uname=zte&upass=zs">demo16.jsp</a>
</body>
</html>
- 表单和超链接
相同点:都是静态代码,都可以生成http请求
不同点:
超链接 :不能和用户交互,只能是get请求,但是如果只是传一个参数,或者只是跳转一个页面,用超链接代码更简单
表单 :可以和用户进行交互,可以选择post/get 请求,代码比较复杂
如果参数要和用户交互、安全性高—用表单
如果参数只是实现一个功能–用超链接
11、response
- 定时刷新
<%@page contentType="text/html;charset=gb2312"%>
<%!
// 此处为全局变量,初始化一次
int i = 0 ;
%>
<%
// 一秒种刷新一次,每次使i自增
response.setHeader("refresh","1") ;
%>
<h1><%=++i%></h1>
- 定时跳转
<%@page contentType="text/html;charset=gb2312"%>
<%
// 两秒种后跳到responseDemo02.jsp页面
response.setHeader("refresh","2;URL=responseDemo02.jsp") ;
%>
两秒后跳转到欢迎页!!!<br>
如果没有跳转,请按<a href="responseDemo02.jsp">这里</a>!!!
往http协议头里加入控制信息
http带着结果信息,协议头里有控制信息,去到浏览器,浏览器将结果信息解析在页面上,然后控制信息负责跳转
- 两种跳转方式
<%@page contentType="text/html;charset=gb2312"%>
<h1>欢迎光临:responseDemo03.jsp</h1>
<!-- http://127.0.0.1:8080/test/base/05/responseDemo03.jsp?upass=123 -->
<%
System.out.println("** 跳转之前...") ;
%>
<%
// 进行跳转
response.sendRedirect("responseDemo04.jsp?uname=ZTE");
//response.setHeader("refresh","0;URL=responseDemo04.jsp?uname=ZTE") ;
%>
<%--<jsp:forward page="responseDemo04.jsp"/>--%>
<% //request.getRequestDispatcher("responseDemo04.jsp").forward(request, response);
System.out.println("** 跳转之后...");
%>
重定向,客户端跳转
response.sendRedirect(“responseDemo04.jsp?uname=ZTE”);
服务器执行这个,服务器没有跳转,服务器只是将控制信息设到http协议头,服务器继续执行后面的代码。返回到浏览器后,浏览器来进行跳转。
转发,服务端跳转
request.getRequestDispatcher(“responseDemo04.jsp”).forward(request, response);
服务器执行这个,服务器进行跳转,不会再执行后面的代码。返回到浏览器,浏览器并没有跳转,还是第一次的request请求,可以从request中拿到信息。
- 重定向和转发的区别
共同点:都是从一个组件跳转到另一个组件,一个页面跳转到另一个页面
不同点:
- 语法不同,写法不同。
response.sendRedirect(“responseDemo04.jsp?uname=ZTE”);
request.getRequestDispatcher(“responseDemo04.jsp”).forward(request, response);
- 跳转的实质不同
重定向:服务器执行这条代码,仅仅将控制信息设置到协议头,等到http协议带着结果信息和控制信息重新回到浏览器后,将结果信息的内容在浏览器显示,跳转由浏览器来实现,重新发送请求,之前的request结束
转发:由服务器来跳转,request还在;服务器执行这条代码,直接进行跳转,http协议带着结果信息回到浏览器已经跳转到新的页面,所以客户端根本不知道跳转了,是服务端进行跳转
- 服务端跳转后面的代码不执行;客户端跳转,后面的代码还会继续执行
- 客户端跳转,地址栏发送变化;服务端跳转,地址栏不会发生变化
- 传参。服务端跳转可以传参;客户端跳转不能传参
- 重新传参,服务端跳转地址栏不变,不能重新传参;客户端是重新发送请求,可以重新传参
应用场景:
正常流程,服务端实现跳转。异常流程,客户端实现跳转
12、cookies
<%
Cookie c1 = new Cookie("name","zs") ;
Cookie c2 = new Cookie("password","123") ;
// 保存时间为60秒
c1.setMaxAge(60) ;
c2.setMaxAge(60) ;
%>
<%
// 通过response对象将Cookie设置到客户端
response.addCookie(c1) ;
response.addCookie(c2) ;
%>
<!--127.0.0.1:8080/test/base/05/cookieDemo02.jsp-->
<%
// 通过request对象,取得客户端设置的全部Cookie
// 实际上客户端的Cookie是通过HTTP头信息发送到服务器端上的
Cookie[]c = request.getCookies() ;
%>
<%
for(int i=0;i<c.length;i++)
{
%>
<h1><%=c[i].getName()%> <%=c[i].getValue()%></h1>
<%
}
%>
通过request取得客户端设置的所有cookie
结果页面有三个cookie,两个是之前通过response设置的
还有一个是**系统cookie,由tomcat自动设置 **
JSESSIONID 5FC8065563854B99455604E2729D9F37
Idea-27e61da6 c0d47287-c87a-4a2b-bc3e-979e3d5b271a
Authorization b7893d85fdec484c9884b23fd1b56816
当用户第一次登录时,tomcat获取不到任何cookie,就会认为用户是新用户,就创建新的session
new HttpSession()
sessionId =32位的sessionid
cookie c = new cookie(sessionId)
response.addCookie(c);
//这都是tomcat做的事
tomcat通过response将三个cookie设到http协议头,http协议带着三个cookie和结果信息再次回到浏览器。所以其实cookie存储敏感信息是很不安全的,因为会返回到浏览器,在浏览器很容易被拦截。
-
当没有设置cookie时,直接Cookie[]c = request.getCookies() 返回null,不会创建数组对象,调用null的length属性,报空指针异常。
-
优化:
将静态页面改为jsp。当服务器判断是第一次登录,就会自动创建sessionId,系统cookie,这样就避免了空指针异常的问题。
13、session
- 获取sessionId和长度
<h1>SESSIONID : <%=session.getId()%></h1>
<h1>SESSIONID LENGTH : <%=session.getId().length()%></h1>
- 验证当前是不是新用户
session.isNew();
比较sessionId和系统cookie的sessionId ,如果不一样(说明没有系统cookie),因为系统cookie就是在用户第一次登录tomcat设置的sessionId,所以如果在服务端的sessionId列表中比对没有一致的,说明是新用户。返回true—新用户
比较sessionId和系统cookie的sessionId一样(说明已经有系统cookie了),返回false—不是新用户
用户发送请求带着系统cookie,服务器拿到系统cookie,将其和服务器里用户的sessionId对比,如果有一样的,不是新用户;如果没有,新用户
<!--http://127.0.0.1:8080/test/base/06/sessionNew.jsp-->
<%@page contentType="text/html;charset=gb2312"%>
<%//session的sessionid和系统cookie的sessionid比较
if(session.isNew())
{
%>
<h1>您是新的session</h1>
<%
}
else
{
%>
<h1>您不是新的session</h1>
<%
}
%>
<%
// 使session失效
//session.invalidate() ;
%>
- session的时间
<%@page contentType="text/html;charset=gb2312"%>
<%@page import="java.util.*"%>
<%
long l1= session.getCreationTime() ;
long l2 = session.getLastAccessedTime() ;
%>
<h1>session CREATE : <%=new Date(l1)%></h1>
<h1>session last access: <%=new Date(l2)%></h1>
<h1><%=(l2-l1)/1000%></h1>
14、application
- 拿到虚拟目录的真实路径
<%@ page contentType="text/html;charset=gbk"%>
<h1>取得虚目录的真实路径</h1>
<h1><%=this.getServletContext().getRealPath("/")%></h1>
<h1>取得相对路径的绝对路径</h1>
<h1><%=application.getRealPath("base")%></h1>
- web.xml
如果一个页面不想用户通过发起请求访问,可以放进web-inf目录下,这样无法直接通过地址栏访问到。如何访问web-inf下的网页?需要配置web.xml
<?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"
metadata-complete="true">
<servlet>
<servlet-name>zte</servlet-name>
<jsp-file>/WEB-INF/hello.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>zte</servlet-name>
<url-pattern>/a4</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>zte</servlet-name>
<jsp-file>/WEB-INF/sdemo.jsp</jsp-file>
<init-param>
<param-name>uname</param-name>
<param-value>zs</param-value>
</init-param>
<init-param>
<param-name>upass</param-name>
<param-value>123456</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>zte</servlet-name>
<url-pattern>/a3</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
在web.xml文件中配置参数
<param-name>uname</param-name>
<param-value>zs</param-value>
</init-param>
<init-param>
<param-name>upass</param-name>
<param-value>123456</param-value>
</init-param>
tomcat在一启动时,就会加载配置文件,就会将属性值设到属性上。
设置网页的映射地址,web-inf下的网页
<servlet>
<servlet-name>zte</servlet-name>
<jsp-file>/WEB-INF/hello.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>zte</servlet-name>
<url-pattern>/a4</url-pattern>
</servlet-mapping>
当你不想网页直接通过地址栏访问时,可以放进WEB-INF下,这样要访问的话需要去web.xml中进行配置。可以修改访问的网页名。如这里,可以直接通过访问 127.0.0.1:8080/test/a4
设置主页
<welcome-file-list>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
虽然web项目中会有一个默认的主页index.jsp,但是当你在web.xml中配置了主页的话,这个index.jsp就不再是主页了会失效。即便手动设置的主页丢失,网站也不会去找那个默认的主页。一旦设置,就会使用手动设置的。