NIUCLOUD是一款SaaS管理后台框架多应用插件+云编译。上千名开发者、服务商正在积极拥抱开发者生态。欢迎开发者们免费入驻。一起助力发展! 广告
# Servlet与Jsp进阶 [TOC] ## 导学 在之前的学习中,我们已经初步认识到什么是Servlet和Jsp。那么今天我们再来重新认识一下Servlet和Jsp,本节课需要掌握Java Web的核心特性(请求与响应的结构)、掌握Servlet的核心对象、Jsp九大内置对象(面试笔试中常遇到)等内容 ## HTTP请求的结构 请求是浏览器像服务器发送的数据包,那么在请求中其实是包含了三部分的内容的:请求行,请求头,请求体。 ![](https://img.kancloud.cn/85/30/85300b9dcda73a124752b8d3f151f8a8_625x289.png) 请求行包括请求的方式,请求的地址,以及请求的HTTP版本 请求头中,包括很多辅助的请求信息,能为请求处理提供额外的支持。 **资料(关于请求头与响应头):**[https://www.cnblogs.com/xjcjcsy/p/6135006.html](https://www.cnblogs.com/xjcjcsy/p/6135006.html) 请求体中,描述了请求的参数内容。注意一下,get请求是将参数写入URL中,所以get请求是没有请求体的,只有post请求才有请求体。 ~~~java /** * Servlet implementation class MethodServlet */ @WebServlet("/method") public class MethodServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public MethodServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().println("This is Get method"); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().println("This is Post method"); } } ~~~ ~~~html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <form action="/MyJsp/method" method="get"> <input name="userName"/> <input name="password" type="password"/> <input type="submit"/> </form> </body> </html> ~~~ ![](https://img.kancloud.cn/04/ef/04efb61bebf64abd46f8f1ffb8242ef2_1365x669.png) ![](https://img.kancloud.cn/b6/10/b61058f84cd57fbec97a6f6913b15c27_1363x663.png) ## 利用请求头开发多端应用 早期的程序,基本都是运行的在电脑上的,我们编写页面的时候只要考虑电脑端的情况就可以了。但是随着个人设备越来越多,我们需要考虑的显示设备也越来越多,那么我们该如何去尝试着在Java中进行多种设备的考量呢?这个时候我们就可以利用请求头进行判断分析 ~~~ /** * Servlet implementation class UserAgentServlet */ @WebServlet("/useragent") public class UserAgentServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public UserAgentServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String userAgent = request.getHeader("User-Agent");//获取请求头信息 response.setContentType("text/html;charset=utf-8");//设置服务器端响应的编码方式以及内容解析方式 response.getWriter().println(userAgent); String output = ""; if(userAgent.indexOf("Windows NT") != -1) { output = "<h1>这是PC端</h1>"; } else if(userAgent.indexOf("iPhone") != -1 ||userAgent.indexOf("Android") != -1 ){ output = "<h1>这是手机端</h1>"; } response.getWriter().println(output); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } ~~~ ## 响应的结构 HTTP响应包含三部分:响应行、响应头、响应体 ![](https://img.kancloud.cn/2d/a6/2da6c00a74180e7debfcc301897991f1_668x267.png) HTTP常用状态码: ![](https://img.kancloud.cn/f9/a7/f9a70be35916394cdbb3aee1380bc31d_583x330.png) ## ContentType的作用 ContentType决定浏览器采用何种的方式对响应体进行处理。 ![](https://img.kancloud.cn/f4/00/f400fdce8c7731104ff7bd6f431a87d6_728x332.png) ~~~java /** * Servlet implementation class ContentTypeServlet */ @WebServlet("/contenttype") public class ContentTypeServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public ContentTypeServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String output = "<h1><a href='www.baidu.com'><span>百度</span></a></h1>"; /*response.setContentType("text/html;charset=utf-8");*/ /*response.setContentType("text/plain;charset=utf-8");*///输出纯文本 /*response.setContentType("text/xml;charset=utf-8");*/ response.setContentType("application/x-msdownload;charset=utf-8"); response.getWriter().println(output); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } ~~~ ## 请求转发与重定向 在之前的学习中,都是通过一个servlet来完成的程序处理,但在真正的开发中,需要多个servlet进行组合调用。从A servlet到B servlet,完成一场“传值的游戏”。那么从A到B之间,如何进行通信和跳转呢? 对于多个servlet和jsp之间跳转有两钟方式: 1. 请求转发:`request.getRequestDispatcher(path).forword(request,response)` 2. 响应重定向:`response.sendRedirect(Contextpath工程名称/映射地址);` 区别: 请求转发是不会改变一开始访问的映射地址 响应重定向是会改变到最后请求的映射地址 ### 请求转发与重定向的使用 ~~~ @WebServlet("/direct/index") public class IndexServlet extends HttpServlet { private static final long serialVersionUID = 1L; public IndexServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().println("This is index page"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } ~~~ ~~~ /** * 用户校验页面 * @author LiXinRong * */ @WebServlet("/direct/check") public class CheckLoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; public CheckLoginServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("用户登录成功"); //请求.请求触发器.转发->浏览器地址栏不会发生改变 request.getRequestDispatcher("/direct/index").forward(request, response); //响应重定向需要增加contextPath->浏览器地址栏会发生改变 response.sendRedirect("/sd/direct/index"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } ~~~ 转发时,是在服务器内部由第一个servlet跳转到新的servlet。而转发是在服务器处理完第一个servlet后,通知浏览器,由浏览器再发送一个请求给服务器的新的servlet。 ### 请求转发与重定向的原理 虽然请求转发与重定向都是用于地址的跳转,但是它们两个在本质上是完全不一样的。 **请求转发** 请求转发是在服务器内部进行跳转,转发调用的是HttpServletRequest对象中的方法以及转发时浏览器只请求一次服务器,地址栏的url不会发生变化。 ![](https://img.kancloud.cn/79/e4/79e4ef52edea941e96590d95f986d3a7_677x217.png) 在进行请求转发时,允许创建自定义属性。 设置请求属性: `request.setAttribute(属性名,属性值)` 获取请求属性: `Object attr = request.getAttribute(属性名)` ~~~ @WebServlet("/direct/check") public class CheckLoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; public CheckLoginServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("用户登录成功"); request.setAttribute("name", "Jack"); //请求.请求触发器.转发->浏览器地址栏不会发生改变 request.getRequestDispatcher("/direct/index").forward(request, response); //响应重定向需要增加contextPath /*response.sendRedirect("/sd/direct/index");*/ } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } ~~~ ~~~ @WebServlet("/direct/index") public class IndexServlet extends HttpServlet { private static final long serialVersionUID = 1L; public IndexServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = (String)request.getAttribute("name"); System.out.println(name); System.out.println("index page"); request.getRequestDispatcher("/direct/index2").forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } ~~~ ~~~ @WebServlet("/direct/index2") public class IndexServlet2 extends HttpServlet { private static final long serialVersionUID = 1L; public IndexServlet2() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = (String)request.getAttribute("name"); System.out.println(name); System.out.println("index page2"); request.getRequestDispatcher("/direct/index3").forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } ~~~ ~~~ @WebServlet("/direct/index3") public class IndexServlet3 extends HttpServlet { private static final long serialVersionUID = 1L; public IndexServlet3() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = (String)request.getAttribute("name"); System.out.println(name); System.out.println("index page3"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } ~~~ 在servlet中定义的属性,可以通过请求转发一直传递下去。 **重定向** 重定向则是浏览器端跳转,会产生两次请求。 ![](https://img.kancloud.cn/94/29/9429b411c154bbfa8e99b8e2f546f41b_662x207.png) 重定向的时候不会去传递属性。 **注意:** 1. 如果需要携带数据到要跳转的界面,建议使用转发。地址栏不会改变。 2. 如果不需要携带数据到要跳转的界面,建议使用重定向。地址栏会改变 ## Cookie与Session ### Cookie Cookie(小甜饼)是浏览器保存在本地的文本内容,cookie常用于保存登录状态,用户资料等小文本。cookie是具有时效性的,有效的cookie内容会伴随着请求发送给Tomcat。比如我们可以使用cookie保存用户的登录信息,这样在一定时长内,用户就可以一直保持登录状态了。 ![](https://img.kancloud.cn/20/c9/20c9502c5eebab050851bfb8056335ba_1139x600.png) 该文件打开是一堆乱码,这是因为这个文件往往包含敏感数据,所以浏览器对此进行了加密。 ![](https://img.kancloud.cn/77/0f/770f8d9a7c2fa8cb36e0cc5acad9a3a7_1358x514.png) 设置Cookie ~~~ @WebServlet("/cookies/lg") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; public LoginServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("用户登录成功"); //设置用户七天内保持登录 Cookie cookie = new Cookie("user","admin"); cookie.setMaxAge(60*60*24*7); response.addCookie(cookie); response.getWriter().println("login success"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } ~~~ 若不设置有效期,则cookie有效期为当前浏览器窗口,若窗口关闭,则cookie清空 ![](https://img.kancloud.cn/90/f1/90f1365c427c48304763a1c41718e351_1365x517.png) 读取cookie ~~~ @WebServlet("/cookies/is") public class IndexServlet extends HttpServlet { private static final long serialVersionUID = 1L; public IndexServlet() { super(); // TODO Auto-generated constructor stub } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie[] cs = request.getCookies();//用于获取所用的用户信息 String user = null; for(Cookie c :cs) { System.out.println(c.getName() + ":" + c.getValue()); if(c.getName().equals("user")) { user = c.getValue(); break; } } if(user == null) { response.getWriter().println("user not login"); } else { response.getWriter().println("user:" + user); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } ~~~ 注意cookie是作用于本目录及其子目录,如果发送cookis那个文件的映射地址是/cookies/login,那么想要获取的那个也必须是/cookies/xx ~~~ @WebServlet("/cookie/is")//该地址获取不到对应的cookie public class IndexServlet2 extends HttpServlet { private static final long serialVersionUID = 1L; public IndexServlet2() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie[] cs = request.getCookies();//用于获取所用的用户信息 String user = null; for(Cookie c :cs) { System.out.println(c.getName() + ":" + c.getValue()); if(c.getName().equals("user")) { user = c.getValue(); break; } } if(user == null) { response.getWriter().println("user not login"); } else { response.getWriter().println("user:" + user); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } ~~~ ### session cookie是保存在我们本地的数据,但是这个数据不一定可靠,保存在本地迟早会被破解,而且设置cookie之后,每次发送请求都会携带cookie,增加了浏览器的带宽负担。于是,我们有了一个新的解决方案session,用于将数据保存在服务器上。 **session特点:** 1. Sesstion(用户会话)用于保存"浏览器窗口"对应的数据 2. Session的数据存储在Tomcat服务器的内存中,具有时效性(无人访问时长为30分钟) 3. Session通过浏览器Cookie的SessionId(浏览器的session识别码)值提取用户数据,每个浏览器的SessionId都不一样。 ~~~ @WebServlet("/session/sl") public class SessionLoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; public SessionLoginServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("用户登录成功"); //获取用户会话session HttpSession session = request.getSession(); session.setAttribute("name", "张三"); String sessionId = session.getId(); System.out.println(sessionId); request.getRequestDispatcher("/session/id").forward(request,response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } ~~~ ~~~ @WebServlet("/session/sil") public class SessionIndexServlet extends HttpServlet { private static final long serialVersionUID = 1L; public SessionIndexServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); String sessionId = session.getId(); System.out.println(sessionId); String name = (String)session.getAttribute("name"); response.setContentType("text/html;charset=utf-8");//设置返回内容解码方式 response.getWriter().println("这是首页,当前用户为:" + name); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } ~~~ #### session使用的原理 session 对象是由服务器自动创建的与用户请求相关的对象。服务器为每个用户都生成一个session对象,用于保存该用户的信息,跟踪用户的操作状态,服务器创建的每个session对象互不干涉。session是会话级别的变量,我们一般使用 session 处理用户的登陆信息。 简单的理解,打开一个浏览器,无论你打开多少标签页, 用 session 存储的变量都会存在,除非使用 session.removeAttribute() 将其显式销毁。 其实可以将session看做在Tomcat中存储的与客户端浏览器窗口绑定的数据存储空间。在使用的时候只需要使用`setAttribute`和`getAttribute`进行存值和取值即可。但是在底层却不是简单,是如何实现的呢? 当浏览器第一次创建session对象的时候会tomcat会在内存空间中开辟一个空间存放session数据,并且给session空间一个sessionid,tomcat在返回响应数据的时候会把sessionid一起返回给浏览器,浏览器把sessionid保存在cookie中,之后从浏览器传送过来的数据都通过sessionid来查找session的位置来保存数据。 ![](https://img.kancloud.cn/cb/7f/cb7fcfbb692c794da4d98da4cda513bf_974x506.png) session在工程的使用是非常广泛的,最常用的就是根据session可以与浏览器对应的原理,用于保存每个用户的登录信息。 ## ServletContext ServletContext(Servlet上下文对象),是web应用的上下文对象。在一个Web应用程序中只会存在一个ServletContext对象,该对象在Tomcat启动的时候创建,在Tomcat关闭的时候销毁。 ![](https://img.kancloud.cn/b4/f3/b4f326a183af0c3ca131ef855ca2a415_1357x424.png) 类似于这种网站备案信息和版权信息,会显示于整个网站全局,这个时候我们就可以使用ServletContext这种全局对象来进行设置。 ~~~ @WebServlet("/servletcontext/init") public class ServletContextInitServlet extends HttpServlet { private static final long serialVersionUID = 1L; public ServletContextInitServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取应用程序上下文对象,其实也就是应用程序对象 ServletContext sc = request.getServletContext(); //利用该对象的特性,设置作用范围为全局的自定义属性 sc.setAttribute("copyright", "Powered by EduSoho v8.6.4 ©2014-2020 课程存档 \n课程内容版权均归 南通在渡教育咨询有限公司 所有 苏ICP备18015371号"); //sc.setAttribute("copyright","");如果设置了相同的属性名,则新的属性值会覆盖旧的属性值,其他设置request自定义属性和session自定义属性也是相同的道理 sc.setAttribute("title", "渡课IT教育"); response.getWriter().println("init success"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } ~~~ ~~~ @WebServlet("/servletcontext/defualt") public class ServletContextDefaultServlet extends HttpServlet { private static final long serialVersionUID = 1L; public ServletContextDefaultServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext sc = request.getServletContext(); String copyright = (String)sc.getAttribute("copyright"); String title = (String)sc.getAttribute("title"); response.setContentType("text/html;charset=utf-8"); response.getWriter().println("<h1>" + title + "</h1>" + copyright); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } ~~~ ## Java Web三大作用域 * HttpServletRequest -请求对象 * HttpSession - 用户会话对象 * ServletContext - web应用全局对象 这三个对象的作用域,从上到下是依次递增的。 请求对象,它的生命周期最短,当浏览器发送请求到Tomcat,则请求对象就被创建,当servlet处理完成并返回响应到浏览器时,当前的请求对象就会被销毁。 用户会话对象用于保存与浏览器窗口对应的数据,该对象是在用户第一次向浏览器发送请求的时候被创建,默认情况下,这个对象如果在三十分钟后没有访问就会被销毁。注意一下,关闭浏览器该对象不会被销毁,销毁的是保存在浏览器cookie中的sessionId。就好像银行卡与存在银行中的钱一样,丢失了银行卡,但是银行中的钱还在,只是取不出来这笔钱而已。 全局对象在web应用启动的时候就被创建了,只有在web应用程序关闭或重启的时候才会被销毁。 有个注意点,为了程序维护的需要和资源避免浪费的情况,如果能用小作用域完成的任务就不用大作用域完成,所以request请求对象是以后使用的最多的对象 ## 中文乱码 中文乱码的核心就是解析字符集不支持中文,所以解决中文乱码的关键就是将默认字符集变成UTF-8,servlet中的请求与响应都需要设置为UTF-8。 ### Post请求中文乱码 ~~~HTML <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <form action="/servlet_advanced/charset/process" method="post"> 姓名:<input name="ename"> 地址:<input name="address"> <input type="submit" value="提交"> </form> </body> </html> ~~~ ~~~ @WebServlet("/charset/process") public class CharsetServlet extends HttpServlet { private static final long serialVersionUID = 1L; public CharsetServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //request.setCharacterEncoding方法用于将请求体中的字符集转换为UTF-8,对于get请求,没有请求体,所以该方法只对post请求生效。 request.setCharacterEncoding("UTF-8"); String ename = request.getParameter("ename"); String address = request.getParameter("address"); System.out.println(ename + ":" + address); //通过字符串构造器将字符串的解析字符集转换为utf-8,但是不怎么方便,所以使用setCharacterEncoding方法 //String utf8Ename = new String(ename.getBytes("iso-8859-1") , "utf-8"); //String utf8Address = new String(address.getBytes("iso-8859-1") , "utf-8"); //System.out.println(utf8Ename + ":" + utf8Address); } } ~~~ ### Get请求与响应中文乱码 ~~~ @WebServlet("/charset/process") public class CharsetServlet extends HttpServlet { private static final long serialVersionUID = 1L; public CharsetServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //对于Tomcat8.x的版本,默认get请求发送中文就是UTF-8的格式,因此无需转换 String ename = request.getParameter("ename"); String address = request.getParameter("address"); System.out.println(ename + ":" + address); response.setContentType("text/html;charset=utf-8"); response.getWriter().println(ename + ":" + address); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } ~~~ ## web.xml的常用配置 在本章节中,我们将做到以下功能: * 修改web应用默认首页 * Servlet通配符映射及初始化参数 * 设置404,500等状态码首页 **修改web应用默认首页** ~~~ <welcome-file-list> <!-- 指定默认首页,二级目录下的页面也可以作为默认首页,使用的时候需要在地址后面注意加/ --> <welcome-file>index.html</welcome-file> <welcome-file>default.html</welcome-file> </welcome-file-list> ~~~ **通配符映射,利用地址传参(非get提交)** ~~~ public class PatternServlet extends HttpServlet{ @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //查询员工的基本信息 //获取当前访问的URL String url = request.getRequestURL().toString(); System.out.println(url); String id = url.substring(url.lastIndexOf("/") + 1); int eid = Integer.parseInt(id); response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println(id); if(eid == 1) { out.println("张三"); }else if(eid == 2) { out.println("李四"); }else { out.println("其他员工"); } } } ~~~ ~~~ <servlet> <servlet-name>patternServlet</servlet-name> <servlet-class>com.dodoke.servlet.pattern.PatternServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>patternServlet</servlet-name> <!-- 使用*作为通配符,指的是pattern/后面不管是什么地址,都会被该servlet拦截请求 --> <url-pattern>/pattern/*</url-pattern> </servlet-mapping> ~~~ **设置全局参数** 在之前的学习中,我们在设置网站备案信息和版权信息时,是将内容写死在程序中的,这其实对我们的程序来说不算友好,现在我们可以尝试着将这些全局信息写入到配置文件中。 ~~~ <context-param> <param-name>copyright</param-name> <param-value>Powered by EduSoho v8.6.4 ©2014-2020 课程存档 \n课程内容版权均归 南通在渡教育咨询有限公司 所有 苏ICP备18015371号</param-value> </context-param> <context-param> <param-name>title</param-name> <param-value>渡课IT教育</param-value> </context-param> ~~~ ~~~ @WebServlet("/servletcontext/init") public class ServletContextInitServlet extends HttpServlet { private static final long serialVersionUID = 1L; public ServletContextInitServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext context = request.getServletContext(); //获取ServletContext对象通过配置文件设置的初始化参数 String copyright = context.getInitParameter("copyright"); context.setAttribute("copyright", copyright); String title = context.getInitParameter("title"); context.setAttribute("title", title); response.getWriter().println("init success"); } } ~~~ **设置404,500等状态码首页** ~~~ <!-- 指定错误页面 --> <error-page> <error-code>404</error-code> <location>/error/404.html</location> </error-page> <error-page> <error-code>500</error-code> <location>/error/500.jsp</location> </error-page> ~~~ ~~~ <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> 资源不存在 </body> </html> ~~~ ~~~ <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> 服务器内部错误,请联系管理员 </body> </html> ~~~ ## JSP九大内置对象 内置对象,又叫做隐含对象,不需要预先声明就可以在脚本代码和表达式中随意使用 1\. 由JSP规范提供,不用编写者实例化。  2\. 通过Web容器实现和管理  3\. 所有JSP页面均可使用  4\. 只有在脚本元素的表达式或代码段中才可使用 ![](https://img.kancloud.cn/30/a3/30a360c3b59eb052cec2413058bf403a_781x522.png) ~~~ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <% String url = request.getRequestURL().toString(); // HttpServletRequest response.getWriter().println(url);//HttpServletResponse %> <% out.println("<br>ABCCC"); session.setAttribute("user", "张三"); out.println((String)session.getAttribute("user")); %> <% String cp = application.getInitParameter("copyright") ; //ServletContext out.println("<hr/>"); out.println(cp); //pageContext可以帮助我们快速获取其他对象 pageContext.getRequest(); pageContext.getResponse(); pageContext.getSession(); pageContext.getServletContext(); %> </body> </html> ~~~ 利用exception对象显示错误信息。 ~~~ <!-- isErrorPage表示该页面专门用于显示错误 --> <%@ page contentType="text/html;charset=utf-8" isErrorPage="true"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> 服务器内部错误,请联系管理员 ,错误信息如下: <% String msg = exception.getMessage(); out.print("<br>" + exception.getClass().getSimpleName() + ":" + msg); %> </body> </html> ~~~ ## Java Web的打包与发布 在编写完成代码后,就需要正式的进行程序的上线了,那么我们该如何进行程序的上线呢? ![](https://img.kancloud.cn/cc/53/cc53624402c6babeaa11cf47fbadb729_890x413.png) ![](https://img.kancloud.cn/b6/07/b60718c050814901204124073071aea1_525x550.png) ![](https://img.kancloud.cn/fb/de/fbde58940fc7701af139ed19cbeee146_525x550.png) 直接将这样的war包,保存到Tomcat的webapp目录中,启动Tomcat就可以了。 注意: * 端口可以改为80,避免输入端口号 * 项目路径可以只保留斜杠,避免输入项目路径 * ![](https://img.kancloud.cn/21/96/21961c142ea3c3722fe4fd28da5b3809_1151x97.png)