java学习与应用(4.4)–Tomcat、servlet等

  • 2020 年 2 月 23 日
  • 筆記

Tomcat配置

常用的web服务器软件:webLogic(oracle),webSphere(IBM),JBOSS(JBOSS公司)(以上三种支持所有JavaEE规范,企业版共13项规范),Tomcat(Apache基金,支持少量JavaEE规范) Tomcat:下载,解压使用。其中webapps存放网页,work存放运行数据,bin存放执行文件(shutdown.bat可关闭)。没有配置JAVA_HOME可能不能启动startup.bat。logs中存放日志信息记录一些错误等。netstat -ano查看端口使用的PID。conf配置目录的server.xml定义了tomcat的端口使用。 将代码打包为war包,放置到webapps下,会自动解压缩,和自动删除。server.xml的host标签下,定义Context自闭和标签中,定义docBase项目路径和path虚拟目录的属性便于访问。 常用的热部署并防止修改错误server.xml内容:方式为:conf下Catania下localhost下创建任意名称的xml文件,写入Context标签和属性,替换server.xml中的路径部署。 ROOT为项目根目录,WEB_INF为动态项目目录(web.xml为核心配置文件,classes目录存放字节码,lib存放jar包),其他为静态目录文件。 run->configuration ->Tomcat Server ->local->Application server中将tomcat集成到idea中。Java Enerprise -> Web Application,create server.xml勾选。等等配置。 idea直接修改可以使用热部署,不用重启服务器,进行代码调试,文件创建。idea也可以修改虚拟路径,方便使用。

servlet基础

Servlet(server applet 运行在服务器端的小程序),该接口定义了Java类规则(需要自定义实现),使得tomcat等能识别。 Servlet的方法重写,service方法提供服务, 然后在WEB_INF下的web.xml中配置servlet的servlet-name名称和servlet-class完全类名。在servlet-mapping标签中配置servlet-name和url-pattern路径名。url输入路径,执行全类名servlet实现重写的service方法。 执行原理:tomcat查找web.xml文件,按照请求的路径参数查找servlet-name,找到路径,全类名,调用全类名中实现的servlet接口的service方法。 servlet的方法:init方法在servlet创建时执行,只执行一次。service方法在每次访问都执行。destory方法在服务器正常关闭(servlet销毁)时执行(用于释放资源)。getServletConfig获取配置对象,getServletInfo获取信息,版本等。 servlet默认第一次访问时创建,也可在web.xml中指定创建时机(在servlet标签下使用load-on-startup,负数为第一次访问创建,非负为启动服务器就创建servlet)。 内存中只有一个servlet对象,多线程访问可能存在安全问题,一般不使用成员变量,或使用成员变量不进行赋值操作。 servlet3.0可以使用注解配置web.xml(不用创建web.xml)。注解(@WebServlet(配置信息))使用在类上进行配置。配置虚拟目录下的资源路径(可省略value=字段)。 IDEA对tomcat部署单独建立了配置文件,通过图形界面修改该部分内容。文件在工作空间项目进行编辑,idea部署位置存储在out目录,供tomcat访问。WEB_INF下的静态资源无法访问。

servlet内容

Servlet的实现类:GenericServlet抽象类(只需要复写service方法),HttpServlet类(service需要判断请求方式分别处理,在该类中以定义,继承该类,复写doGet和doPost方法即可方便使用)。 servlet的注解配置urlpatterns数组,可设置多个资源路径(可写*作为通配符,优先级较低,也有*.do等表示方式)指向一个servlet。 HTTP协议(Hyper Text Transfer Protocol超文本传输协议,基于TCP/IP协议,默认80端口,基于请求响应模型,每次请求相互独立,请求间不能相互通信(1.0每次响应都建立新连接,1.1则复用连接)) 请求消息数据格式:请求行(请求方式 请求url 请求HTTP版本),请求头(参数名 参数),请求空行(一空行),请求体/请求正文(请求参数[如表单post提交的信息,get方式则在请求行中显式参数])。 请求头中User-Agent可以用于服务器对不同浏览器的兼容视图,Referer提供了来源地址,用于服务器识别并是否拒绝连接(防止盗链),也可用作统计工作。

