javaweb----servlet
在正式看servlet前先补充一些小知识
web应用目录
下图为web应用目录,为了保证程序开发的正确性和规范性,大家的项目应当按照这样的结构去展开。
web.xml文件
web.xml文件就是web项目的设置中心,你可以在这里实现你想对项目的设置。
如配制web应用默认页面:
<welcom-file-list>
<welcom-file>index.html</welcom-file>
<welcom-file>index.htm</welcom-file>
<welcom-file>index.jsp</welcom-file>
</welcom-file-list>
当用户访问web应用时,如果没有具体要访问的页面资源,tomcat会按照元素指定默认页面的顺序,一次查找这些默认页面。
Servlet开发入门
Servlet接口及其实现类
Servlet接口位于javax.servlet.Servlet
在Setvlet接口中定义了5个抽象方法
图源于API
图源于百度
针对Servlet接口,SUN公司提供了两个默认的接口实现类:GenericServlet和HttpServlet。其中GenericServlet是抽象类并没有实现Http请求处理;HttpServlet继承了GeneriServlet的所有方法。并且为HTTP请求的POST、GET等类型提供了具体的操作方法。
使用eclipse工具开发Servlet
创建servlet
()
在项目正式开始前,简单说明一下servlet引入项目的两种方式:
1、注解(Servlet3.0及其以后版本支持)【推荐使用】
在Servlet文件中形成引入
@WebServlet("/HelloWorld")【包servlet.annotation.WebServlet】
推荐理由:
- 简洁、便于修改
- 不容易形成覆盖
2、web.xml(Servlet3.0及其以后版本需要手动设置否则默认注解方式)
通过四个子元素来引入
<servlet>
<servlet-name>HelloWorld</servlet-name>
<servlet-class>servlet.HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name>
<url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>
需要注意的是,这两种方法不能同时使用。
一个简单的小例子:此处使用的为注解方式
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class servletDemo
*/
@WebServlet("/servletDemo")
public class servletDemo extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("This Sevlet has been created by eclipse");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
使用配制web.xml方法
<servlet>
<servlet-name>servletDemo</servlet-name>
<servlet-class>servlet.servletDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servletDemo</servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>
可以注意到url-pattern那有一些特殊,这里用到了Servlet映射路径通配符。
servlet映射路径通配符“ * ”,使用的格式有两种:具体如下。
- 格式为“ *.扩展名 ”,例如“ *.do ”匹配以“ .do ”结尾的所有URL地址;
- 格式为“ /* ”例如“ /abc/* ”匹配以“ /abc ”开始的所有URL的地址;
所有当我将URL输入为下面的形式也能显示出正常的页面,不会报错
http://localhost:8080/FirstWebProject/servlet/servlet.servlet123
设置缺省Servlet:当找不到匹配servlet-mapping时交给缺省servlet
<servlet>
<servlet-name>servletDemo</servlet-name>
<servlet-class>servlet.servletDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servletDemo</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
ServletConfig和ServletContext接口
ServletConfig和ServletContext分别相当于设置局部变量和设置全局变量。
ServletConfig接口比较简单,其作用为获取 Web应用程序的初始化参数,所以献上一个例子就不做过多阐述;
<servlet>
<servlet-name>TestServlet02</servlet-name>
<servlet-class>cn.itcast.servlet.TestServlet02</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
传递数据的方法:
web.xml >> ServletConfig >> Init >> Servlet
ServletConfig config = this.getServletConfig();
// 获得参数名为encoding对应的参数值
String param = config.getInitParameter("encoding");
out.println("encoding=" + param);
ServletConfig的常用方法
ServletContext接口
作用:
- 获取 Web应用程序的初始化参数
- 实现多个Servlet对象共享数据
- 读取Web应用下的资源文件
<context-param>
<param-name>address</param-name>
<param-value>beijing</param-value>
</context-param>
传递数据的方法:
web.xml >> ServletContext >> Init >> Servlet
ServletContext context = this.getServletContext();
// 得到包含所有初始化参数名的Enumeration对象
Enumeration<String> paramNames = context.getInitParameterNames();
// 遍历所有的初始化参数名,得到相应的参数值,打印到控制台
out.println("all the paramName and paramValue are following:");
// 遍历所有的初始化参数名,得到相应的参数值并打印
while (paramNames.hasMoreElements()) {
String name = paramNames.nextElement();
String value = context.getInitParameter(name);
out.println(name + ": " + value);
out.println("<br>");
多个servlet共享数据
<Demo01.java>
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class firstservlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// response.setCharacterEncoding("utf-8");
// PrintWriter out = response.getWriter();
// out.println("Hello World哈哈哈哈");
// System.out.println("运行");
ServletContext context = this.getServletContext();
context.setAttribute("coding", "UTF-8");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doPost(req, resp);
}
}
<Demo02.java>
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class servletDemo
*/
//@WebServlet("/servlet")
public class servletDemo extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String str = (String)context.getAttribute("coding");
PrintWriter out = response.getWriter();
out.println(str);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
在浏览器输入http://localhost:8080/FirstWebProject/servlet
读取Web应用下的资源文件
常用方法说明:
- Set getResourcePaths(String path):返回一个set集合,为相对路径
- String getRealPath(String path):返回资源文件在服务器文件系统上的真实路径(绝对路径);
<itcast.propties>
name = kim
password = kim123
<servletDemo.java>
package servlet;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class servletDemo
*/
//@WebServlet("/servlet")
public class servletDemo extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
ServletContext context = this.getServletContext();
/*Java Resources下的src目录其实就是Web-INF下的classes目录*/
InputStream in = context.getResourceAsStream("/WEB-INF/classes/itcast.propties");
Properties pros = new Properties();
pros.load(in);
out.println("name:"+pros.getProperty("name")+"<br />");
out.println("password:"+pros.getProperty("password")+"<br />");
// String str = (String)context.getAttribute("coding");
// out.println(str);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
接口常用方法
servlet的请求和响应
HttpServletRespons接口对象,继承自ServletResponse,专门用来封装HTTP响应消息。在该接口中定义了向客户端发送响应状态码、响应消息头、响应消息体。
HttpServletResponse : 戳它
发送响应消息头相关的三个重点方法:
void setContentType(Stirng type):
- 用于设置Servlet输出内容的MIME类型
- 设置字符编码集
一个栗子:
response.setContentType(“text/html;charset=utf-8”);
void setCharacterEncoding(String ):
- 设置输出内容使用的字符编码
void addIntHeader(java.lang.String名称,整数值)
添加具有给定名称和整数值的响应标头。此方法允许响应标头具有多个值。
参数:
name -标头名称
value -分配的整数值
功能:实现页面定时刷新
发送响应消息头相关的方法:IO流理念
ServletResponse中定义了两个与输出流相关的方法:
getWriter();
getOutputStream();
区别:
1、getWriter()用于向客户机回送字符数据
2、getOutputStream()返回的对象,可以回送字符数据,也可以回送字节数据(二进制数据)
如何选择:
若果我们回送字符数据,则使用PrintWriter对象,效率高
如果我们回送字节数据,只能用OutputStream
注意:
PrintWriter和OutputStream不能同时使用
PrintWriter out=response.getWriter();
out.println("abc");
OutputStream os=response.getOutputStream();
os.write("hello,world".getBytes());
解决中文输出乱码问题
计算机的数据都是以二进制的形式存储的,当传输文本时会发生字符和字节之间的转换。字符和字节之间的转换实通过查码表完成的,将字符转换成为字节的过程称为编码,反之为解码;乱码则意味着编码和解码用的码表不一致。故,解决的此问题的方案为:调整response编码码表、浏览器解码码表,使其一致。
方式一:
response设置编码:
response.setCharacterEncoding(“UTF-8”);
通知浏览器使用特定的码表解码
response.setHeader(“Content-type”,“text/html;charset=utf-8”);
方式二:
response.setContentType(“text/html;charset=utf-8”);
实现页面跳转
response.setHeader(“Refresh”,“3;URL=https://www.baidu.com”);
实现请求重定向
利用sendRedirect实现
sendRedirect工作原理
ewsponse.sendRedirect(“http://www.baidu.com”);
HttpServletRequest对象
包括了获取请求行、请求头和请求消息体
获取请求行信息
获取消息头
实现利用Referer请求头请求防止盗链
Referer的的作用是指示一个请求是从哪里链接过来,那么当一个请求并不是由链接触发产生的,那么自然也就不需要指定这个请求的链接来源,如:直接在浏览器的地址栏中输入一个资源的URL地址,那么这种请求是不会包含 Referer 字段的,因为这是一个“凭空产生”的 HTTP 请求,并不是从一个地方链接过去的。服务器允许 Referer 为空,意味着服务器允许浏览器直接访问。
利用Referer防盗链
一些站点为了吸引人气提高访问量,提供了各种软件的下载页面,倒是本身却没有资源,而只是提供超链接指向其他站点上的资源。为防止分流,我们需要进行防盗链。
【referrer中文解释:推荐人、引路人】,根据这个意思,我们便能快速理解防盗链的原理了,通过referer检查是否在自己的网站上发起的请求,而不是别人的网页
一个栗子
package cn.itcast.chapter04.request;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class DownManagerServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
// 获取referer头的值
String referer = request.getHeader("referer");
// 获取访问地址
String sitePart = "http://" + request.getServerName();
// 判断referer头是否为空,这个头的首地址是否以sitePart开始的
if (referer != null && referer.startsWith(sitePart)) {
// 处理正在下载的请求
out.println("dealing download ...");
} else {
// 非法下载请求跳转到download.html页面
RequestDispatcher rd = request
.getRequestDispatcher("/download.html");
rd.forward(request, response);
}
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
doGet(request, response);
}
}
获取请求参数
解决请求参数的中文乱码问题
在填写表单时,难免会输入中文,如姓名、公司名等。由于HTML设置了默认编码为ISO-8859-1,因此会导致乱码出现。
解决方法:将浏览器编码和服务器解码设为一致。
对于request中的乱码的解决方法和在response中有所不同,POST方式和GET方式的解决方式不一致。
POST解决方式 :
request.setCharacherEncoding(“utf-8”);
GET解决方式: 解决GET方式提交表单时乱码,可以先对得到的字符串name使用错误码表ISO-8859-1将其重新编码,然后使用码表UTF-8进行解码。
name = new String(name.getBytes(“iso8859-1”,“utf-8”));
通过Request对象传递数据
Request对象不仅可以获取一系列数据,还可以通过属性传递数据。
ServletRequest接口中的一系列操作属性的方法:
setAttribute()方法
public void setAttribute(变量名,值对象);
getAttribute()方法
Object getAtrribute(变量名);
removeAttribute()方法
public void removeAttribute(变量名);
getAttributeNames()方法:该方法用于返回一个包含ServletRequest对象中的所有属性名的Enumeration对象,在此基础上,可以对ServletRequest对象中的所有属性进行遍历处理。
public Enumeration getAtrributeNames();
RequestDispatcher接口对象
可以用该接口的forword方法实现:让服务器通知另外一个资源去处理请求。注意:此接口与sendRedirect作用上有类似,但其有本质区别。
forword原理图
一个栗子:
RequestForwardServlet.java
package com.demo;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class RequestForwardServlet
*/
public class RequestForwardServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
//将数据存储在request对象中
request.setAttribute("company", "Kim集团");
//访问另一个servlet
RequestDispatcher dispatcher = request.getRequestDispatcher("/ResultServlet");
dispatcher.forward(request, response);
}
}
ResultServlet.java
package com.demo;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ResultServlet
*/
public class ResultServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("公司名称: "+request.getAttribute("company"));
}
}
效果图:
再来一个栗子
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="FirstServlet" method="post">
<table width="298" border="0" align="center" cellpading="2" callspacing="1">
<tr>
<td align="right">学号: </td>
<td align="left"><input type="text" name="snumber" size="15"></td>
</tr>
<tr>
<td align="right">姓名: </td>
<td align="left"><input type="text" name="sname" size="15"></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="登录"><input type="reset" value="取消"></td>
</tr>
</table>
</form>
</body>
</html>
Student.java
package com.demo;
public class Student {
private String snoString="123";
private String snameString="123";
public Student(String snoString,String snamString) {
this.snoString = snoString;
this.snameString = snamString;
}
public void setsno(String snoString) {
this.snoString = snoString;
}
public String getsno() {
return snoString;
}
public void setsname(String snaString) {
this.snameString = snameString;
}
public String getsname() {
return snameString;
}
}
FirstServlet.java
package com.demo;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class FirstServlet
*/
public class FirstServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String snumber = request.getParameter("snumber");
String sname = request.getParameter("sname");
Student student = new Student(snumber, sname);
request.setAttribute("student", student);
// response.sendRedirect("/Demo05/SecondServlet");
RequestDispatcher view = request.getRequestDispatcher("SecondServlet");
view.forward(request, response);
}
}
SecondServlet.java
package com.demo;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class SecondServlet
*/
public class SecondServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//设置发送到客户端的响应类型
response.setContentType("text/html;charset=utf-8");
Student student = (Student)request.getAttribute("student");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<center>");
out.println("学号:"+student.getsno()+"<br />");
out.println("姓名:"+student.getsname()+"<br />");
out.println(" <a href=\"/Demo05/input.html\">返回输入界面</a> ");
out.println("</center>");
out.print("</html></body>");
}
}