一、JavaWeb概述
1. 什么是Javaweb
JavaWeb是指所有通过Java语言编写,可以通过浏览器访问的程序的总称。
JavaWeb是基于请求和响应来开发的。
请求:Request
响应:Response
客户端(浏览器) 服务器(Tomcat等)
2. Web资源分类
- 静态资源:HTML,CSS,JS,txt,mp4,jpg等等
- 动态资源:jsp页面,servlet程序
3. 常用Web服务器
- Tomcat:提供对jsp和servlet的支持,是一种轻量级的JavaWeb容器
- Jboss
- GlassFish
- Resin
- WebLogic
4. Tomcat的使用
①Tomcat目录中的webapps文件夹存放部署的Web工程
②启动Tomcat,找到bin目录下的startup.bat文件。或者管理员权限下的cmd,输入startup。
③测试是否启动成功,访问本机真实地址或者(localhost:8080)
④停止Tomcat的方式:找到tomcat的bin目录下的shutdown.bat按钮
⑤如何修改Tomcat的端口号:
mysql默认3306,Tomcat默认8080
server.xml配置文件下的Connector标签,修改port属性,修改完端口号之后要重启Tomcat⑥HTTP协议默认端口是80
部署Web工程到Tomcat服务器
Tomcat是一个服务器,供客户端访问Web工程。
- 直接把Web工程拷贝到Tomcat的webapps下如何访问Web工程。先localhost:8080(这一步就相当于切入到webapps文件夹下)然后再加上这里面某个html文件的路径即可
IDEA整合Tomcat服务器
- 全局添加服务器
- 单个工程添加服务器
Server&Deployment
- 配置工程输出路径
- 解决服务器控制台输出乱码
二、Servlet
1. 什么是Servlet
- Servlet是JavaEE规范之一,规范就是接口
- Servlet是JavaWeb三大组件之一,三大组件分别是Servlet程序,Filter过滤器,Listener监听器
- Servlet是运行在服务器上的一个Java小程序,它可以接收客户端发送过来的请求,并响应客户的请求。Tomcat等服务器相当于容器,里面装了许多Servlet。
2. 实现Servlet程序
编写一个类去实现Servlet接口
实现service方法,处理请求并响应请求得到数据(抽象类HttpServlet中service方法就包含了doGet,doPost,doDelete等等所有请求类型的方法)
到web.xml文件中去配置Servlet程序的访问地址
<-- servlet标签:给Tomcat配置Servlet程序--> <servlet> <-- servlet-name标签:给servlet程序起一个别名(别名一般是该servlet实现类的类名)--> <servlet-name>MyServletImpl</servlet-name> <-- 上面那个servlet的全限定类名--> <servlet-class>com.zt.MyServletImpl</servlet-class> </servlet> <-- servlet-mapping标签:给servlet程序配置一个访问地址--> <servlet-mapping> <-- 该处servlet-name标签作用是:告诉服务器,当前mapping标签配置的地址给哪个servlet程序用 一般和上面那个一致,就表示该地址就给该servlet程序用--> <servlet-name>MyServletImpl</servlet-name> <-- url-pattern标签:用来配置访问地址 /:"/"在服务器解析的时候,被解析为:http://ip:port/工程路径/。其中工程路径就是配置Tomcat时的Deployment中的context /hello:这表示http://ip:port/工程路径/hello,即该servlet程序要去访问这个地址,然后执行service方法 --> <url-pattern>/hello</url-pattern> //在开发的时候一般遵守习惯:/xxx,xxx的内容与类名有关联 </servlet-mapping>
3. Servlet生命周期
- 执行Servlet构造方法
- 执行init()初始化方法
- 执行service()方法,每次调用Servlet都会调用该方法
- 执行destroy()方法
4. 通过继承HttpServlet实现Servlet程序
一般实际开发项目中,都是使用继承HttpServlet类(它实现了Servlet接口,它是个抽象类)去实现Servlet程序
①编写一个类继承HttpServlet
②根据业务需要重写doGet()doPost()等方法
③到web.xml文件中配置Servlet程序的访问地址
ServletConfig类
Servlet程序的配置类,它是某个servlet应用程序的config,不是全局的config
作用:
(1)可以获取Servlet程序的别名servlet-name
(2)获取初始化参数init-param
(3)获取ServletContext对象
ServletContext类
这是一个全局的对象,作用域为整个Web工程,可以用它去做一些全局性的配置,也可以获得全局的属性
ServletContex是一个接口,它表示Servlet上下文对象
一个Web工程只有一个ServletContext对象实例,相对于每个servlet程序而言
ServletContext对象是一个域对象
ServletContext在web工程部署的时候创建,在web工程停止的时候销毁
存数据 取数据 删除数据 Map put get remove 域对象 setAttribute getAttribute removeAttribute
HttpServletRequest类(实现ServletRequest接口)
作用
每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到HttpServletRequest对象中,然后传递到service方法(doGet,doPost)中给我们使用。我们可以通过HttpServletRequest对象,获取到请求的所有信息HttpServletRequest常用API
String getContextPath():获取Web工程相对路径(Tomcat服务器中除去http://ip:port) System.out.println(req.getContextPath()); /Temp URI getRequestURI():获取请求的资源路径,相对路径,某Web工程下的路径 System.out.println(req.getRequestURI()); /Temp/hello URL getRequestURL():获取请求的统一资源定位符(绝对路径) System.out.println(req.getRequestURL()); http://localhost:8080/Temp/hello
String getRemoteHost():获取客户端的ip地址 String getParameter():获取请求的参数 String getParameterValues():获取请求的参数(多个值时) 可以用于获取用户输入的值,如用户名。 String getHeader():获取请求头 String getMethod():获取请求的方式GET或POST setAttribute(key,value):设置域数据 Object getAttribute(key):获取域数据 getRequestDispatcher("/+servlet名"):获取下一个转发对象。必须以斜杠开头 RequestDispatcher rd = servletRequest.getRequestDispatcher("Two"); rd.forward(servletRequest,servletResponse); //获取之后进入到下一个servlet总 req.setCharacterEncoding("UTF-8")
HttpServletResponse类
每次请求进来,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用,HttpServletResponse表示所有响应的信息。如果需要设置返回给客户端的信息,都可以通过HttpServletResponse对象来进行设置
两个输出流
字节流:getOutputStream(),常用于下载(传递二进制数据)
字符流:getWriter(),常用于回传字符串(常用)
resp.setContentType("text/html; charset=UTF-8"); //同时设置服务器和客户端的字符集为UTF-8 PrintWriter writer = resp.getWriter(); writer.write("Hello World");
请求重定向
请求重定向是指,客户端给服务器发送请求,然后服务器给客户端一个新地址,客户端转发到新地址。
resp.sendRedirect("http://www.sina.com");
注意
- 不能重定向到自己,否则浏览器会报错
- 浏览器地址会发生变化,请求次数为两次,而不是请求转发的一次
- 两个servlet程序不共享HttpServletRequest域中的数据,因为每个HttpServletRequest只属于一个Servlet
- 不能访问WEB-INF下的内容
- 可以访问工程外的资源
三、HTTP协议
1. GET请求
- 请求的方式 GET
- 请求的资源路径
- 请求的协议版本号 HTTP/1.1
- 请求头 key:value 组成
2. POST请求
- 请求方式POST
- 请求资源路径
- 请求的协议版本号 HTTP/1.1
- 请求头 key:value
- 请求体:发送给服务器的数据
<常见的GET请求和POST请求>
GET请求:
①<form>标签,method=get
②<a>标签
③<link>标签引入css
④<Script>标签引入js文件
⑤<img>标签引入图片
⑥<iframe>标签引入html页面
⑦在浏览器地址栏中输入地址后敲回车
POST请求:
<form>标签,method=post
3. 常用请求头
- Accept:表示客户端可以接收的数据类型
- Accpet_language:表示客户端可以接收的语言类型
- User-Agent:表示客户端浏览器的信息
- Host:表示请求时的服务器ip和端口号
4. 响应的HTTP格式
- 响应的协议和版本号
- 响应状态码
- 响应状态描述符
- 响应头:key:value
- 响应体 :回传给客户端的数据
5. 响应码
- 200:表示请求成功
- 302:表示请求重定向()
- 404:表示请求服务器已经收到了,但是数据不存在(请求地址错误或数据不存在)
- 500:表示服务器已经收到请求,但是服务器内部错误(代码错误)
6. MIME类型
- 格式:大类型/小类型如:
image/jpg video/mp4
四、监听器
- 作用:监听某种事物的变化,回调函数,反馈给客户做一些响应的处理
- ServletContextListener监听器
五、文件上传与下载
1. 上传
- 导入依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
- form表单设置
<form action="http://localhost:8080/day01_2_war_exploded/photo" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
头像:<input type="file" name="image"><br/>
<input type="submit" value="上传头像">
</form>
- ServletFileUpload获得文件对象
// 1、判断上传的数据是否是多段数据,只有是多段数据才能解析
if(ServletFileUpload.isMultipartContent(req)){
// 2、创建fileItemFactory工厂实现类
FileItemFactory fileItemFactory = new DiskFileItemFactory();
// 3、创建用于解析上传数据的工具类ServletFileUpload类
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
// 4、解析数据,得到每一个FileItem
try {
//解析request,得到文件项
List<FileItem> fileItems = servletFileUpload.parseRequest(req);
for (FileItem f : fileItems){
// 如果每个fileItem是普通表单项
if (f.isFormField()){
// 获得表单项的name属性值
System.out.println(f.getFieldName());
// 获得表单项的value值
System.out.println(f.getString("UTF-8"));
}
// 否则上传的是文件
else {
// 获得表单中的各项input里的name属性名称以及他们的值
System.out.println(f.getFieldName());
// 获得文件名,因为上传的是文件,则要获取名称不能用getFiledName
System.out.println(f.getName());
// 保存在服务器,参数为地址
f.write(new File("E:\\"+f.getName()));
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
2. 下载
- form表单
<form action="http://localhost:8080/day01_2_war_exploded/download" method="get">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
<input type="submit" value="下载文件">
</form>
- 客户端
// 1、获取要下载的文件名
String downloadFileName = "picture.png";
// 2、获取读取要下载的文件内容的对象(ServletContext)
ServletContext sc = getServletContext();
// 获取要下载的文件类型
String mimeType = sc.getMimeType("/download/" + downloadFileName);
// 在回传数据之前,告诉客户端要返回的数据类型
resp.setContentType(mimeType);
// 告诉客户端收到的数据是用在直接使用(在浏览器打开)还是保存在本地
// Content-Disposition响应头,表示收到的数据怎么处理
// attachment:表示附件,表示下载使用 filename=表示指定下载的文件名
// 将文件名进行url编码,防止下载时客户端出现中文乱码
resp.setHeader("Content-Disposition","attachment; filename=" + URLEncoder.encode(downloadFileName,"UTF-8"));
// 获取下载文件的输入流
InputStream resource = sc.getResourceAsStream("/download/"+downloadFileName);
// 3、获取响应的输出流,用于下载
OutputStream os = resp.getOutputStream();
// 4、读取输入流中全部的数据,复制给输出流,输出给客户端
IOUtils.copy(resource,os);
六、Cookie
1. 什么是Cookie
Cookie是服务器通知客户端保存键值对的一种技术,客户端有了cookie后,每次请求都发送给服务器,每个cookie的大小不超过4kB。cookie如果要支持中文,必须对值进行Base64编码
2. 设置Cookie
创建
// 创建cookie对象
Cookie cookie1 = new Cookie("key1", "value1"); //cookie可以一次创建多个
// 通知客户端保存cookie
resp.addCookie(cookie1);
Cookie cookie2 = new Cookie("key2", "value2"); //cookie可以一次创建多个
// 通知客户端保存cookie
resp.addCookie(cookie2);
流程:
获取
Cookie[] cookies = req.getCookies();
for (Cookie c : cookies)
System.out.println(c.getName() + " " + c.getValue());
修改
//覆盖cookie的value属性,类似Map,key不变。
// 创建cookie对象
Cookie cookie1 = new Cookie("key1", "newValue1"); //cookie可以一次创建多个
// 通知客户端保存cookie
resp.addCookie(cookie1);
存活时间
// 默认为-1,负数表示浏览器一关闭(即一个session结束),cookie就删除
cookie1.setMaxAge(-1);
// 0表示马上删除,都不需要等待浏览器关闭
cookie1.setMaxAge(0);
// 以秒为单位,设置1小时后删除
cookie1.setMaxAge(60*60);
有效路径
// 只有当访问的url是以下url时,才会创建cookie
cookie1.setPath("url");
3. 练习
免用户名登录
<form action="login" method="get">
用户名:<input type="text" name="username" value="${cookie.username.value}"/><br/> //将保存的cookie显示到页面上
密码:<input type="password" name="password" value="${cookie.password.value}"/><br/>
<input type="submit" value="登录">
</form>
resp.setContentType("text/html; Charset=UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
if (username.equals("abcd")&&password.equals("1234")){
Cookie cookie = new Cookie(username,password);
cookie.setMaxAge(60*60);
resp.addCookie(cookie);
resp.getWriter().write("登录成功");
}else {
resp.getWriter().write("登录失败");
}
七、Session
1. 什么是Session
- session是一个接口(HttpSession),它用来维护一个客户端和服务器之间关联的一种技术
- 每个客户端都有自己的一个session会话
- session会话中,经常用来保存用户登录之后的信息。(一个session就是客户端与服务器之间的一次会话,关闭客户端就结束一次会话)
- cookie是保存在客户端,session保存在服务器端
2. 设置Session
创建和获取
// 创建Session会话对象
HttpSession session = req.getSession();
// 判断当前Session是否是新创建的
System.out.println(session.isNew());
// 获取Session的唯一标识id
System.out.println(session.getId());
// 取得key1的值
session.getAttribute("key1");
超时时间
超时时间指的是客户端两次请求之间的最大间隔
// 设置当前session的超时时间,以秒为单位,超过超时时间就销毁
// 默认的超时时间为:1800秒,因为Tomcat服务器的默认设置为30分钟
session.setMaxInactiveInterval(60);
3. Session和Cookie的关系
session技术,底层其实是基于cookie技术实现的
没有cookie的时候,getSession()获得一个session,把session的id给cookie的value。以后有了cookie,再getSession()时就获得session的id与cookie的value值相同的session。
八、过滤器
1. 概述
- 用于拦截请求,过滤响应,拦截请求的常见应用场景:权限检查、日记操作、事务操作等
- 要求:在web工程下新建一个admin目录,目录下的所有资源必须是用于登录之后才允许访问
- 思路:用户登录后的信息保存在服务器的session域中,检查session域中是否包含有用于登录的信息即可
Filter的生命周期
- 构造器方法
- init初始化方法
- doFilter过滤方法
- destroy销毁方法
实现filter接口,运行doFilter方法
HttpSession session = ((HttpServletRequest) request).getSession();
Object user = session.getAttribute("user");
if (user==null){
// 如果user=null,则权限检查没有通过,就转到登录页面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}else {
// 权限检查通过,放行,让客户端访问目标资源
chain.doFilter(request,response);
}
Session域保存用户数据
resp.setContentType("text/html; charset=UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
if (username.equals("abcd")&&password.equals("1234")){
req.getSession().setAttribute("user",username);
System.out.println(username);
resp.getWriter().write("登录成功");
}else {
req.getRequestDispatcher("/login.jsp").forward(req,resp);
}
web.xml配置过滤器
<!--filter标签配置一个filter过滤器-->
<filter>
<!--给filter起一个别名-->
<filter-name>MyFilter</filter-name>
<!--配置filter的全限定类名-->
<filter-class>com.zt.MyFilter</filter-class>
</filter>
<!--filter-mapping配置filter过滤器的拦截路径-->
<filter-mapping>
<!--filter-name表示当前的拦截路径给哪个filter使用-->
<filter-name>MyFilter</filter-name>
<!--/斜杠表示当前的请求地址为:http://ip:port/工程路径/ 映射到idea的webapp目录下
/admin/*表示拦截访问路径为admin目录下的全部url-->
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
2. FilterConfig类
- 它是filter过滤器的配置文件类,Tomcat每次创建Filter的时候也会创建一个FilterConfig类的对象,包含了Filter配置文件的配置信息。作用是获取filter过滤器的配置内容
- 过滤链FilterChain
FilterChain.doFilter()方法的作用:
①如果有filter,执行下一个Filter过滤器
②执行目标资源(没有Filter过滤器)**多级Filter执行顺序
3. Filter的拦截路径
精确匹配
<url-pattern>/admin/demo1.jsp</url-pattern>
目录匹配
<url-pattern>/admin/*</url-pattern>
后缀名匹配
<表示以.html结尾的都被拦截,这个后缀名不是说必须这种文件,而是所有字符串都可以,只要有这种字符串,都会被拦截 filter过滤器只关心请求的地址是否匹配,不关心请求的地址是否存在。> <url-pattern>*.html</url-pattern>