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; } }