将web应用部署到tomcat中,web应用中所有的内容都是服务器中的资源
web资源的分类:web应用中src中编写的动态资源,web应用中web中编写的静态资源
静态资源:每次访问时,内容不会发生变化,例如html、css、js、图片、音频、视频。。。
动态资源:每次访问时,条件不同、情况不同访问结果不一样,例如:Servlet、jsp、Thymeleaf。。。
Servlet 是运行在服务端(tomcat)的Java小程序,是sun公司提供一套定义动态资源规范
从代码层面上来讲Servlet就是一个接口,同时所有实现了Servlet接口的实现类都是一个Servlet
Servlet的作用:处理请求和响应
a>创建一个类,实现Servlet接口,并重写其中所有的抽象方法
public class FirstServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//初始化
}
@Override
public ServletConfig getServletConfig() {
//返回一个Servlet的配置对象
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("hello,Servlet");
servletResponse.getWriter().println("success");
}
@Override
public String getServletInfo() {
//返回一个Servlet的信息
return null;
}
@Override
public void destroy() {
//销毁
}
}
b>在web.xml中注册Servlet
<servlet>
<servlet-name>FirstServletservlet-name>
<servlet-class>com.xy.servlet.FirstServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>FirstServletservlet-name>
<url-pattern>/firstServleturl-pattern>
servlet-mapping>
注意:
1、注册Servlet时,servlet标签和servlet-mapping标签中的servlet-name的值保持一致,建议使用类名
2、url-pattern设置Servlet的虚拟路径,必须以/开头,/表示localhost:8080/上下文路径
3、url-pattern设置Servlet的虚拟路径的规则:
url-pattern可以设置多个
url-pattern可以设置多种格式的路径:/test/abc、/test.html、*.do
c>访问Servlet
在页面中通过Servlet的虚拟路径,访问Servlet,此时Servlet中相对应的方法就会被调用
d>src中资源的部署路径
当web应用部署到tomcat中,src下的资源会被存放到WEB-INF下的classes文件夹中
tomcat是一个Servlet容器,可以管理Servlet的生命周期,即Servlet重实例化、初始化到服务再到销毁都由tomcat管理,那Servlet的生命周期的过程是什么呢?
1、初始化,在服务器启动之后,第一次访问Servlet,会执行init(),且在服务器运行的整个过程中,只执行一次
注意:可以在注册Servlet时,在servlet标签中添加子标签load-on-startup,此时就可以将Servlet的初始化时间提前到服务器启动时,且其中的值越小优先级越高
<servlet>
<servlet-name>SecondServletservlet-name>
<servlet-class>com.xy.servlet.SecondServletservlet-class>
<load-on-startup>1load-on-startup>
servlet>
2、服务,每一次访问Servlet,都会执行service(),在服务器运行的整个过程中,会执行多次
3、销毁,在服务器关闭时执行destroy(),在服务器运行的整个过程中,只执行一次
ServletConfig表示Servlet的配置对象,因此可以通过该对象获取Servlet的配置信息
/**
* ServletConfig表示Servlet的配置对象,因此可以通过该对象获取Servlet的配置信息
* 1、获取Servlet的友好名称,即注册时servlet-name标签的值
* 2、获取Servlet的初始化参数
* 3、获取ServletContext
*/
//获取Servlet的友好名称,即注册时servlet-name标签的值
String servletName = servletConfig.getServletName();
System.out.println("Servlet的友好名称:"+servletName);
//获取Servlet的初始化参数
String testInitParam = servletConfig.getInitParameter("testInitParam");
System.out.println("Servlet的初始化参数:" + testInitParam);
//获取ServletContext
ServletContext servletContext = servletConfig.getServletContext();
ServletContext表示的是整个web应用,因此可以通过该对象获取web应用的相关内容
ServletContext在服务器启动时创建,在服务器关闭时销毁,在服务器运行的整个过程中,只会被创建一次,即在当前服务器运行的整个过程中,所获取的ServletContext都是同一个
/**
* ServletContext表示的是整个web应用,因此可以通过该对象获取web应用的相关内容
* 1、获取当前web应用的上下文路径
* 2、获取当前web应用的部署路径(真实路径)
* 3、获取当前web应用的上下文参数
* 4、作为一个域对象,在整个web应用中共享数据
*/
//获取当前web应用的上下文路径
String contextPath = servletContext.getContextPath();
System.out.println("当前web应用的上下文路径:"+contextPath);
/**
* 获取当前web应用的部署路径(真实路径)
* servletContext.getRealPath(""):获取服务器上web应用的路径
* D:\IDEA\workspace\java_web\out\artifacts\Servlet_war_exploded\
* servletContext.getRealPath("test"):获取服务器上web应用中某个文件的路径,不会判断该文件是否存在,只是一个拼接的效果
* D:\IDEA\workspace\java_web\out\artifacts\Servlet_war_exploded\test
*/
String realPath = servletContext.getRealPath("test");
System.out.println("当前web应用的部署路径(真实路径):"+realPath);
//获取当前工程的上下文参数
String testContextParam = servletContext.getInitParameter("testContextParam");
System.out.println("当前web应用的上下文参数:"+testContextParam);
/**
* ServletContext是一个域对象,可以在整个web应用中共享数据
* 域对象即区域对象、范围对象,指定的范围中,所使用的对象都是同一个
* 域对象:请求域(HttpServletRequest),会话域(HttpSession),应用域(ServletContext)
* 因为在指定的范围值,所获取的域对象都是同一个,因此可以在这个范围内,使用域对象共享数据
* 操作共享数据的方法:
* void setAttribute(String name, Object value):设置共享的数据
* Object getAttribute(String name):获取共享的数据
* void removeAttribute(String name):删除共享的数据
*/
servletContext.setAttribute("testServletContext", "hello,ServletContext");
GenericServlet实现了Servlet接口,将不经常使用的方法进行了重写,例如init()、destroy(),而将真正需要重写的方法service()设置为了抽象方法
因此在创建Servlet时就可以继承GenericServlet,此时只需要重写service()即可
HttpServlet继承了GenericServlet,重写了service()方法,在方法的内部,将ServletRequest转换为HttpServletRequest,将ServletResponse转换为HttpServletResponse,并调用了有HttpServletRequest和HttpServletResponse作为参数的service(),并在此方法中,根据请求方式的不同,调用了不同的方法,GET–>doGet(),POST–>doPost()
因此在创建Servlet时就可以继承HttpServlet,此时只需要重写doGet()和doPost()即可
HttpServletRequest对请求报文进行了封装,因此可以通过该对象获取请求报文相关信息,例如可以获取请求方式、请求参数、请求头信息、请求转发等
//获取当前请求的请求方式
String method = request.getMethod();
System.out.println("当前请求的请求方式:" + method);
//获取当前请求的上下文路径
String contextPath = request.getContextPath();//重要
System.out.println("当前请求的上下文路径:"+contextPath);
//获取当前所请求的服务器的ip、端口号、协议
String serverName = request.getServerName();
int serverPort = request.getServerPort();
String scheme = request.getScheme();
System.out.println("ip:"+serverName+",端口号:"+serverPort+",协议:"+scheme);
//获取当前请求的url和uri
StringBuffer requestURL = request.getRequestURL();
System.out.println("requestURL = " + requestURL);
String requestURI = request.getRequestURI();
System.out.println("requestURI = " + requestURI);
//获取请求头信息
String referer = request.getHeader("referer");
System.out.println("referer = " + referer);
//获取单个的请求参数
String username = request.getParameter("username");
String password = request.getParameter("password");
//获取多个同名的请求参数
String[] hobbies = request.getParameterValues("hobby");
System.out.println("username:"+username+",password:"+password+",hobby:"+ Arrays.toString(hobbies));
注意:
tomcat7中get请求和post请求在获取请求参数时都有乱码问题
tomcat7中get请求的乱码问题的解决方案:
在配置文件server.xml中,在设置端口号的标签中添加属性URIEncoding=“UTF-8”
tomcat8中只有post请求在获取请求参数时有乱码问题
tomcat7和tomcat8中post请求的乱码问题的解决方案:
在获取请求参数之前设置编码:request.setCharacterEncoding(“UTF-8”);
注意:设置编码的代码之前一定不能获取任何的请求参数,否则无效
请求转发是将当前的请求发送到下一个资源继续进行处理,一般转发到某一个页面,此时就可以将这个页面响应到浏览器
由于请求转发是发生在服务器内部的跳转,因此浏览器的地址栏中地址不会发生变化
//请求转发
request.getRequestDispatcher("/success.html").forward(request, response);
HttpServletResponse表示的是响应报文,因此可以通过该对象设置响应报文的信息
//解决响应的数据在页面中显示乱码的问题
response.setContentType("text/html;charset=UTF-8");
//response.setHeader("content-type", "text/html;charset=UTF-8");
//响应浏览器数据
PrintWriter writer = response.getWriter();
//writer.write("helloworld");
writer.print("你好
");
重定向会通知浏览器再次发送请求,访问重定向的地址,因此浏览器的地址栏中地址会发生变化
response.sendRedirect("success.html");
a>请求转发
b>响应浏览器数据
c>重定向
a>请求转发是发生在服务器内部,对于浏览器来说只发送了一次请求,因此浏览器的地址栏中的地址不会发生变化
重定向是由服务器通知浏览器再次发送请求,请求重定向的地址,对于浏览器来说发送了两次请求,因此浏览器的地址栏中的地址会发生变化
b>转发可以获取请求域中的数据,但是重定向不可以
c>重定向可以跨域访问,但是转发不可以,因为转发是发生在服务器内部的跳转,因此能够访问的资源也必须是服务器内部的资源
d>WEB-INF下的资源无法通过浏览器直接访问,只能通过服务器访问
因此请求转发可以访问WEB-INF下的资源,但是重定向不可以
总结:若业务逻辑处理成功使用重定向,若业务逻辑处理失败则使用转发,例如登陆成功使用重定向跳转到成功页面,登录失败使用转发跳转到登录页面
相对路径:目标资源相当于当前位置的路径
绝对路径:
静态web:绝对路径表示资源在磁盘上的路径,以盘符开头
web应用:绝对路径表示资源在服务器上的路径,以/开头
相对路径路径不靠谱,以后主要使用绝对路径
1、相对路径和目标资源的位置以及当前的位置有关,当前位置不一样,访问目标资源的相对路径不一样,即同一个资源没有统一的相对路径
2、相对路径和目标资源的位置以及当前的位置有关,而通过转发跳转到某个页面时,地址栏中的地址和页面中的内容不匹配,因此会导致页面中的相对路径失效
静态web:绝对路径表示资源在磁盘上的路径,以盘符开头
web应用:绝对路径表示资源在服务器上的路径,以/开头
web应用中的绝对路径又分为浏览器解析的绝对路径和服务器解析的绝对路径
浏览器解析的绝对路径,/被解析为localhost:8080,例如html页面中,标签中设置的绝对路径、重定向到的绝对路径
服务器解析的绝对路径,/被解析为localhost:8080/上下文路径,例如web.xml中的路径、转发到的资源的路径
1、html页面中,标签中设置的绝对路径
a>在页面标签中设置绝对路径时,手动添加上下文路径
<a href="/Servlet/success.html">测试/a>
b>使用base标签
在head标签中,设置base标签,设置了base标签的页面,使用标签中的路径都会以base标签的路径为基础,即标签的真正路径base+标签的路径
注意:base标签无法作用于以/、…/、./开头的路径
<base href="/Servlet/">
<a href="testRequestServlet">TestRequestServleta><br>
2、重定向到的绝对路径
response.sendRedirect(request.getContextPath() + "/success.html");