善用页面搜索,h6标题不能生成目录
Tomcat
Tomcat 服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用
户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。
支持Servlet和JSP 规范,且最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现。
安装
到官网下载即可
Tomcat目录结构
bin:脚本目录
启动脚本:startup.bat
停止脚本:shutdown.bat
conf:配置文件目录 (config /configuration)
核心配置文件:server.xml
用户权限配置文件:tomcat-users.xml
所有web项目默认配置文件:web.xml
lib:依赖库,tomcat和web项目中需要使用的jar包
logs:日志文件.
localhost_access_log..txttomcat记录用户访问信息,星表示时间。
例如:localhost_access_log.2018-07-07.txt
temp:临时文件目录,文件夹内内容可以任意删除。
webapps:默认情况下发布WEB项目所存放的目录。
work:tomcat处理JSP的工作目录。
配置和发布
创建模块
部署模块
进入设置
进入Deployment
在Application context那里配置路由
点右边的小铅笔,进入发布配置
改变输出目录到tomacat的webapps下面。最好自己在后面加个路径,因为以后可能是多个模块,每个模块单独放一个文件夹
另外需要注意的是,导包后,打开project structure->problem->fix修复,lib与web项目关联
如果不关联,可能只能在当前开发时可用,但是项目发布是失败
Servlet类
Servlet 运行在服务端的Java小程序,是sun公司提供一套规范,用来处理客户端请求、响应给浏览器的动态资源
Servlet是JavaWeb三大组件之一(Servlet、Filter、Listener),且最重要。
编写步骤
继承Servlet接口
- 定义类, 实现 Servlet接口
- 重写 service方法 , 当浏览器访问此类, 会自动执行 service 方法。
- 编写 web.xml 配置文件 . 在文件配置我们 HelloServlet 的信息
配置方式
xml:
servlet 类信息
servlet 路径信息
<!-- 表示 Servlet 类 -->
<servlet>
<!-- 表示 servlet类的名字 , 格式任意起名 ,建议见名知意 -->
<servlet-name>hello</servlet-name>
<!-- 表示 servlet类的 路径 , 全类名 -->
<servlet-class>hm01_hello.HelloServlet</servlet-class>
</servlet>
<!-- 表示 Servlet 类 配置的路径 , 用于浏览器访问-->
<servlet-mapping>
<!-- 表示 servlet类的名字 , 与前面Servlet标签中 name 一致 -->
<servlet-name>hello</servlet-name>
<!-- 表示 servlet类 在浏览器中虚拟路径 -->
<url-pattern>/h</url-pattern>
</servlet-mapping>
注解:
Servlet3.0新增了一些注解,用来简化的javaweb代码开发
//name = "HelloServlet":servlet名称,相当于web.xml中的<servlet-name>
//urlPatterns = "/hello":servlet的访问路径,相当于<url-pattern>
@WebServlet(name = "HelloServlet",urlPatterns = "/hello")
可以直接写urlPatterns
相关方法
servletRequest
这个对象在service的参数列表中
所有的提交的数据,都以键值对保存在里面。用key可以拿到里面的数据,返回的是字符串形式
servletRequest.getParameter("key")
servletResponse
回写数据 , 打印回在浏览器上 。
servletResponse.getWriter().print();
print()不定,可以调用其他方法
继承HttpServlet接口
doGet()方法用于处理get请求。
doPost()方法用于处理post请求。
HttpServletRequest相关方法
获取值的方法
getParameter(String s)
:返回一个字符串,值是键为s的值
getParameterValues(String s)
:返回一个字符串数组
getParameterMap()
:保存所有提交参数。表单中的name的值为key, value 为String[]的值
Map<String, String[]> parameterMap = request.getParameterMap();
// 遍历数组
Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
// 通过键值对 获取key 和value
for (Map.Entry<String, String[]> entry : entries) {
String key = entry.getKey();
String[] value = entry.getValue();
System.out.println(key +" -- " + Arrays.toString(value));
常见请求头
获取请求行中信息的相关方法
调用方法后的结果
获取请求头信息的相关方法
示例代码
public class Req3Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 解析请求头
String host = request.getHeader("host");
System.out.println(host);
// 获取所有的头的键 -- 返回枚举类型 .
Enumeration<String> names = request.getHeaderNames();
// 枚举类型的遍历 - 枚举 就相当于你学的迭代器 .
while (names.hasMoreElements()) { // hasMoreElements --> hasNext
String s = names.nextElement(); // nextElement --> next
System.out.println(s);
// 获取 值
String value = request.getHeader(s);
System.out.println(s +" -- " + value);
}
}
}
获取请求参数
在实际开发中,经常需要获取用户提交的表单数据,例如,用户名、密码、电子邮件等,为了方便获取表单中的请求参数,在HttpServletRequest接口中,定义了一系列获取请求参数的方法
表中,列出了HttpServletRequest获取请求参数的一系列方法。其中,getParameter()方法用于获取某个指定的参数,而getParameterValues()方法用于获取多个同名的参数。
getParameterMap()方法配合BeanUtils使用,将发送的数据用对象保存
Request对象保存数据
Request对象不仅可以获取一系列数据,还可以通过属性传递数据。在ServletRequest接口中,定义了一系列操作
属性的方法,具体如下:> 只有属于同一个请求中的数据才可以通过ServletRequest对象传递数据
RequestDispatcher对象(重要)
RequestDispatcher接口
当一个Web资源收到客户端的请求后,如果希望服务器通知另外一个资源去处理请求,这时,除了使sendRedirect()方法实现请求重定向外,还可以通过RequestDispatcher接口的实例对象来实现。在ServletRequest接口中定义了一个获取RequestDispatcher对象的方法
获取到RequestDispatcher对象后,最重要的工作就是通知其它Web资源处理当前的Servlet请求,为此,在RequestDispatcher接口中,定义了两个相关方法
列举的两个方法中,forward()方法可以实现请求转发,include()方法可以实现请求包含(就是将当前页面和被包含页面的输出结果,合并一起响应给浏览器)
跟重定向不一样的是,重定向是游览器多次请求。最后的地址栏会变。但请求转发游览器只向服务器请求一次,请求在服务器内多次转发,最后的地址栏地址不会变。
请求转发可以携带数据,重定向只能用Servlet来传递数据
示例代码
AServlet
@WebServlet(urlPatterns = "/a")
public class AServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
/*
请求 转发:
getRequestDispatcher : 获取转发器 , 参数地址 , 不需要添加 项目的名称 , 直接填写 资源路径即可.
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 使用 request 保存 数据 .
request.setAttribute("name" , "tom");
// 转发 到 BServlet 中
// 1. 获取转发器
// 这里是同一个项目中(模块?),所以不用加项目名
RequestDispatcher rd = request.getRequestDispatcher("/b");
// 2. 发送 (走你)
rd.forward(request ,response);
}
}
BServlet
@WebServlet(urlPatterns = "/b")
public class BServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("BServlet.doGet");
// 获取request 对象 保存数据
Object name = request.getAttribute("name");
// 回写到页面
response.getWriter().println(name);
}
}
中文乱码问题
Tomcat 8 以后get方式自动处理了,post方式没有解决。
由于HTML设置了浏览器在传递请求参数时,采用的编码方式是UTF-8,但在解码时采用的是默认的ISO8859-1,因此会导致乱码的出现。
解决:
在HttpServletRequest
接口中,提供了一个setCharacterEncoding()
方法,该方法用于设置request对象的解码方式
HttpServletResponse
也有类似的方法response.setContentType("text/html;charset=utf-8");
@WebServlet(urlPatterns = "/ch")
public class ChinaServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
/*
获取请求中的中文数据.
GET 方式请求: 自动处理 tomcat8特性.
POST 方式 : 依然乱码 . 通过
setCharacterEncoding 设置编码
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取 参数前 ,设置请求对象中编码
request.setCharacterEncoding("utf-8");
// 设置 回写的编码
response.setContentType("text/html;charset=utf-8");
String name = request.getParameter("name");
System.out.println(name);
response.getWriter().println(name);
}
}
HttpServletResponse
在Servlet API中,定义了一个HttpServletResponse接口,它继承自ServletResponse接口,专门用来封装HTTP响应消息,由于HTTP响应消息分为状态行、响应消息头、消息体三部分,因此,在HttpServletResponse接口中定义了向客户端发送响应状态码、响应消息头、响应消息体的方法。
发送状态码相关的方法
当Servlet向客户端回送响应消息时,需要在响应消息中设置状态码。
setStatus(int status)
:该方法用于设置HTTP响应消息的状态码,并生成响应状态行。由于响应状态行中的状态描述信息直接与状态码相关,而HTTP版本由服务器确定,因此,只要通过setStatus(int status)方法设置了状态码,即可实现状态行的发送。需要注意的是,正常情况下,Web服务器会默认产生一个状态码为200的状态行。
/*
响应行 : 状态码: 200
版本:HTTP/1.1
响应头 :
Content-Length :12
Date :Sat, 25 May 2019 02:48:14 GMT
响应体: 正文内容
hello resp
=============================================================================
setStatus(int i) : 可以用来设置状态码 , 通常 tomcat 去设置 ,我们几乎不会调用.
此状态码只是描述作用 , 无法真实反映代码实际状态.
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置 响应行 -- 状态码
response.setStatus(500); // 表示200 成功 , 500 表示 出现异常 .
// 回写内容
response.getWriter().print("hello resp");
}
发送响应消息头相关的方法
当Servlet向客户端发送响应消息时,由于HTTP协议的响应头字段有很多种,为此,在HttpServletResponse接口中,定义了一系列设置HTTP响应头字段的方法。
addHeader(key, value)
:添加头信息键值对, 键可以重复.setHeader(key,value)
: 设置头信息键值对, 键唯一的. 键重复时, 后面值覆盖前面的值.
/*
添加头信息 : addHeader(key, value) , 添加头信息键值对, 键可以重复.
设置头信息: setHeader(key,value) , 设置头信息键值对, 键唯一的. 键重复时, 后面值覆盖前面的值.
=========================
了解 : setIntHeader setDateHeader ,几乎不会调用 ,因为 字符串类型可以替代.
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 添加 头信息
// response.addHeader("name" , "tom");
// response.addHeader("name" , "tom");
// response.addHeader("name" , "tom");
// 设置头信息
response.setHeader("name" , "tom");
response.setHeader("name" , "tom");
response.setHeader("name" , "tom");
response.setHeader("name" , "tommy");
response.setHeader("Date" , new Date().toString());
}
其他方法:
响应头信息
应答头 | 说明 |
---|---|
Allow | 服务器支持哪些请求方法(如GET、POST等)。 |
Content-Encoding | 文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept-Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。 |
Content-Length | 表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入 ByteArrayOutputStream,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream()发送内容。 |
Content-Type | 表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。 |
Date | 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。 |
Expires | 应该在什么时候认为文档已经过期,从而不再缓存它? |
Last-Modified | 文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。 |
Location | 表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。 |
Refresh | 表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。 注意这种功能通常是通过设置HTML页面HEAD区的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的HTML编写者十分重要。但是,对于Servlet来说,直接设置Refresh头更加方便。 注意Refresh的意义是"N秒之后刷新本页面或访问指定页面",而不是"每隔N秒刷新本页面或访问指定页面"。因此,连续刷新要求每次都发送一个Refresh头,而发送204状态代码则可以阻止浏览器继续刷新,不管是使用Refresh头还是<META HTTP-EQUIV="Refresh" ...>。 注意Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它。 |
Server | 服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。 |
Set-Cookie | 设置和页面关联的Cookie。Servlet不应使用response.setHeader("Set-Cookie", ...),而是应使用HttpServletResponse提供的专用方法addCookie。参见下文有关Cookie设置的讨论。 |
WWW-Authenticate | 客户应该在Authorization头中提供什么类型的授权信息?在包含401(Unauthorized)状态行的应答中这个头是必需的。例如,response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")。 注意Servlet一般不进行这方面的处理,而是让Web服务器的专门机制来控制受密码保护页面的访问(例如.htaccess)。 |
中文乱码问题:因为没有设置解析为utf-8
在响应之前,调用setContentType("text/html;charset=utf-8"); 设置解析方式解决
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 测试 自动跳转 : // 格式 : "时间(秒); URL=地址" response.setHeader("Refresh","5; URL=https://www.baidu.com"); // 处理响应 中文 , 回写之前设置utf8编码 response.setContentType("text/html;charset=utf-8"); response.getWriter().println("5 秒 自动跳转到 baidu.co"); }