1 什么是Servlet:小服务器程序,用Java编写的服务器端程序,主要功能在于交互式地浏览和修改数据,生成动态Web内容。
2 创建Servlet
3 配置Servlet
4 接受请求参数
5 响应数据
1、重定向和转发
2、HTTPServletResponse的使用
3、HTTPServletRequest的使用
1、掌握重定向和转发
2、掌握HTTPServletResponse的使用
3、熟悉HTTPServletRequest的使用
作为后台开发人员,我们大多时候都在接收处理用户请求,给予用户响应,为了方便操作,服务器软件将请求和响应封装成了request和response,我们今天就讲解两个对象的操作!
Java Web服务端控制页面跳转主要有两种:重定向和转发
重定请求重新定个方向转到其它位置。
实现原理:
客户浏览器发送http请求----》web服务器接受后发送302状态码响应及对应新的location给客户浏览器--》客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址----》服务器根据此请求寻找资源并发送给客户。在这里location可以重定向到任意URL,既然是浏览器重新发出了请求,则就没有什么request传递的概念了。在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的。
特点:
特点:
1,重定向是客户端行为。
2,重定向是浏览器做了至少两次的访问请求的。
3,重定向浏览器地址改变。
4,重定向两次跳转之间传输的信息会丢失(request范围)。
5,重定向可以指向任何的资源,包括当前应用程序中的其他资源,同一个站点上的其他应用程序中的资源,其他站点的资源。注意:传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录
html页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<div>
<form action="/day12web1/login" method="post">
<label>账号:</label><input name="un"/><br/>
<label>密码:</label><input type="password" name="pw"/><br/>
<input type="submit" value="登录"/>
</form>
</div>
<h5><a href="register.html">还没账号请注册</a></h5>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>网站首页</title>
</head>
<body>
欢迎进入xxx管理系统............
</body>
</html>
Servlet代码:
/**
* Servlet implementation class LoginServlet
* 实现登录信息操作
*/
@WebServlet(value="/login",initParams={@WebInitParam(name="version",value="v10")})
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public LoginServlet() {
super();
// TODO Auto-generated constructor stub
}
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
super.init(config);
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @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);
//获取表单提交的用户名
String username=request.getParameter("un");
//获取密码
String password=request.getParameter("pw");
//服务端输出打印
System.out.println("POST:用户名:"+username+"---->密码:"+password);
//重定向.可以跳转到指定的页面
response.sendRedirect("index.html");
}
}
Servlet除了支持重定向之外还支持请求转发
转发的原理:
原理:
客户浏览器发送http请求----》web服务器接受此请求--》调用内部的一个方法在容器内部完成请求处理和转发动作----》将目标资源发送给客户。在这里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。
特点:
1,转发是服务器行为
2,转发是浏览器只做了一次访问请求
3,转发浏览器地址不变
4,转发两次跳转之间传输的信息不会丢失,所以可以通过request进行数据的传递
5,转发只能将请求转发给同一个WEB应用中的组件
注意:如果创建RequestDispatcher 对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。
package com.qf.web.servlet;
import java.io.IOException;
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 RegisterServlet
请求转发
*/
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public RegisterServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取表单提交的用户名
String username = request.getParameter("un");
// 获取密码
String password = request.getParameter("pw");
// 服务端输出打印
System.out.println("POST:注册:用户名:" + username + "---->密码:" + password);
//请求转发
request.getRequestDispatcher("/login.html").forward(request, response);
}
}
路径分类 :
绝对路径: 用在不同网站之间的跳转,比如:http://www.baidu.com/aaa/1.jpg
**相对路径:**用在同一个网站中, aaa/1.jpg,仅限静态资源,如果页面比较多,会出现混乱。
根路径:根指定就是主机名(服务器) /day12web1/loginservlet
(/ 表示 http://localhost:8080/)/day12web1/loginservlet
如果在浏览器中使用 / 表示 http://localhost:8080//listservlet
如果是在服务器中使用 / 表示 /day12web1
在Servlet中可以使用的内置对象主要有:request、response、application、session、out(PrintWriter)。
定义辅助 servlet 将响应发送到客户端的对象。servlet 容器创建 ServletResponse 对象,并将它作为参数传递给 servlet 的 service 方法。 要发送 MIME 正文响应中的二进制数据,请使用 getOutputStream 返回的 ServletOutputStream。要发送字符数据,请使用 getWriter 返回的 PrintWriter 对象。
扩展 ServletResponse 接口以提供特定于 HTTP 的发送响应功能。例如,该接口拥有访问 HTTP 头和 cookie 的方法。 客户端向服务器发起的都是HTTP协议操作,所以我们大部分使用HttpServletResponse对象作为直接操作对象!
方法名称 | 作用 |
---|---|
setStatus(int code) | 设置响应状态码:200 成功 302 临时重定向 304 处理缓存 404 Not Found没有找到资源,500 服务器错误 |
setHeader(name,value) | 设置响应信息头 |
setCharacterEncoding(String); | 设置编码格式 |
setContentType(String) | 设置返回数据mimetype |
getWriter() | 获取字符输出流 |
getOutputStream() | 获取字节输出流 |
方案1
response.setCharacterEncoding("utf-8");
设置tomcat编码格式
<html>
<head>
<meta charset="utf-8">
<title>xxx</title>
</head>
<body>编写返回的文本内容</body>
</html>
设置浏览器解析文本内容格式
可以解决返回字符串乱码问题,但是需要将返回的字符串封装到html代码中.操作繁琐!
方案2
response.setHeader("Content-type","text/html;charset=UTF-8")
方案按相对简单,通过设置响应头告知浏览器解析字符串的编码格式!
方案3(推荐)
response.setContentType("text/html;charset=UTF-8")
利用setContentType这种综合性的写法解决问题!此方法也是开发中常用的方法!方便!
用户下载服务器图片
public class DownLoadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/**
* 别人访问我 我给你一张图片
*
* 1.获取图片的输入流
* 2.response的字节输出流
*/
//1.获取图片或者文件的输入流
//想要或某个文件 你必须知道绝对路径
//手段: 项目中的相对路径 去获取绝对路径
// /吃鸡.jpg
// /WEB-INF/classes/吃鸡.jpg
// /WEB-INF/classes/com/itqf/servlet/吃鸡.jpg
//ServletContext getRealPath 相对路径转成绝对路径
String path = getServletContext().getRealPath("/吃鸡.jpg");
System.out.println(path);
//文件输入流
FileInputStream stream = new FileInputStream(path);
//xx/xx/x/x/x/x/x/x/吃鸡.jpg
//获取文件的名字 /
//File.separator == /
String filename = path.substring(path.lastIndexOf(File.separator)+1);
//文件名编码
filename = URLEncoder.encode(filename,"UTF-8");
//设置响应头
//content-disposition", "attachment;filename="+filename
//下载用的 attachment下载: filename下载文件的名字
response.setHeader("content-disposition", "attachment;filename="+filename);
//根据文件名字的后缀名获取类型
String mimetype = getServletContext().getMimeType(filename);
response.setContentType(mimetype); //下载文件的类型
ServletOutputStream outputStream = response.getOutputStream();
byte [] buffer = new byte [8*1024];
int len = 0;
while((len=stream.read(buffer)) != -1){
outputStream.write(buffer, 0, len);
}
stream.close();
}
}
页面中添加验证码
public class CodeServlet extends HttpServlet {
/**
* The doGet method of the servlet. <br>
* This method is called when a form has its tag value method equals to get
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置生成规则
/**
* width:验证码的宽度 px 像素
* height: px
* codeCount:生成验证码有几个数
* lineCount:有几根线
*/
ValidateCode code = new ValidateCode(200, 50, 6, 20);
//2.获取生成的验证码的字符串值
System.out.println(code.getCode()); //获取正确值
//3.响应写回验证图片
code.write(response.getOutputStream());
}
}
<!DOCTYPE html>
<html>
<head>
<title>login.html</title>
<meta name="keywords" content="keyword1,keyword2,keyword3">
<meta name="description" content="this is my page">
<meta name="content-type" content="text/html; charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
</head>
<body>
<form action="/Day11_Response1/servlet/LoginServlet" method="post">
<input type="text" name="username" placeholder="请输入账号!" />
<input type="submit" value="登录"/>
</form>
<img src="/Day11_Response1/servlet/CodeServlet" onclick="changeCodes()" alt="验证码" title="验证码"/>
<a href="javascript:changeCodes()" >看不清?</a>
<script type="text/javascript">
function changeCodes(){
var img= document.getElementsByTagName("img")[0];
img.src = "/Day11_Response1/servlet/CodeServlet?r="+Math.random();
}
</script>
</body>
</html>
####第三节 request对象
定义将客户端请求信息提供给某个 servlet 的对象。servlet 容器创建ServletRequest 对象,并将该对象作为参数传递给该 servlet 的service方法。
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。
小结: 同响应相同,客户端请求协议都是基于HTTP所以我们选用HttpServletRequest来操作用户发送过来的请求的数据!
URL :Uniform Resource Location (统一资源定位符) 网址
URI :Uniform Resource Identifier (统一资源标识符) URI包含URL
美国总统:—》李学智 URI
11331401230120401203—>李学智
美国白宫10号楼99号房间–>李学智的房间 URL
//获取请求路径相关参数
**
getRequestURL方法返回客户端发出请求时的完整URL。
getRequestURI方法返回请求行中的资源名部分。
getQueryString 方法返回请求行中的参数部分。
getRemoteAddr方法返回发出请求的客户机的IP地址
getRemoteHost方法返回发出请求的客户机的完整主机名
getRemotePort方法返回客户机所使用的网络端口号
getLocalAddr方法返回WEB服务器的IP地址。
getLocalName方法返回WEB服务器的主机名
getMethod得到客户机请求方式
//获取请求头信息
getHead(name)方法
getHeaders(String name)方法
getHeaderNames方法
//获取请求正文参数
**getParameter(name)方法
**getParameterValues(String name)方法
getParameterNames方法
getParameterMap方法 //做框架用,非常实用
getInputStream方法 获取输入流
//1.测试获取请求行数据的方法和请求头的方法
//1.获取请求行的方法
//获取请求方式
String method = request.getMethod();
//获取请求的url
String url = request.getRequestURL()+"";
//获取uri
String uri = request.getRequestURI();
//获取请求的参数 get
String query = request.getQueryString();
//获取请求人的ip
String ip = request.getRemoteAddr();
//获取请求的主机名
String host = request.getRemoteHost();
System.out.println(method+" url:"+url+" uri:"+
uri+" query:"+query+" ip:"+ip+" host:"+host);
//获取请求信息
//全部输出
//post fix
String header = request.getHeader("user-agent");
if (header.contains("firefox")) {
}
//获取所有请求的names
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String name = (String) headerNames.nextElement();
//根据name获取keys
Enumeration<String> headers = request.getHeaders(name);
while (headers.hasMoreElements()) {
String key = (String) headers.nextElement();
System.out.println(name+"--->"+key);
}
}
将数据封装到实体类上
创建一个对应的实体类!
实体类要变量命名和变量类型都有相应的要求,要求变量名跟提交参数的key相同,变量跟参数类型形同!
public class User {
private String username;
private String password;
private String sex;
private String [] hobby;
//getter/setter
}
原生方式进行解析
//表单的name值和value值
//key name值 value values值
Map<String, String[]> parameterMap = request.getParameterMap();
JavaBean bean = new JavaBean();
Set<Entry<String, String[]>> entrySet = parameterMap.entrySet();
for (Entry<String, String[]> entry : entrySet) {
//entry map中的一条
//username password sex
String key = entry.getKey();
String[] value = entry.getValue();
try {
PropertyDescriptor descriptor =
new PropertyDescriptor(key, JavaBean.class);
Method set = descriptor.getWriteMethod();
/**
* 参数:哪个对象的set方法
* password username sex
*/
if (value.length == 1) {
set.invoke(bean, value[0]);
}else{
set.invoke(bean, (Object)value);
}
} catch (IntrospectionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
使用Apache BeanUtils进行快速映射
1.导入beanutils对应jar包、logging日志、commons-collections-3.2.1.jar
2.映射
BeanUtils.populate(bean2, request.getParameterMap());
System.out.println(bean2);
1页面跳转
重定向
转发
2 response对象
3 request对象
1.添加登录功能,将用户登录,修改为连接数据版本
登录成功 重定向商城页面
2.使用BeanUtils工具实现注册功能,采用Dao模式,注册成功后重定向到登录页面
1、request.getAttribute()和request.getParameter()的区别