request、response

tomcat创建selvlet对象后,创建Request(封装请求数据)和Response对象,传递给selvlet的service方法。用户通过request和response对象获取消息和设置响应消息。 request对象继承ServletRequest下的HttpServletRequest下的RequestFacade类。 获取请求行(getMethod方法)。获取虚拟目录(getContextPath),获取Servlet路径(getServletPath),获取请求参数(getQueryString),获取请求URI(getRequestURI,getRequestURL),获取协议(getProtocol),获取客户机IP(getRemoveAddr) URL:统一资源定位符,URI统一资源标识符。 获取请求头(getHeader[返回字符串,传入键值数据等] getHeaderNames[返回枚举字符串组])。referer关键字给出了来源的URL地址<–。页面显示数据:response.setContentType("text/html;charset=utf-8");response.getWriter()/write("内容"); 请求体的数据(只有POST的请求方式),先获取流对象(getReader获取字符流,getInputStream获取字节流),再取数据(流方式方法,如readLine等)。 通用获取请求参数:getParameter方法,传入参数[键值],返回字符串。getParameterValues方法,返回字符串数组(用于复选框等)。getParameterNames方法,返回所有请求参数枚举键值。getParameterMap返回所有参数的map集合。 中文数据作为请求信息,使用GET不会乱码,使用POST方式设置流编码request.setCharacterEncoding('utf-8');解决。

请求转发、共享数据等

请求转发:资源跳转方式(servlet之间)。通过request对象获取请求转发对象(getRequestDispatcher方法,传入资源路径)并使用RequestDispatcher对象的forward传入参数进行转发。 转发时浏览器地址栏不变,只能服务器本地内部跳转,转发是一次请求,多次处理。 共享数据:域对象:一个有作用范围的对象。request域对象使用在一次请求范围,转发让多个servlet共享。使用方法:setAttribute存储数据,getAttribute通过键值获取数据,removeAttribute删除。 获取ServletContext对象:getServletContext方法获取该对象。 dao中存放了数据库操作的类,util工具包,test测试包,web网页包,domain数据域包。 BeanUtil工具(apache提供,用于封装JavaBean),获取的参数以map形式存在后放入到对象中(BeanUtil.populate方法传入对象和数据map参数)。 JavaBean是Java标准类,被public修饰,提供空参构造,private成员变量,getter,setter。用于封装数据。包含setProperty(设置值)方法和getProperty(获取值)方法,populate(设置所有值)方法。

HTTP协议的响应头

HTTP协议:响应消息用于浏览器解析。分为响应行(协议,版本,状态码),响应头,响应空行,响应体(返回的传输文本)。 状态码:1xx服务器接收客户端但没有发送完。2xx成功,3xx重定向资源(302服务器返回后浏览器自动跳转地址,304表示让浏览器访问缓存),4xx客户端错误(404路径没有资源,405请求方式没有对应方法)5xx服务器错误。 响应头:Content-Type响应体数据和编码格式,Content_disposition告诉客户端打开响应体的格式(默认in-line,attachment以附件形式打开),location重定向地址等。 Response对象:设置状态码setStatus,设置响应头,setHeader(键,值),设置响应体/获取输出流(getWriter,getOutputStream方法)。sendRedirect方法简化重定向(之前修改响应行和响应头重定向) 重定向不同于转发(2次请求,可外部转地址,不可共享数据),转发是服务器本地的servlet之间的,一次请求的,地址栏不变的,能共享数据的。 服务器中的绝对路径,在URL中简化前端的域名,值以/开头。相对路径以./或省略其进行开头,不以/开头。selvlet之间的转发不需要写虚拟目录(转发由服务器本地发出,客户端发出的请求需要写虚拟目录)。 客户端请求的路径建议使用request.getContextPath动态获取虚拟目录,并拼接,增强代码健壮性。 服务器输出字符数据到浏览器:获取字符输出流输出数据(response.getWriter对象(默认ISO-8859-1编码),其他刷新释放等操作自动执行),使用write写入。 response.setCharacterEncoding方法设置编码,response.setHeader中设置content-type的charset,设置流和浏览器的默认编码。相同功能的response.setContentType简化操作。 获取字节流数据response.getOutputStream,使用write方法(传入字符流转换字节后可以传入charset设置,但建议简化的操作)。 验证码:由程序动态生成,使用BufferdImage对象创建图像,然后使用getGraphics获取画笔,使用画笔的setColor,fillRect,drawRect,drawString在画布上进行绘制,使用ImageIO.write方法,可以将图片输出到字节输出流。 验证码使用js切换时,修改src的值为相同的值(给src传入不重复的无意义参数,以防止缓存,一般使用时间毫秒作为参数)

