- 1,关于Servlet
- 2,第一个Servlet程序
- 3,Servlet原理
- 4,Mapping问题
- 5,ServletContext对象
- 5.1,ServletContext的应用:共享数据
- 5.2,ServletContext的应用:获取初始化参数
- 5.3,ServletContext的应用:请求转发
- 5.3,ServletContext的应用:读取资源文件
- 6,HttpServletResponse
- 6.1,内部结构简单分类
- 6.2,response实现下载文件
- 6.3,response实现验证码功能
- 6.4,response实现重定向(重点)
- 7,HttpServletRequest
- 代码演示一:重定向、获取前端参数
- 代码演示二:请求转发、获取前端参数
- Servlet就是sun公司开发动态web的一门技术
- Sun在这些APi中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
-
①编写一个类,实现Serlet接口
-
②把开发好java类部署到web服务器中。
-
把实现了Servlet接口的Java程序叫做,Servlet
2,第一个Servlet程序
①构建一个普通Maven项目,删除src目录,在pom.xml文件中导入Servlet和JSP相关依赖:
javax.servlet javax.servlet-api 4.0.1 javax.servlet.jsp javax.servlet.jsp-api 2.3.3
②创建目录把Maven项目搭建完整
③编写一个普通类实现Servlet接口,这里我们直接继承HttpServlet。重写doGet()、doPost()。
因为Serlvet接口Sun公司有两个默认的实现类:HttpServlet,GenericServlet。(GenericServlet实现了Servlet接口,然后HttpServlet继承了GenericServlet,所以我们自己的类只需要继承HttpServlet即可,就可满足Servlet程序要求)
public class HelloServlet extends HttpServlet {
//一般要重写doGet和doPost。
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入了DOGET方法"); //标志
//ServletOutputStream outputStream = resp.getOutputStream();
PrintWriter writer = resp.getWriter(); //响应流
writer.print("Hello,Serlvet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//由于get,post只是请求实现的不同方式,可以相互调用,因为业务逻辑都一样
doGet(req, resp); //此处调用了上面的逻辑。就可以不用处理doPost(),专注于处理doGet()
}
}
④在web.xml中编写Servlet映射
为什么需要映射:我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径;
hello com.kuang.servlet.HelloServlet hello /hello
⑤配置Tomcat
⑥启动Tomcat测试
启动Tomcat自动打开:http://localhost:8080/s1/
端口为8080,项目名路径即为/s1,会先进入index.jsp。
如果想要刚才在xml文件中映射的/hello,可以访问:http://localhost:8080/s1/hello
成功访问,打开控制台查看:
表明进入了doGet()方法。
3,Servlet原理
Servlet由Web服务器调用,Web服务器收到浏览器请求后,会:
4,Mapping问题
注意:一个Servlet可以指定一个或多个映射路径,也可以指定通用映射路径:
-
①指定一个:
-
②指定多个
-
③指定通用映射路径(如使用*):
(此时hello下的任何请求都可以映射成功,乱写也行,如)
但要注意*前面不能加项目映射的路径,否则会访问失败。
5,ServletContext对象
①通过股骨架创建一个Maven的module,servlet-02用于演示
②把 srcmainwebappWEB-INFweb.xml 替换为如下的内容:
③创建目录把Maven项目搭建完整
④配置Tomcat
web容器(如Tomcat)在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用;
ServletContext可以理解为整个web应用,凌驾于所有的Servlet之上。
5.1,ServletContext的应用:共享数据
共享数据:
- 在一个Servlet中保存的数据可以在另一个Servlet中访问到。
①通过HelloServlet向ServletContext中存数据。
public class HelloServlet extends HttpServlet {
//ServletContext应用1:共享数据
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//this.getServletContext() 获得Servlet上下文(重点)
ServletContext servletContext = this.getServletContext();
String username="小白"; //数据对象
//将一个数据保存至ServletContext中,名字为:username,值为username(键值对)
servletContext.setAttribute("username",username);
System.out.println("hello");
}
}
②通过GetServlet取出HelloServlet往ServletContext中存入的数据
public class GetServlet extends HttpServlet {
//ServletContext应用1:共享数据
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//数据
// this.getServletContext():想取存进去的东西,要先获取此ServletContext对象。HelloServlet和GetServlet拿到的都是同一个ServletContext
ServletContext servletContext = this.getServletContext();
String username = (String) servletContext.getAttribute("username"); //强转成String
//响应
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
writer.print("名字"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
③在web.xml中注册
hello com.kuang.servlet.HelloServlet hello /hello getc com.kuang.servlet.GetServlet getc /getc
④启动Tomcat
启动之后自动打开如下页面:
直接进入/getc,发现名字后面是null:
这是因为我们还没有往ServletContext里存数据,就访问了/getc去取数据,所以为null。)
所以正确的方式为先访问/hello
这时控制台会输出 hello,因为存数据之后执行了HelloServlet中的输出语句:如下图
此时再访问/getc就会成功拿到存入ServletContext中的共享数据。
①再XML中配置一些初始化参数
url
jdbc:mysql://localhost:3306/mybatis
②ServletContext类对象调用getInitParameter()获取初始化参数
public class ServletDemo03 extends HttpServlet {
//ServletContext应用2:获取初始化参数
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");//可以获取web.xml中初始化的参数
//PrintWriter writer = resp.getWriter();
//writer.print(url); 也可以使用如下的方式,一步到位
resp.getWriter().print(url); //把String类型的url打印出来看一下
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
③在web.xml中注册
gp com.kuang.servlet.ServletDemo03 gp /gp
④启动Tomcat成功访问到参数内容
①编写Servlet
getRequestDispatcher():获取请求转发,参数为String类型的path,此参数即需要转发到的地址。
比如参数"/gp",“/”表示当前项目,/gp:转发到gp请求。
最后还需要调用forword()实现请求转发。
public class ServletDemo04 extends HttpServlet {
//ServletContext应用3:请求转发
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
System.out.println("进入了ServletDemo04"); //标志
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/gp"); //转发的请求路径
requestDispatcher.forward(req,resp); //调用forward实现请求转发(通过getRequestDispatcher转发到另一个页面)
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
②在web.xml中注册
sd4 com.kuang.servlet.ServletDemo04 sd4 /sd4
③启动Tomcat,访问/sd4,效果如下图所示:
请求到/sd4,但通过请求转发去了另一个页面/gp,转发的时候路径是没有变的(和重定向不同,重定向路径会变)。
请求转发机制的通俗理解:
A想拿到C的资源,但A当前只能找到B,B可以去找C拿,C返回给B之后,B再转发给A。此过程中A始终和B交互,没有看到C,所以路径不变。
(而重定向是:A找到B告诉B它需要某个资源,但此资源只要C处才有,这时B告诉A让它去找C拿,于是A又去找C)
读取资源文件需要一个文件流,先在resources目录下里创建db.properties文件,文件内容如下:
Javaweb之前读取配置文件的方式是:
- 使用load()方法并放入相应文件流作为参数。
以上方式中需要涉及到文件的绝对地址,但在Web应用需要走服务器,无法保证文件绝对地址,因此需要要观察target目录,看文件会生成在web的哪个地方。
WEB-INF目录下的classes目录包含main中java目录和resources目录中文件生成的目录,也称之为classpath(类路径)
①编写Servlet
先获取ServletContext对象,用此对象调用getResourceAsStream()
public class ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");//路径相对于生成的target目录,第一个/表示当前web项目不可省略
Properties properties = new Properties();
properties.load(is); //把流加载进去
String user = properties.getProperty("username");
String pwd = properties.getProperty("password");
resp.getWriter().print("user:"+user+" pwd:"+pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
②到web.xml文件中注册
sd5 com.kuang.servlet.ServletDemo05 sd5 /sd5
③启动Tomcat,访问/sd5
web服务器接收到客户端的http请求后,
会针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse。
- 要获取客户端请求过来的参数,使用HttpServletRequest
- 要获取客户端响应的一些信息,使用HttpServletResponse
6,HttpServletResponse
HttpServletResponse extends ServletResponse
6.1,内部结构简单分类其中:
负责向浏览器发送数据的方法:
servletOutputstream getOutputstream() throws IOException; Printwriter getwriter() throws IOException;
负责向浏览器发送响应头的方法,比如:
void setCharacterEncoding(String var1); void setContentLength(int var1); void setContentLengthLong(long var1); void setContentType(String var1); void setDateHeader(String varl,long var2) void addDateHeader(String var1,long var2) void setHeader(String var1,String var2); void addHeader(String var1,String var2); void setIntHeader(String var1,int var2); void addIntHeader(String varl,int var2);
响应的状态码
1,向浏览器输出消息(前面一直在讲,此处不再赘述)
2,下载文件:
- ①先获取下载文件的路径
- ②下载的文件名
- ③想办法让浏览器支持下载我们需要的资源
- ④获取下载文件的输入流
- ⑤创建缓冲区
- ⑥获取OutPutStream对象
- ⑦将FileOutputStream流写入buffer缓冲区
- ⑧使用OutputStream对象将缓冲区中的数据输出到客户端
编写Servlet程序:
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1,要获取下载文件的路径
String realPath1=this.getServletContext().getRealPath("/海湾.jpg");
System.out.println(realPath1); //F:programmingJavanotesapache-tomcat-7.0.93webappsr海湾.jpg
//注意ServletContext是由Tomcat创建的,所以/海湾.jpg是去Tomcat的webapps下找,找不到
//此处把路径(target下的文件路径)写死
String realPath = "F:\javawebcode\javaweb\response\target\classes\海湾.jpg";
System.out.println("下载的文件的路径为:"+realPath); //下载的文件的路径为:F:javawebcodejavawebresponsetargetclasses海湾.jpg
//2,下载的文件名是啥?
String fileName = realPath.substring(realPath.lastIndexOf("\") + 1); //注意此处很巧妙。\转义了一个,最后+1表示截取/后面的下一个位置到最后
//3,设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西(设置浏览器行为,使用response)
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8")); //URLEncoder.encode(fileName,"UTF-8"))转码使中文名文件可正常显式
//4,获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);
//5,创建缓冲区
byte[] buffer=new byte[1024];
int len;
//6,获取OutputStream对象
ServletOutputStream os = resp.getOutputStream();
//7,将FileOutputStream流写入到bufer缓冲区
while ((len=in.read(buffer))!=-1){
os.write(buffer,0,len);
}
//8,使用OutputStream将缓冲区中的数据输出到客户端!
os.close();
in.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
web.xml中注册
filedown com.kuang.servlet.FileServlet filedown /down
启动Tomcat测试访问
成功下载
了解
编写Servlet
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//如何让浏览器五秒自动刷新一次
resp.setHeader("refresh","3");
//在内存中创建一个图片
BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D graphics = (Graphics2D) image.getGraphics(); //相当于一支笔
//设置图片背景色
graphics.setColor(Color.white); //使用画笔画出白色背景
graphics.fillRect(0,0,80,20);
//给图片写数据
graphics.setColor(Color.BLUE); //给画笔换颜色
graphics.setFont(new Font(null,Font.BOLD,20));
graphics.drawString(makeNum(),0,20); //把随机数画成一个字符串,图片上就有了数据
//告诉浏览器这个请求用图片的方式打开
resp.setContentType("image/jpeg");
//网站存在缓存,此处不让浏览器缓存
resp.setDateHeader("expires",-1); //设为-1
resp.setHeader("Cache-Control","no-cache"); //缓存策略为不缓存
resp.setHeader("Pragma","no-cache");
//把图片写给浏览器
ImageIO.write(image,"jpg",resp.getOutputStream());
}
//生成随机数
private String makeNum(){
Random random = new Random();
String num= random.nextInt(9999999)+""; //七位数的验证码
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 7 - num.length(); i++) {
sb.append(0); //生成的数字不足七位时使用0填充。
}
String s=sb.toString()+num; //保证是七位
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
web.xml中注册
ImageServlet com.kuang.servlet.ImageServlet ImageServlet /img
启动Tomcat测试:
屏幕中间出现一个七位数的验证码,五秒刷新一次。
用户登陆成功的跳转,就是一个重定向。
重定向使用的方法是:
- public void sendRedirect(String location) throws IOException;
①编写index.jsp
<%@ page contentType="text/html; charset=UTF-8"%>Hello World!
<%--这里提交的路径,需要寻找到项目的路径--%> <%--pageContext.request.contextPath()代表当前项目--%>
②编写Servlet
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/r/img"); //重定向 /r是当前项目
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
③web.xml中注册
RedirectServlet com.kuang.servlet.RedirectServlet RedirectServlet /red
④启动Tomcat测试
启动Tomcat,进入路径/red,自动跳转至/img
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过HttpServletRequest的方法可以获取客户端的所有信息。
HttpServletRequest应用主要有:
- 重定向、获取前端传递的参数,请求转发…
两个常用方法:
- getParameter(String s) 返回String型
- getParameterValues(String s) 返回String[ ]型
代码演示一:重定向、获取前端参数
①编写success.jsp(跳转成功的页面)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
success
②编写Servlet
public class RequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//处理请求
String username = req.getParameter("username");//从请求里获取参数
String password = req.getParameter("pwd");
System.out.println(username+":"+password);
//重定向(注意要路径问题,否则会404,404表示代码正确,页面不对)
resp.sendRedirect("/r/success.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
③配置web.xml
request com.kuang.servlet.RequestTest request /login
④启动Tomcat测试
数据提交后,自动跳转:
查看控制台,发现成功从请求中获取参数
重定向的时候一定要注意路径的问题,否则会报404!!!
代码演示二:请求转发、获取前端参数
①编写Servlet
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8"); //防止输出乱码
resp.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String pwd = req.getParameter("pwd");
String[] hobbies = req.getParameterValues("hobby"); //获取多选框多个值
System.out.println("===========================");
//后台接收中文乱码问题
System.out.println(username);
System.out.println(pwd);
//System.out.println(Arrays.toString(hobbies));
System.out.println(hobbies);
System.out.println("===========================");
//通过请求转发,这里的/success.jsp中的/代表当前的web应用
req.getRequestDispatcher(req.getContextPath()+"/success.jsp").forward(req,resp); //此处路径不写死
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
注意把握请求转发(307)和重定向(302)的区别!



