Web-第九天 ServletContext&Response&request学习
今日内容介绍
今日内容学习目标
登录成功后,5秒后跳转到某个页面,在页面中显示您是第x位登录成功的用户.
服务器启动的时候,为每个WEB应用创建一个单独的ServletContext对象,我们可以使用这个对象存取数据,用这个对象存取的数据可以在整个WEB应用中获得。可以使用如下方法存取数据
方法名 | 描述 |
---|---|
setAttribute(String name,Object object) | 向ServletContext中存数据 |
getAttribute(String name) | 从ServletContext中取数据 |
removeAttribute(name) | 从ServletContext中移除数据 |
/**
* 登录代码的Servlet
*/
public class UserCountServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void init() throws ServletException {
// 初始化一个变量count的值为0.
int count = 0;
// 将这个值存入到ServletContext中.
this.getServletContext().setAttribute("count", count);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
response.setContentType("text/html;charset=UTF-8");
// 1.接收表单提交的参数.
String username = request.getParameter("username");
String password = request.getParameter("password");
// 2.封装到实体对象中.
User user = new User();
user.setUsername(username);
user.setPassword(password);
// 3.调用业务层处理数据.
UserService userService = new UserService();
User existUser = userService.login(user);
// 4.根据处理结果显示信息(页面跳转).
if(existUser == null){
// 登录失败
response.getWriter().println("<h1>登录失败:用户名或密码错误!</h1>");
}else{
// 登录成功
// 记录次数:
int count = (int) this.getServletContext().getAttribute("count");
count++;
this.getServletContext().setAttribute("count", count);
response.getWriter().println("<h1>登录成功:您好:"+existUser.getNickname()+"</h1>");
response.getWriter().println("<h3>页面将在5秒后跳转!</h3>");
response.setHeader("Refresh", "5;url=/day09/CountServlet");
}
} catch (Exception e) {
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
public class CountServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获得Count的值。
response.setContentType("text/html;charset=UTF-8");
int count = (int) this.getServletContext().getAttribute("count");
response.getWriter().println("<h1>您是第"+count+"位登录成功的用户!</h1>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
ServletContext对象,tomcat为每一个web项目单独创建的一个上下文(知上知下贯穿全文)对象。就有功能:
1.可以在多个servlet之间共享数据
存放:setAttribute()
获得:getAttribute()
删除:removeAttribute()
2.可以获得当前WEB项目中的指定资源(文件)
3.可以进行整个web项目初始化数据设置
在web.xml可以给整个web项目配置初始化参数
<!-- 全局初始化参数(整个项目) -->
<context-param>
<param-name>参数名</param-name>
<param-value>参数值</param-value>
</context-param>
主演:李易峰 / 迈克尔·道格拉斯 / 周冬雨
猫眼电影演出 广告
购买
在实际开发中,有时候可能会需要读取Web应用中的一些资源文件,比如配置文件,图片等。为此,在ServletContext接口中定义了一些读取Web资源的方法,这些方法是依靠Servlet容器来实现的。Servlet容器根据资源文件名相对于Web应用的路径,返回关联资源文件的IO流、资源文件在文件系统的绝对路径等。
方法说明 | 功能描述 |
---|---|
Set getResourcePaths(String path) | 返回一个Set集合,集合中包含资源目录中子目录和文件的路径名称。参数path必须以正斜线(/)开始,指定匹配资源的部分路径 |
String getRealPath(String path) | 返回资源文件在服务器文件系统上的真实路径(文件的绝对路径)。参数path代表资源文件的虚拟路径,它应该以正斜线开始(/)开始,“/”表示当前Web应用的根目录,如果Servlet容器不能将虚拟路径转换为文件系统的真实路径,则返回null |
URL getResource(String path) | 返回映射到某个资源文件的URL对象。参数path必须以正斜线(/)开始,“/”表示当前Web应用的根目录 |
InputStream getResourceAsStream(String path) | 返回映射到某个资源文件的InputStream输入流对象。参数path传递规则和getResource()方法完全一致 |
了解了ServletContext接口中用于获得Web资源路径的方法后,接下来通过一个案例,分步骤演示如何使用ServletContext对象读取资源文件
package cn.com.javahelp.servlet;
import java.io.*;
import java.util.Properties;
import javax.servlet.*;
import javax.servlet.http.*;
public class ReadFileServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
ServletContext context = this.getServletContext();
PrintWriter out = response.getWriter();
//获取相对路径中的输入流对象
InputStream in = context.getResourceAsStream("/WEB-INF/classes/javahelp.properties");
Properties pros = new Properties();
pros.load(in);
out.println("Company=" + pros.getProperty("Company") + "<br>");
out.println("Address=" + pros.getProperty("Address") + "<br>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
this.doGet(request, response);
}
}
package cn.com.javahelp.servlet;
import java.io.*;
import java.util.Properties;
import javax.servlet.*;
import javax.servlet.http.*;
public class ReadFileServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
PrintWriter out = response.getWriter();
ServletContext context = this.getServletContext();
//获取文件绝对路径
String path = context
.getRealPath("/WEB-INF/classes/javahelp.properties");
FileInputStream in = new FileInputStream(path);
Properties pros = new Properties();
pros.load(in);
out.println("Company=" + pros.getProperty("Company") + "<br>");
out.println("Address=" + pros.getProperty("Address") + "<br>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
this.doGet(request, response);
}
}
通过ServletConfig对象获得
通过ServletContext对象获得
public static void readFile() throws IOException{
// 使用类的加载器来读取文件.
// 类的加载器用来加载class文件,将class文件加载到内存.
InputStream is = ReadFileUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(is);
String driverClass = properties.getProperty("driverClass");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(driverClass);
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
在登录成功后,页面跳转到文件下载的列表的页面,点击列表中的某些链接,下载文件.
在Servlet API中,定义了一个HttpServletResponse接口,它继承自ServletResponse接口,专门用来封装HTTP响应消息。由于HTTP响应消息分为状态行、响应消息头、消息体三部分,因此,在HttpServletResponse接口中定义了向客户端发送响应状态码、响应消息头、响应消息体的方法,接下来,本节将针对这些方法进行详细的讲解。
当Servlet向客户端回送响应消息时,需要在响应消息中设置状态码。为此,在HttpServletResponse接口中,定义了两个发送状态码的方法,具体如下。
1).setStatus(int status)方法
该方法用于设置HTTP响应消息的状态码,并生成响应状态行。由于响应状态行中的状态描述信息直接与状态码相关,而HTTP版本由服务器确定,因此,只要通过setStatus(int status)方法设置了状态码,即可实现状态行的发送。需要注意的是,正常情况下,Web服务器会默认产生一个状态码为200的状态行。
2).sendError(int sc)方法
该方法用于发送表示错误信息的状态码,例如,404状态码表示找不到客户端请求的资源。在response对象中,提供了两个重载的sendError(int sc)方法,具体如下:
public void sendError(int code) throws java.io.IOException
public void sendError(int code, String message) throws java.io.IOException
在上面重载的两个方法中,第一个方法只是发送错误信息的状态码,而第二个方法除了发送状态码外,还可以增加一条用于提示说明的文本信息,该文本信息将出现在发送给客户端的正文内容中。
当Servlet向客户端发送响应消息时,由于HTTP协议的响应头字段有很多种,为此,在HttpServletResponse接口中,定义了一系列设置HTTP响应头字段的方法,如表4-1所示。
表4-1 设置响应消息头字段的方法
方法声明 | 功能描述 |
---|---|
void addHeader(String name, String value) | 这两个方法都是用来设置HTTP协议的响应头字段,其中,参数name用于指定响应头字段的名称,参数value用于指定响应头字段的值。不同的是,addHeader()方法可以增加同名的响应头字段,而setHeader()方法则会覆盖同名的头字段 |
void setHeader(String name, String value) | |
void addIntHeader(String name,int value) | 这两个方法专门用于设置包含整数值的响应头。避免了使用addHeader()与setHeader()方法时,需要将int类型的设置值转换为String类型的麻烦 |
void setIntHeader(String name,int value) | |
void setContentLength(int len) | 该方法用于设置响应消息的实体内容的大小,单位为字节。对于HTTP协议来说,这个方法就是设置Content-Length响应头字段的值 |
void setContentType(String type) | 该方法用于设置Servlet输出内容的MIME类型,对于HTTP协议来说,就是设置Content-Type响应头字段的值。例如,如果发送到客户端的内容是jpeg格式的图像数据,就需要将响应头字段的类型设置为“image/jpeg”。需要注意的是,如果响应的内容为文本,setContentType()方法的还可以设置字符编码,如:text/html;charset=UTF-8 |
void setCharacterEncoding(String charset) | 该方法用于设置输出内容使用的字符编码,对HTTP 协议来说,就是设置Content-Type头字段中的字符集编码部分。一般不使用。 |
需要注意的是,在表4-1列举的一系列方法中,addHeader()、setHeader()、addIntHeader()、setIntHeader()方法都是用于设置各种头字段的,而setContetType() 和setCharacterEncoding()方法用于设置字符编码,这些设置字符编码的方法可以有效解决乱码问题。
由于在HTTP响应消息中,大量的数据都是通过响应消息体传递的,因此,ServletResponse遵循以IO流传递大量数据的设计理念。在发送响应消息体时,定义了两个与输出流相关的方法,具体如下。
1).getOutputStream()方法
该方法所获取的字节输出流对象为ServletOutputStream类型。由于ServletOutputStream是OutputStream的子类,它可以直接输出字节数组中的二进制数据。因此,要想输出二进制格式的响应正文,就需要使用getOutputStream()方法。
2).getWriter()方法
该方法所获取的字符输出流对象为PrintWriter类型。由于PrintWriter类型的对象可以直接输出字符文本内容,因此,要想输出内容全为字符文本的网页文档,需要使用getWriter()方法。
了解了response对象发送响应消息体的两个方法后,接下来,通过一个案例来学习这两个方法的使用。
在Eclipse中创建Web项目chapter04,在项目的src目录下,新建一个名称为cn.com.javahelp. chapter04.response的包,在包中编写一个名为PrintServlet的Servlet类,该类中使用了response对象的getOutPutStream()方法获取输出流对象,如文件4-1所示。
文件4-1 PrintServlet.java
package cn.com.javahelp.chapter04.response;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class PrintServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
String data = "javahelp";
// 获取字节输出流对象
OutputStream out = response.getOutputStream();
out.write(data.getBytes());// 输出信息
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
doGet(request, response);
}
}
在web.xml中配置完PrintServlet的映射后,启动Tomcat服务器,在浏览器的地址栏中输入地址“http://localhost:8080/chapter04/PrintServlet”访问PrintServlet,浏览器的显示结果如图4-2所示。
图 4-2
从图4-2中可以看出,浏览器显示出了response对象响应的数据。由此可见,response对象的getOutputStream()方法可以很方便的发送响应消息体。
接下来,对文件4-1进行修改,使用getWriter()方法发送消息体,修改后的代码如文件4-2所示。
文件4-2 PrintServlet.java
package cn.com.javahelp.chapter04.response;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class PrintServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
String data = "javahelp";
// 获取字符输出流对象
PrintWriter print = response.getWriter();
print.write(data); // 输出信息
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
doGet(request, response);
}
}
重启Tomcat服务器,在浏览器的地址栏中输入地址 “http://localhost:8080/chapter04/PrintServlet”再次访问PrintServlet,浏览器的显示结果同样如图4-2所示。
注意:
虽然response对象的getOutputStream()和getWriter()方法都可以发送响应消息体,但是,它们之间互相排斥,不可同时使用,否则会发生IllegalStateException异常,如图4-3所示。
图4-3
图4-3中发生异常的原因就是在Servlet中,调用response.getWriter() 方法之前已经调用了response.getOutputStream() 方法。
对于文件下载,相信读者并不会陌生,因为通常在上网时所下的图片、文档和影片等都是文件下载的范畴。现在很多网站都提供了下载各类资源的功能,因此在学习Web开发过程中,有必要学习文件下载的实现方式。
实现文件下载功能比较简单,通常情况下,不需要使用第三方组件实现,而是直接使用Servlet类和输入/输出流实现。与访问服务器文件不同的是,要实现文件的下载,不仅需要指定文件的路径,还需要在HTTP协议中设置两个响应消息头,具体如下:
//设定接收程序处理数据的方式
Content-Disposition: attachment; filename =
//设定实体内容的MIME类型
Content-Type:application/x-msdownload
浏览器通常会直接处理响应的实体内容,需要在HTTP响应消息中设置两个响应消息头字段,用来指定接收程序处理数据内容的方式为下载方式。当单击“下载”超链接时,系统将请求提交到对应的Servlet。在该Servlet中,首先获取下载文件的地址,并根据该地址创建文件字节输入流,然后通过该流读取下载文件内容,最后将读取的内容通过输出流写到目标文件中。
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.接收参数
String filename = request.getParameter("filename");
// 2.完成文件下载:
// 2.1设置Content-Type头
String type = this.getServletContext().getMimeType(filename);
response.setHeader("Content-Type", type);
// 2.2设置Content-Disposition头
response.setHeader("Content-Disposition", "attachment;filename="+filename);
// 2.3设置文件的InputStream.
String realPath = this.getServletContext().getRealPath("/download/"+filename);
InputStream is = new FileInputStream(realPath);
// 获得response的输出流:
OutputStream os = response.getOutputStream();
int len = 0;
byte[] b = new byte[1024];
while((len = is.read(b))!= -1){
os.write(b, 0, len);
}
is.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
/**
* 文件下载的Servlet
*/
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.接收参数
String filename = new String(request.getParameter("filename"));
System.out.println(filename);
// 2.完成文件下载:
// 2.1设置Content-Type头
String type = this.getServletContext().getMimeType(filename);
response.setHeader("Content-Type", type);
// 2.3设置文件的InputStream.
String realPath = this.getServletContext().getRealPath("/download/"+filename);
// 根据浏览器的类型处理中文文件的乱码问题:
String agent = request.getHeader("User-Agent");
System.out.println(agent);
if(agent.contains("Firefox")){
filename = base64EncodeFileName(filename);
}else{
filename = URLEncoder.encode(filename,"UTF-8");
}
// 2.2设置Content-Disposition头
response.setHeader("Content-Disposition", "attachment;filename="+filename);
InputStream is = new FileInputStream(realPath);
// 获得response的输出流:
OutputStream os = response.getOutputStream();
int len = 0;
byte[] b = new byte[1024];
while((len = is.read(b))!= -1){
os.write(b, 0, len);
}
is.close();
}
public static String base64EncodeFileName(String fileName) {
BASE64Encoder base64Encoder = new BASE64Encoder();
try {
return "=?UTF-8?B?"
+ new String(base64Encoder.encode(fileName
.getBytes("UTF-8"))) + "?=";
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
在开发中,如果需要响应给浏览器中文数据,我们需要使用getWriter()方法,tomcat使用getWriter()处理字符时,默认编码时ISO8859-1。响应给浏览器的数据,此时为乱码。在开发中我们需要使用setCharacterEncoding方法来设置编码。此时响应给浏览器的数据为正常数据,但浏览器查看编码,可能使我们查看到内容仍为乱码,需要使用响应头 content-type进行设置。
在HttpServletResponse对象中,提供了两种解决乱码的方案,具体如下:
// 设置HttpServletResponse使用utf-8编码,此数据提供给tomcat使用。
response.setCharacterEncoding("utf-8");
// 通知浏览器查看编码为utf-8
response.setHeader("Content-Type","text/html;charset=utf-8");
// 使用通用方法,setContentType底层自动调用了setCharacterEncoding
response.setContentType("text/html;charset=utf-8");
通常情况下,为了使代码更加简洁,会采用第二种方式。实现代码如下文所示:
package cn.com.javahelp.chapter04.response;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ChineseServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//设置字符编码
response.setContentType("text/html;charset=utf-8");
String data="中国";
PrintWriter out = response.getWriter();
out.println(data);
}
public void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}
启动Tomcat服务器,在浏览器的地址栏中输入地址“http://localhost:8080/day14/ChineseServlet”访问ChineseServlet,浏览器显示出了正确的中文字符,如下图所示。
在访问登录页面时,需要生产验证码。从而防止用户使用程序恶意登录。
public class VerifyCodeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//生成图片
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1 高和宽
int height = 30;
int width = 60;
String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
Random random = new Random();
//2 创建一个图片
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//3 获得画板
Graphics g = image.getGraphics();
//4 填充一个矩形
// * 设置颜色
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);
g.setColor(Color.WHITE);
g.fillRect(1, 1, width-2, height-2);
// * 设置字体
g.setFont(new Font("宋体", Font.BOLD|Font.ITALIC, 25));
//5 写随机字
for(int i = 0 ; i < 4 ; i ++){
// 设置颜色--随机数
g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
// 获得随机字
int index = random.nextInt(data.length());
String str = data.substring(index, index + 1);
// 写入
g.drawString(str, width/6 * (i + 1), 20);
}
//6 干扰线
for(int i = 0 ; i < 3 ; i ++){
// 设置颜色--随机数
g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
// 随机绘制先
g.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width),random.nextInt(height));
// 随机点
g.drawOval(random.nextInt(width), random.nextInt(height), 2, 2);
}
//end 将图片响应给浏览器
ImageIO.write(image, "jpg", response.getOutputStream());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
<servlet>
<servlet-name>VerifyCodeServlet</servlet-name>
<servlet-class>cn.com.javahelp.web.servlet.VerifyCodeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>VerifyCodeServlet</servlet-name>
<url-pattern>/VerifyCodeServlet</url-pattern>
</servlet-mapping>
<div>
<img id="imgId" onclick="changeImg()" style="cursor: pointer;"
src="${pageContext.request.contextPath}/VerifyCodeServlet"/>
<a href="javascript:void(0)" onclick="changeImg()" >换一张</a>
<script type="text/javascript">
function changeImg(){
$("#imgId").attr("src","${pageContext.request.contextPath}/VerifyCodeServlet?t="+new Date());
}
</script>
</div>
今日内容介绍
今日内容学习目标
网站首页上点击注册的链接,跳转到注册页面,在注册页面中输入信息.完成注册:(将数据保存到数据库中).
在Servlet API中,定义了一个HttpServletRequest接口,它继承自ServletRequest接口,专门用来封装HTTP请求消息。由于HTTP请求消息分为请求行、请求消息头和请求消息体三部分,因此,在HttpServletRequest接口中定义了获取请求行、请求头和请求消息体的相关方法,接下来,本节将针对这些方法进行详细地讲解。
当访问Servlet时,会在请求消息的请求行中,包含请求方法、请求资源名、请求路径等信息,为了获取这些信息,在HttpServletRequest接口中,定义了一系列用于获取请求行的方法,如表4-2所示。
表4-2 获取请求行的相关方法
方法声明 | 功能描述 |
---|---|
String getMethod() | 该方法用于获取HTTP请求消息中的请求方式(如GET、POST等) |
String getRequestURI() | 该方法用于获取请求行中资源名称部分,即位于URL的主机和端口之后、参数部分之前的部分 |
String getQueryString() | 该方法用于获取请求行中的参数部分,也就是资源路径后面问号(?)以后的所有内容 |
String getProtocol() | 该方法用于获取请求行中的协议名和版本,例如,HTTP/1.0或HTTP/1.1 |
String getContextPath() | 该方法用于获取请求URL中属于WEB应用程序的路径,这个路径以“/”开头,表示相对于整个WEB站点的根目录,路径结尾不含“/”。如果请求URL属于WEB站点的根目录,那么返回结果为空字符串("") |
String getServletPath() | 该方法用于获取Servlet的名称或Servlet所映射的路径 |
String getRemoteAddr() | 该方法用于获取请求客户端的IP地址,其格式类似于“192.168.0.3” |
String getRemoteHost() | 该方法用于获取请求客户端的完整主机名,其格式类似于“pc1.javahelp.com.cn”。需要注意的是,如果无法解析出客户机的完整主机名,该方法将会返回客户端的IP地址 |
int getRemotePort() | 该方法用于获取请求客户端网络连接的端口号 |
String getLocalAddr() | 该方法用于获取Web服务器上接收当前请求网络连接的IP地址 |
String getLocalName() | 该方法用于获取Web服务器上接收当前网络连接IP所对应的主机名 |
int getLocalPort() | 该方法用于获取Web服务器上接收当前网络连接的端口号 |
String getServerName() | 该方法用于获取当前请求所指向的主机名,即HTTP请求消息中Host头字段所对应的主机名部分 |
int getServerPort() | 该方法用于获取当前请求所连接的服务器端口号,即如果HTTP请求消息中Host头字段所对应的端口号部分 |
String getScheme() | 该方法用于获取请求的协议名,例如http、https或ftp |
StringBuffer getRequestURL() | 该方法用于获取客户端发出请求时的完整URL,包括协议、服务器名、端口号、资源路径等信息,但不包括后面的查询参数部分。注意,getRequestURL()方法返回的结果是StringBuffer类型,而不是String类型,这样更便于对结果进行修改 |
在表4-2中,列出了一系列用于获取请求消息行信息的方法,为了使读者更好地理解这些方法,接下来,通过一个案例来演示这些方法的使用。
在chapter04项目的src目录下,新建一个名称为cn.com.javahelp.request的包,在包中编写一个名为RequestLineServlet的类,该类中编写了用于获取请求行中相关信息的方法,如文件4-3所示。
文件4-3 RequestLineServlet.java
package cn.com.javahelp.request;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class RequestLineServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
// 获取请求行的相关信息
out.println("getMethod : " + request.getMethod() + "<br>");
out.println("getRequestURI : " + request.getRequestURI() + "<br>");
out.println("getQueryString:"+request.getQueryString() + "<br>");
out.println("getProtocol : " + request.getProtocol() + "<br>");
out.println("getContextPath:"+request.getContextPath() + "<br>");
out.println("getPathInfo : " + request.getPathInfo() + "<br>");
out.println("getPathTranslated : "
+ request.getPathTranslated() + "<br>");
out.println("getServletPath:"+request.getServletPath() + "<br>");
out.println("getRemoteAddr : " + request.getRemoteAddr() + "<br>");
out.println("getRemoteHost : " + request.getRemoteHost() + "<br>");
out.println("getRemotePort : " + request.getRemotePort() + "<br>");
out.println("getLocalAddr : " + request.getLocalAddr() + "<br>");
out.println("getLocalName : " + request.getLocalName() + "<br>");
out.println("getLocalPort : " + request.getLocalPort() + "<br>");
out.println("getServerName : " + request.getServerName() + "<br>");
out.println("getServerPort : " + request.getServerPort() + "<br>");
out.println("getScheme : " + request.getScheme() + "<br>");
out.println("getRequestURL : " + request.getRequestURL() + "<br>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
doGet(request, response);
}
}
在web.xml中配置完RequestLineServlet的映射后,启动Tomcat服务器,在浏览器的地址栏中输入地址“http://localhost:8080/ day15/RequestLineServlet”访问RequestLineServlet,浏览器的显示结果如图4-14所示。
图4-14
从图4-14中可以看出,浏览器显示出了请求RequestLineServlet时,发送的请求行信息。由此可见,通过HttpServletRequest对象可以很方便的获取到请求行的相关信息。
当请求Servlet时,需要通过请求头向服务器传递附加信息,例如,客户端可以接收的数据类型,压缩方式,语言等等。为此,在HttpServletRequest接口中,定义了一系列用于获取HTTP请求头字段的方法,如表4-3所示。
表4-3 获取请求消息头的方法
方法声明 | 功能描述 |
---|---|
String getHeader(String name) | 该方法用于获取一个指定头字段的值,如果请求消息中没有包含指定的头字段,getHeader()方法返回null;如果请求消息中包含有多个指定名称的头字段,getHeader()方法返回其中第一个头字段的值 |
Enumeration getHeaders(String name) | 该方法返回一个Enumeration集合对象,该集合对象由请求消息中出现的某个指定名称的所有头字段值组成。在多数情况下,一个头字段名在请求消息中只出现一次,但有时候可能会出现多次 |
Enumeration getHeaderNames() | 该方法用于获取一个包含所有请求头字段的Enumeration对象 |
int getIntHeader(String name) | 该方法用于获取指定名称的头字段,并且将其值转为int类型。需要注意的是,如果指定名称的头字段不存在,返回值为-1;如果获取到的头字段的值不能转为int类型,将发生NumberFormatException异常 |
Long getDateHeader(String name) | 该方法用于获取指定头字段的值,并将其按GMT时间格式转换成一个代表日期/时间的长整数,这个长整数是自1970年1月1日0点0分0秒算起的以毫秒为单位的时间值 |
在表4-3中,列出了一系列用于读取HTTP请求消息头字段的方法,为了更好地掌握这些方法,接下来通过一个案例来学习这些方法的使用。
在cn.com.javahelp.request包中编写一个名为RequestHeadersServlet的类,该类使用getHeaderNames()方法来获取请求消息头信息,如文件4-4所示。
文件4-4 RequestHeadersServlet.java
package cn.com.javahelp.request;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.*;
import javax.servlet.http.*;
public class RequestHeadersServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
// 获取请求消息中所有头字段
Enumeration headerNames = request.getHeaderNames();
// 使用循环遍历所有请求头,并通过getHeader()方法获取一个指定名称的头字段
while (headerNames.hasMoreElements()) {
String headerName = (String) headerNames.nextElement();
out.print(headerName + " : "
+ request.getHeader(headerName)+ "<br>");
}
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
doGet(request, response);
}
}
在web.xml中配置完RequestHeadersServlet映射后,启动Tomcat服务器,在浏览器的地址栏中输入地址“http://localhost:8080/day15/RequestHeadersServlet”访问RequestHeadersServlet,浏览器的显示结果如图4-15所示。
在实际开发中,经常需要获取用户提交的表单数据,例如,用户名、密码、电子邮件等,为了方便获取表单中的请求参数,在HttpServletRequest接口中,定义了一系列获取请求参数的方法,如表4-4所示。
表4-4 获取请求参数的方法
方法声明 | 功能描述 |
---|---|
String getParameter(String name) | 该方法用于获取某个指定名称的参数值,如果请求消息中没有包含指定名称的参数,getParameter()方法返回null;如果指定名称的参数存在但没有设置值,则返回一个空串;如果请求消息中包含有多个该指定名称的参数,getParameter()方法返回第一个出现的参数值 |
String[] getParameterValues(String name) | HTTP请求消息中可以有多个相同名称的参数(通常由一个包含有多个同名的字段元素的FORM表单生成),如果要获得HTTP请求消息中的同一个参数名所对应的所有参数值,那么就应该使用getParameterValues()方法,该方法用于返回一个String类型的数组 |
Enumeration getParameterNames() | getParameterNames()方法用于返回一个包含请求消息中所有参数名的Enumeration对象,在此基础上,可以对请求消息中的所有参数进行遍历处理 |
Map getParameterMap() | getParameterMap()方法用于将请求消息中的所有参数名和值装入进一个Map对象中返回 |
表4-4中,列出了HttpServletRequest获取请求参数的一系列方法。其中,getParameter()方法用于获取某个指定的参数,而getParameterValues()方法用于获取多个同名的参数。接下来,通过一个具体的案例,分步骤讲解这两个方法的使用,具体如下:
(1)在day15项目的WebContent根目录下编写一个表单文件form.html,如文件4-5所示。
文件4-5 form.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/day15/RequestParamsServlet" method="POST">
用户名:<input type="text" name="username"><br>
密 码:<input type="password" name="password">
<br>
爱好:
<input type="checkbox" name="hobby" value="sing">唱歌
<input type="checkbox" name="hobby" value="dance">跳舞
<input type="checkbox" name="hobby" value="football">足球<br>
<input type="submit" value="提交">
</form>
</body>
</html>
(2)在cn.com.javahelp.request包中编写一个名称为RequestParamsServlet的Servlet类,使用该Servlet获取请求参数,如文件4-6所示。
文件4-6 RequestParamsServlet.java
package cn.com.javahelp.request;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class RequestParamsServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
String name = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("用户名:" + name);
System.out.println("密 码:" + password);
// 获取参数名为“hobby”的值
String[] hobbys = request.getParameterValues("hobby");
System.out.print("爱好:");
for (int i = 0; i < hobbys.length; i++) {
System.out.print(hobbys[i] + ", ");
}
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
doGet(request, response);
}
}
在文件4-14中,由于参数名为“hobby”的值可能有多个,因此,需要使用getParameterValues()方法,获取多个同名参数的值,返回一个String类型的数组,通过遍历数组,打印出每个“hobby”参数对应的值。
(3)在web.xml中配置完RequestParamsServlet映射后,启动Tomcat服务器,在浏览器的地址栏中输入地址“http://localhost:8080/ day15/form.html”访问form.html页面,并填写表单相关信息,填写后的页面如图4-18所示。
图4-18 运行结果
(4)单击图4-18所示的“提交”按钮,在Eclipse的控制台打印出了每个参数的信息,如图4-19所示。
图4-19 运行结果
BeanUtils 是 Apache commons组件的成员之一,主要用于简化JavaBean封装数据的操作。它可以给JavaBean封装一个字符串数据,也可以将一个表单提交的所有数据封装到JavaBean中。
使用第三方工具,需要导入jar包:
BeanUtils工具常用工具类有两个:BeanUtils、ConvertUtils。BeanUtils用于封装数据,ConvertUtils用于处理类型转换,常用API如下
方法 | 描述 | |
---|---|---|
BeanUtils对象 | populate(Object bean, Map<String,String[]> properties) | 将Map数据封装到指定Javabean中,一般用于将表单的所有数据封装到javabean |
ConvertUtils | register(Converter converter, Class clazz) | 注册类型转换器 |
public class User {
private String username;
private String password;
private int age;
private Date birthday;
public User() {
}
public User(String username, String password, int age, Date birthday) {
...
}
@Test
public void demo01() throws Exception{
//将map数据封装给user
Map<String,String[]> properties = new HashMap<String,String[]>();
properties.put("username", new String[]{"jack"});
properties.put("password", new String[]{"1234"});
properties.put("age", new String[]{"18"});
User user = new User();
// 封装数据
BeanUtils.populate(user, properties);
System.out.println(user);
}
@Test
public void demo02() throws Exception{
//转换器
Map<String,String[]> properties = new HashMap<String,String[]>();
properties.put("username", new String[]{"jack"});
properties.put("password", new String[]{"1234"});
properties.put("age", new String[]{"18"});
properties.put("birthday", new String[]{"2012-12-21"});
User user = new User();
//1 创建BeanUtils提供时间转换器
DateConverter dateConverter = new DateConverter();
//2 设置需要转换的格式
dateConverter.setPattern("yyyy-MM-dd");
//3 注册转换器
ConvertUtils.register(dateConverter, java.util.Date.class);
//4 封装数据
BeanUtils.populate(user, properties);
System.out.println(user);
}
public class MyBeanUtils {
/**
* 将数据封装给JavaBean,支持时间类型转换
* @param user
* @param properties
*/
public static void populate(Object user, Map<String,String[]> properties){
try {
//1 创建BeanUtils提供时间转换器
DateConverter dateConverter = new DateConverter();
//2 设置需要转换的格式
dateConverter.setPatterns(new String[]{"yyyy-MM-dd","yyyy-MM-dd HH:mm:ss"});
//3 注册转换器
ConvertUtils.register(dateConverter, java.util.Date.class);
//4 封装数据
BeanUtils.populate(user, properties);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
使用
/**
* 高级封装,不需要new javabean
* @param beanClass
* @param properties
* @return
*/
public static <T> T populate(Class<T> beanClass, Map<String,String[]> properties){
try {
//1 使用反射创建实例
T bean = beanClass.newInstance();
//2.1 创建BeanUtils提供时间转换器
DateConverter dateConverter = new DateConverter();
//2.2 设置需要转换的格式
dateConverter.setPatterns(new String[]{"yyyy-MM-dd","yyyy-MM-dd HH:mm:ss"});
//2.3 注册转换器
ConvertUtils.register(dateConverter, java.util.Date.class);
//3 封装数据
BeanUtils.populate(bean, properties);
return bean;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
使用
package cn.com.javahelp.e_regist;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 用户注册的Servlet
*/
public class RegistServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try{
request.setCharacterEncoding("UTF-8");
// 1.接收参数
String username = request.getParameter("username");
String password = request.getParameter("password");
String email = request.getParameter("email");
String name = request.getParameter("name");
String sex = request.getParameter("sex");
String telephone = request.getParameter("telephone");
// 2.封装数据
User user = new User();
user.setUsername(username);
user.setPassword(password);
user.setEmail(email);
user.setName(name);
user.setSex(sex);
user.setTelephone(telephone);
// 3.调用业务层处理数据
UserService userService = new UserService();
userService.regist(user);
// 4.页面跳转
response.sendRedirect(request.getContextPath()+"/login.htm");
}catch(Exception e){
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
在填写表单数据时,难免会输入中文,如姓名、公司名称等。在文件4-13中,由于HTML设置了浏览器在传递请求参数时,采用的编码方式是UTF-8,但在解码时采用的是默认的ISO8859-1,因此会导致乱码的出现。在浏览器的地址栏中输入地址“http://localhost:8080/day15/form.html”再次访问form.html页面,输入用户名为“悟空教程”以及相关表单信息,如图4-20所示。
图4-20 运行结果
单击图4-20中的“提交”按钮,这时,控制台打印出了每个参数的值,具体如图4-21所示。
图4-21 运行结果
从图4-21可以看出,当输入的用户名为中文时,出现了乱码问题。通过本任务的学习,读者将学会如何处理请求参数的中文乱码问题。
【实现步骤】
1.设置编码方式
在HttpServletRequest接口中,提供了一个setCharacterEncoding()方法,该方法用于设置request对象的解码方式,接下来,对文件4-6进行修改,修改后的代码如文件4-7所示。该方法用于返回请求消息的实体部分的字符集编码
文件4-7 RequestParamsServlet.java
package cn.com.javahelp.chapter04.request;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class RequestParamsServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
//设置request对象的解码方式
request.setCharacterEncoding("utf-8");
String name = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("用户名:" + name);
System.out.println("密 码:" + password);
String[] hobbys = request.getParameterValues("hobby");
System.out.print("爱好:");
for (int i = 0; i < hobbys.length; i++) {
System.out.print(hobbys[i] + ", ");
}
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
doGet(request, response);
}
}
2.查看运行结果
启动Tomcat服务器,再次访问form.html页面,输入中文用户名“悟空教程”以及相关表单信息,控制台打印的结果如图4-22所示。
图4-22 运行结果
从图4-22可以看出,控制台输出的参数信息没有出现乱码。需要注意的是,这种解决乱码的方式只对POST方式有效,而对GET方式无效。为了验证GET方式的演示效果,接下来,将form.html文件中method属性的值改为“GET”。重新访问form.html页面并填写中文信息,控制台的打印结果如图4-23所示。
图4-23 运行结果
从图4-23中可以看出,使用GET方式提交表单,用户名出现了乱码,这就验证了setCharacterEncoding()方法只对POST提交方式有效的结论。为了解决GET方式提交表单时出现的中文乱码问题,接下来,对文件4-7进行修改,增加一行代码,如下所示:
name=new String(name.getBytes("iso8859-1"),"utf-8");
重启Tomcat服务器,再次访问form.html网页,输入中文用户名“悟空教程”,这时,控制台的打印结果没有出现乱码,如图4-24所示。
图4-24
总结
完善“登录”案例,如果用户填写信息有误,在当前表单页面中给出相应的提示。
Request对象不仅可以获取一系列数据,还可以通过属性传递数据。在ServletRequest接口中,定义了一系列操作属性的方法,具体如下:
该方法用于将一个对象与一个名称关联后存储进ServletRequest对象中,其完整语法定义如下:
public void setAttribute(java.lang.String name,java.lang.Object o);
需要注意的是,如果ServletRequest对象中已经存在指定名称的属性,setAttribute()方法将会先删除原来的属性,然后再添加新的属性。如果传递给setAttribute()方法的属性值对象为null,则删除指定名称的属性,这时的效果等同于removeAttribute()方法。
该方法用于从ServletRequest对象中返回指定名称的属性对象,其完整的语法定义如下:
public java.lang.String getAttribute (java.lang.String name);
该方法用于从ServletRequest对象中删除指定名称的属性,其完整的语法定义如下:
public void removeAttribute(java.lang.String name);
该方法用于返回一个包含ServletRequest对象中的所有属性名的Enumeration对象,在此基础上,可以对ServletRequest对象中的所有属性进行遍历处理。getAttributeNames()方法的完整语法定义如下:
public java.util.Enumeration getAttributeNames();
需要注意的是,只有属于同一个请求中的数据才可以通过ServletRequest对象传递数据。关于ServletRequest对象操作属性的具体用法,将在后面的小节进行详细讲解。在此,大家只需了解即可。
当一个Web资源收到客户端的请求后,如果希望服务器通知另外一个资源去处理请求,这时,除了使用sendRedirect()方法实现请求重定向外,还可以通过RequestDispatcher接口的实例对象来实现。在ServletRequest接口中定义了一个获取RequestDispatcher对象的方法,如表4-5所示。
表4-5 获取RequestDispatcher对象的方法
方法声明 | 功能描述 |
---|---|
getRequestDispatcher(String path) | 返回封装了某个路径所指定资源的RequestDispatcher对象。其中,参数path必须以 “/”开头,用于表示当前Web应用的根目录。需要注意的是,WEB-INF目录中的内容对RequestDispatcher对象也是可见的,因此,传递给getRequestDispatcher(String path)方法的资源可以是WEB-INF目录中的文件 |
获取到RequestDispatcher对象后,最重要的工作就是通知其它Web资源处理当前的Servlet请求,为此,在RequestDispatcher接口中,定义了两个相关方法,如表4-6所示。
表4-6 RequestDispatcher接口的方法
方法声明 | 功能描述 |
---|---|
forward(ServletRequest request,ServletResponse response) | 该方法用于将请求从一个Servlet传递给另外的一个Web资源。在Servlet中,可以对请求做一个初步处理,然后通过调用这个方法,将请求传递给其它资源进行响应。需要注意的是,该方法必须在响应提交给客户端之前被调用,否则将抛出IllegalStateException异常 |
include(ServletRequest request,ServletResponse response) | 该方法用于将其它的资源作为当前响应内容包含进来 |
表4-6列举的两个方法中,forward()方法可以实现请求转发,include()方法可以实现请求包含,关于请求转发相关知识,将在下面的小节中进行详细讲解。
请求包含:就是将当前页面和被包含页面的输出结果,合并一起响应给浏览器。
在Servlet中,如果当前Web资源不想处理请求时,可以通过forward()方法将当前请求传递给其它的Web资源进行处理,这种方式称为请求转发。为了使读者更好地理解使用forward()方法实现请求转发的工作原理,接下来通过一张图来描述,如图4-25所示。
图4-25 forward()方法的工作原理
从图4-25中可以看出,当客户端访问Servlet1时,可以通过forward()方法将请求转发给其它Web资源,其它Web资源处理完请求后,直接将响应结果返回到客户端。
了解了forward()方法的工作原理后,接下来,通过一个案例来学习forward()方法的使用。
在day15项目的cn.com.javahelp.request包中编写一个名为RequestForwardServlet的Servlet类,该类使用forword()方法将请求转发到一个新的Servlet页面,如文件4-8所示。
文件4-8 RequestForwardServlet.java
package cn.com.javahelp.request;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
public class RequestForwardServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// 将数据存储到request对象中
request.setAttribute("company", "上海满吉教育科技有限公司");
RequestDispatcher dispatcher = request.getRequestDispatcher("/ResultServlet");
dispatcher.forward(request, response);
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
doGet(request, response);
}
}
通过使用forward()方法,将当前Servlet的请求转发到ResultServlet页面,在cn.com.javahelp.request包中编写一个名为ResultServlet的Servlet类,该类用于获取RequestForwardServlet类中保存在request对象中的数据并输出,ResultServlet类的代码实现。
ResultServlet.java
package cn.com.javahelp.request;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ResultServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// 获取PrintWriter对象用于输出信息
PrintWriter out = response.getWriter();
// 获取request请求对象中保存的数据
String company = (String) request.getAttribute("company");
if (company != null) {
out.println("公司名称:" + company + "<br>");
}
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
doGet(request, response);
}
}
在web.xml中,添加完两个Servlet的映射信息后,启动Tomcat服务器,在浏览器中输入地址“http://localhost:8080/day15/RequestForwardServlet”访问RequestForwardServlet,浏览器的显示结果如图4-26所示。
图4-26 运行结果
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
// * request作用设置错误信息
request.setAttribute("msg", "用户名或密码不匹配");
// * 请求转发到登录页面
request.getRequestDispatcher("login.jsp").forward(request, response);
<%=request.getAttribute("msg") %>
* 1.重定向的地址栏会发生变化,转发的地址栏不变.
* 2.重定向两次请求两次响应,转发一次请求一次响应.
* 3.重定向路径需要加工程名,转发的路径不需要加工程名.
* 4.重定向可以跳转到任意网站,转发只能在服务器内部进行转发.
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import cn.com.javahelp.domain.User;
import cn.com.javahelp.service.UserService;
public class RegisterServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
//1、获得请求数据
Map<String, String[]> map = request.getParameterMap();
//2、封装实体
User user = new User();
//使用BeanUtils进行映射封装(map中的key的名称与实体中的属性名称进行映射)
//bean代表要被封装实体 properties代表存储数据的map
try {
BeanUtils.populate(user, map);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
//手动封装uid
String uid = UUID.randomUUID().toString();
user.setUid(uid);
//3、传递数据到业务对象的方法
UserService service = new UserService();
//4、接受业务方法的处理结果
boolean isRegistSuccess = service.regist(user);
//5、为客户响应
if(isRegistSuccess){
//注册成功 返回登录页面
response.sendRedirect(request.getContextPath()+"/login.jsp");
}else{
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("对不起,注册失败,请联系管理员");
}
}
public void regist1(HttpServletRequest request, HttpServletResponse response) throws IOException{
request.setCharacterEncoding("UTF-8");
//1、获得请求数据
String username = request.getParameter("username");
String password = request.getParameter("password");
String email = request.getParameter("email");
String name = request.getParameter("name");
String sex = request.getParameter("sex");
String birthday = request.getParameter("birthday");
//2、封装实体
User user = new User();
//UUID:随机产生的永不不重复的字符串32位
String uid = UUID.randomUUID().toString();//36位 java产生uuid有四个-
user.setUid(uid);
user.setUsername(username);
user.setPassword(password);
user.setEmail(email);
user.setName(name);
user.setSex(sex);
user.setBirthday(birthday);
//3、传递数据到业务对象的方法
UserService service = new UserService();
//4、接受业务方法的处理结果
boolean isRegistSuccess = service.regist(user);
//5、为客户响应
if(isRegistSuccess){
//注册成功 返回登录页面
response.sendRedirect(request.getContextPath()+"/login.jsp");
}else{
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("对不起,注册失败,请联系管理员");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
以下代码编写根据servlet需求不断的迭代
生成set&get方法,实际开发中一般都是set不会做无参,无参只是方便教学
public class User {
/*`uid` varchar(50) NOT NULL,
`username` varchar(20) DEFAULT NULL,
`password` varchar(50) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`email` varchar(30) DEFAULT NULL,
`telephone` varchar(20) DEFAULT NULL,
`birthday` date DEFAULT NULL,
`sex` varchar(10) DEFAULT NULL,
`state` int(11) DEFAULT NULL,
`code` varchar(64) DEFAULT NULL*/
private String uid;//唯一性标识 主键
private String username;//用户名
private String password;//密码
private String name;//真实姓名
private String email;//邮箱
private String telephone;
private String birthday;//生日
private String sex;//性别
private int state;
private String code;
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
request对象同时也是一个域对象,开发人员通过request对象在实现转发时,把数据通过request对象带给其它web资源处理.当servlet1里面设置了值在servletN中也可以获取设置的值,作用范围:一次请求链中。
request
xxxAttribute();
生命周期:一次请求开始,到响应结束之前
setAttribute方法 设置
getAttribute方法 获取
removeAttribute方法 删除
getAttributeNames方法
request对象提供了一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发,从而共享请求中的数据
request.getRequestDispatcher("内部路径").forward(request,response)
请求转发可以实现路径的跳转操作.
实现:
New两个Servlet1 和Srevlet2
一个<a href="/day10/dis1?money=10">i_请求转发_借钱</a><br/> 前段链接加入money属性
Servlet1下request.getRequestDispatcher("内部路径").forward(request,response)路径为web.xml配置的跳转的Servlet的路径.System.out.println("我说:等会");response.getWriter().print("dis111111111111");request.setAttribute("name", "世纪"); request.getRequestDispatcher("/dis2").forward(request, response); |
---|
Servlet2下String money=request.getParameter("money");String name=(String) request.getAttribute("name");response.getWriter().print("dis2222222222222222");System.out.println("涛哥哥给你"+money+"块钱,然后我借给"+name); |
---|
1.请求转发是服务器内部跳转,地址栏不会发生改变
重定向地址栏会发生改变。
2.请求转发,只有一次请求,一次响应.
重定向,有两次请求,两次响应。
3.请求转发存在request域,可以共享数据.
重定向不存在request域。
4.请求转发只能在服务器的内部跳转,简单说,只能访问本站内资源。
重定向可以访问站外资源,也可以访问站内资源.
5.请求转发是由request 发起的 . request.getRequestDispatcher().forward()
重定向是由response 发起的 response.sendRedirect();
6.请求转发与重定向时路径写法不一样.
重定向要跳转的路径是浏览器在次发起的,是浏览器端路径:写法: /工程名/资源
请求转发是服务器内部跳转,这时它与浏览器无关 写法:/资源
RequestDispatcher.include()方法用于将RequestDispatcher对象封装的资源内容作为当前响应内容的一部分包含进来,从而实现可编程的服务器端包含功能
被包含的Servlet程序不能改变响应消息的状态码和响应头,如果它里面存在这样的语句,这些语句的执行结果将被忽略.include在程序执行上效果类似forward,但是使用forward只有一个程序可以生成响应,include可以由多个程序一同生成响应 ----- 常用来页面布局
New两个html页面分别为 i1.html&i2.htmli1内容1111111111i2内容22222222222New一个Servlet get方法下request.getRequestDispatcher(“/i1.html”).include(request,response);request.getRequestDispatcher(“/i2.html”).include(request,response);最后在页面输出的内容为111111111122222222222是两个页面的所用内容. 包含原理 |
---|
注意:转发与重定向不能一起使用
ServletContext
创建:服务器启动就创建context对象
销毁:服务器关闭
作用范围:整个web应用
Request
创建:请求时创建
销毁:请求结束销毁
作用范围:一次请求链中
什么是客户端地址:客户端直接访问服务器的地址是客户端地址
通过客户端访问web应用 地址必须加上web应用的名称
什么是服务器端地址:web应用内部访问的地址服务器端地址
特点,访问时,不用写web应用名称
写地址时怎么区分是否加上web应用的名称
看在web应用内还是外
1)直接在地址栏中写url地址 --- 客户端地址
2)a标签的href --- 客户端地址
3)form表单的action-----客户端地址
4)location.href ---- 客户端地址
目前记住一个服务器端地址:转发 --- 服务器端地址
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.com.javahelp.domain.User;
import cn.com.javahelp.service.UserService;
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
//1、接受数据
String username = request.getParameter("username");
String password = request.getParameter("password");
//2、封装实体
//3、传递数据
//4、接受结果
UserService service = new UserService();
User user = null;
try {
user = service.login(username,password);
} catch (SQLException e) {
e.printStackTrace();
}
//5、指派页面
if(user!=null){
//登录成功 跳转首页
response.sendRedirect(request.getContextPath()+"/index.jsp");
}else{
//登录失败
//返回登录页面 给予提示信息
request.setAttribute("loginInfo", "对不起 用户名或密码错误");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}