ServletContext对象

ServletContext对象:代表整个web应用,可以和程序的服务器通信。使用request.getServletContext,this.getServletContext获取对象 获取MIME类型(互联网通信过程中的一种文件类型,格式为大类型/小类型如text/html):其父mime存储在tomcat的conf下的web.xml中存在有,getMimeType获取文件类型。 域对象(如request对象):域对象可以共享数据,即可以使用getServletContext的ServletContext对象的setAttribute添加数据,removeAttribute,getAttribute获取数据。该域范围可在不同请求数据用户间传递,并在服务器开启时长期驻留。 获取文件的真实路径:ServletContext的getRealPath方法获取文件的服务器实际路径,包含WEB-INF文件夹的路径作为跟路径/然后传入文件。

文件下载实例

文件下载示范代码:包含了修改请求头,获取文件,输入输出流,DownLoadUtil工具类方法等。

download.html

<!DOCTYPE html>  <html lang="en">  <head>      <meta charset="UTF-8">      <title>Title</title>  </head>  <body>      <a href="/day15/img/1.jpg">图片1</a>      <a href="/day15/img/1.avi">视频</a>      <hr>      <a href="/day15/downloadServlet?filename=九尾.jpg">图片1</a>      <a href="/day15/downloadServlet?filename=1.avi">视频</a>  </body>  </html>

DownloadServlet.java

package cn.itcast.web.download;    import cn.itcast.web.utils.DownLoadUtils;    import javax.servlet.ServletContext;  import javax.servlet.ServletException;  import javax.servlet.ServletOutputStream;  import javax.servlet.annotation.WebServlet;  import javax.servlet.http.HttpServlet;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  import java.io.FileInputStream;  import java.io.IOException;    @WebServlet("/downloadServlet")  public class DownloadServlet extends HttpServlet {      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {          //1.获取请求参数,文件名称          String filename = request.getParameter("filename");          //2.使用字节输入流加载文件进内存          //2.1找到文件服务器路径          ServletContext servletContext = this.getServletContext();          String realPath = servletContext.getRealPath("/img/" + filename);          //2.2用字节流关联          FileInputStream fis = new FileInputStream(realPath);            //3.设置response的响应头          //3.1设置响应头类型:content-type          String mimeType = servletContext.getMimeType(filename);//获取文件的mime类型          response.setHeader("content-type",mimeType);          //3.2设置响应头打开方式:content-disposition            //解决中文文件名问题          //1.获取user-agent请求头、          String agent = request.getHeader("user-agent");          //2.使用工具类方法编码文件名即可          filename = DownLoadUtils.getFileName(agent, filename);            response.setHeader("content-disposition","attachment;filename="+filename);          //4.将输入流的数据写出到输出流中          ServletOutputStream sos = response.getOutputStream();          byte[] buff = new byte[1024 * 8];          int len = 0;          while((len = fis.read(buff)) != -1){              sos.write(buff,0,len);          }            fis.close();          }        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {          this.doPost(request,response);      }  }

DownLoadUtils.java

package cn.itcast.web.utils;  import sun.misc.BASE64Encoder;  import java.io.UnsupportedEncodingException;  import java.net.URLEncoder;  public class DownLoadUtils {      public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {          if (agent.contains("MSIE")) {              // IE浏览器              filename = URLEncoder.encode(filename, "utf-8");              filename = filename.replace("+", " ");          } else if (agent.contains("Firefox")) {              // 火狐浏览器              BASE64Encoder base64Encoder = new BASE64Encoder();              filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";          } else {              // 其它浏览器              filename = URLEncoder.encode(filename, "utf-8");          }          return filename;      }  }