整体介绍
◆介绍请求与响应的结构 ◆讲解Java Web开发内置对象 ◆解决Web应用中文乱码
URL与URI
◆URL统一资源定位符,表示Web应用对外暴露的访问地址 ◆示例:http://www.imooc.com/index.html ◆URI统一资源标示符,表示Web应用资源的访问路径 ◆示例:/index.html
HTTP请求的结构
◆HTTP请求包含三部分:请求行、请求头、请求体
新建servlet工程,选择JAVA Enterprice,选择maven和junit,然后勾选上servlet组件,最后创建成功,记得在项目结构中创建web资源目录,并将web资源目录修改在src\main\webapp下,上面下面的都要修改
(69条消息) IDEA Web项目out/classes目录没有编译的class类文件 - IDEA环境下创建Maven WebApp_WalkingWithTheWind~的博客-CSDN博客
记得配置tomcat时在deployment选项卡把默认访问路径删了,因为我们只需要通过注解@websock进行url路径配置
新建java类com.imooc.servlet.RequestServlet
package com.imooc.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RequestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("This is get method");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("This is post method");
}
}
记得extendsHttpServlet 然后映射
<servlet>
<servlet-name>request</servlet-name>
<servlet-class>com.imooc.servlet.RequestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>request</servlet-name>
<url-pattern>/request</url-pattern>
</servlet-mapping>
继续在webapp下创建request.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/request" method="post">
<input name="username"/>
<input name="password" type="password"/>
<input type="submit">
</form>
</body>
</html>
右键检查,录制网络活动,即可看到请求结构,注意使用get与post方式的区别
如何利用user-Agent进行多端应用开发?
巧用请求头开发多端应用
pc和安卓访问相同网站所呈现样式不一样,user-Agent也发生变化 继续创建UserAgentServlet.java
package com.imooc.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/ua")
public class UserAgentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String ua = request.getHeader("User-Agent");
if(ua == null){
response.getWriter().println("User-Agent请求头不存在");
return;
}
String output = "";
if(ua.toLowerCase().indexOf("windows nt") != -1){
output = "<h1>这是PC端页面</h1>";
}else if(ua.toLowerCase().indexOf("iphone") != -1 || ua.toLowerCase().indexOf("android") != -1){
output = "<h1>这是移动端页面</h1>";
}
response.getWriter().println(output);
}
}
使用注解@WebServlet("/ua")
简化映射配置
http://localhost:8080/ua 即可访问
toLowerCase()
转小写
response.setContentType("text/html;charset=utf-8");
防止中文乱码
HTTP响应的结构
◆HTTP响应包含三部分:响应行、响应头、响应体
HTTP常见响应状态码
ContentType的作用
◆ContentType决定浏览器采用何种方式对响应体进行处理
servlet包下新建ContentTypeServlet.java
package com.imooc.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/ct")
public class ContentTypeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String output = "<h1><a href='http://www.baidu.com'><span>百度</span></a></h1>";
response.setContentType("text/html;charset=utf-8");
response.getWriter().println(output);
}
}
若改为text/plain,则直接将代码打印出来,改为text/xml,则以xml格式打印出来
charset=utf-8
表示强制使用utf-8对其中中文处理,就不会产生乱码问题了
请求转发与响应重定向
上面都是单个servlet请求与处理,但在项目中会存在servlet之间信息传递工作 ◆多个Servlet之间跳转有两种方式: ◆request.getRequestDispatcher().forward()-请求转发 ◆response.sendRedirect()-响应重定向
比如网站首页和登陆界面之间的跳转 新建java类com.imooc.servlet.forward,新建CheckLoginServlet.java
package com.imooc.servlet.forward;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/login")
public class CheckLoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
if(username.equals("admin") && password.equals("123456")){
System.out.println("用户登录成功");
//request.setAttribute("username",username);
//请求转发
//request.getRequestDispatcher("/index").forward(request,response);
HttpSession session = request.getSession();
session.setAttribute("username",username);
//响应重定向
response.sendRedirect("/index");
}else{
System.out.println("用户登录失败");
}
}
}
新建登陆页面html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
<input name="username">
<input name="password" type="password">
<input type="submit">
</form>
</body>
</html>
继续新建首页IndexServlet.java
package com.imooc.servlet.forward;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
//String username = (String)request.getAttribute("username");
HttpSession session = request.getSession();
String username = (String)session.getAttribute("username");
response.getWriter().println("我是MK网首页,当前用户:" + username);
}
}
首页html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>我是默认首页</h1>
</body>
</html>
登陆界面重写dopost方法,首页界面也要重写dopost方法 请求转发后url不变,不需要doget方法,响应重定向url改变,需要doget方法,需要产生两次交互,异常交给login,一次交给index
为何需要这两种方式,有什么区别
请求转发
◆请求转发是服务器跳转,只会产生一次请求 ◆请求转发语句是:request.getRequestDispatcher().forward()
- url链接不变,不跳转
- 方法一致
响应重定向
◆重定向则是浏览器端跳转,会产生两次请求 ◆响应重定向语句是:response.sendRedirect()
响应重定向产生的新请求方式默认使用get方式
适用于跳转第三方网站
设置请求自定义属性
◆请求允许创建自定义属性
◆设置请求属性:request.setAttribute(属性名,属性值)
◆获取请求属性:Object attr=request.getAttribute(属性名)
在login获取用户名
request.setAttribute("username",username);
在index得到用户名
String username = (String)session.getAttribute("username");
username生命周期与request一致,当改为使用响应重定向时,新的响应请求已经销毁request对象,所以用户名为null,适用于请求转发
如果想要重定向也能处理,需要使用范围更大的session对象
浏览器Cookie
◆Cookie(小甜饼)是浏览器保存在本地的文本内容 ◆Cookie常用于保存登录状态、用户资料等小文本 ◆Cookie具有时效性,Cookie内容会伴随请求发送给Tomcat
自动登录选项通过本地cookie即使退出浏览器也保持登陆状态 新建子包cookie 新建RandomServlet.java文件生成随机cookie值
package com.imooc.servlet.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Random;
@WebServlet("/cookie/random")
public class RandomServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Integer random = new Random().nextInt(10000);
Cookie cookie = new Cookie("random" , String.valueOf(random));
cookie.setMaxAge(60*60*24);
response.addCookie(cookie);
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("<h2>随机数" + random+ "已生成</h2>");
}
}
cookie.setMaxAge(606024);设置cookie有效期为一天,当关闭浏览器重新访问url时,可以继续访问
新建CookieServlet.java获取cookie
package com.imooc.servlet.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/cookie/show")
public class CookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
Integer random = -1;
response.setContentType("text/html;charset=utf-8");
if(cookies == null){
response.getWriter().println("未包含任何Cookie数据");
return;
}
for (Cookie c : cookies){
if(c.getName().equals("random")){
random = Integer.parseInt(c.getValue());
}
}
response.getWriter().println("name=random的cookie值为:" + random);
}
}
访问http://localhost:8080/cookie/show
用户会话Session
防止cookie泄露,使用Session提高安全性 ◆Session(用户会话)用于保存与“浏览器窗口”对应的数据 ◆Session的数据存储在Tomcat服务器的内存中,具有时效性 ◆Session通过浏览器Cookie的Sessionld值提取用户数据
通过cookie的Sessionld找到tomcat的内存,存入cookie
Session常用方法
◆request.getSession()-获取Session对象 ◆getsetremoveAttribute()-获取设置删除Session属性 ◆setMaxlnactivelnterval()-设置Session超时时间
新建子包session 新建RandomServlet.java随机生成cookie
package com.imooc.servlet.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Random;
@WebServlet("/session/random")
public class RandomServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Integer random = new Random().nextInt(10000);
HttpSession session = request.getSession();
session.setAttribute("random" , random);
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("<h2>随机数" + random + "已生成</h2>");
}
}
新建Seseion提取cookie
package com.imooc.servlet.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session/show")
public class SessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
Integer random = (Integer)session.getAttribute("random");
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("name=random的session值为:" + random);
}
}
Session的原理
不小心关闭浏览器窗口,在未到达存储周期30分钟前,sessionId与窗口绑定,cookie不存在了,用户本地没了sessionId,服务器会重新寻找一块sessionld,而浏览器关闭后,cookie消失,服务器sessionId存在,要30分钟后才销毁,再次打开根据SessionId得到cookie,存储周期后这块区域才会销毁
第一个请求是往Tomcat放数,第二个响应是从Tomcat取数
当点击网页下不同分栏是,登录信息不会改变,都会被提取出来,使用的是session方案 详细查看请求转发与网页重定向那一节,切换到新标签也能得到登陆信息
ServletContext与三大作用域对象
ServletContext
期望有个全局存储空间,不需要每次打开网页就从数据库重新读取,即使浏览器关闭也能提取出来,比如网站备案信息
◆ServletContext(Servlet_上下文对象),是Web应用全局对象 ◆ー个WebServletContext对象 ◆ServletContext随着Web应用启动而自动创建
新建ServletContextinitServlet.java文件
package com.imooc.servlet.servletcontext;
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;
import java.io.IOException;
@WebServlet("/servletcontext/init")
public class ServletContextInitServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("copyright", "Copyright© 2021 imooc.com 京ICP备 12003892号-11 京公网安备11010802030151号");
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("ServletContext已初始化");
}
}
在创建一个网页IndexServlet.java
package com.imooc.servlet.servletcontext;
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;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/servletcontext/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
ServletContext context = request.getServletContext();
String copyright = (String)context.getAttribute("copyright");
PrintWriter out = response.getWriter();
out.println("导航栏");
out.println("<hr/>");
out.println("首页正文");
out.println("<hr/>");
out.println(copyright);
}
}
Java Web三大作用域对象
◆HttpServletRequest-请求对象 ◆HttpSession-用户会话对象 ◆ServletContext-Web应用全局对象
Web应用的中文乱码由来
◆发送方与接收方对数据使用不同的字符集解析就会产生乱码 ◆解决乱码的思路是保证浏览器与服务器统一为UTF-8编码即可 ◆在Servlet中请求与响应都需要设置UTF-8字符集
webapp下新建search.html
<!DOCTYPE html>
<html lang="en">
<head>
<!--浏览器发送请求时使用的字符集编码-->
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/encoding/search" method="post">
<input name="keyword"/>
<input type="submit"/>
</form>
</body>
</html>
在新建java处理SearchServlet.java
package com.imooc.servlet.encoding;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/encoding/search")
public class SearchServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//在Tomcat 8以后,默认对GET请求发来的参数视为UTF-8编码进行解析
//在Tomcat 8以前,默认为ISO-8859-1,需要在server.xml配置字符集
String keyword = request.getParameter("keyword");
System.out.println(keyword);
response.setContentType("text/html;charset=utf-8");
response.getWriter().println(keyword);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//利用UTF-8编码解析请求体中的请求参数
request.setCharacterEncoding("UTF-8");
String keyword = request.getParameter("keyword");
System.out.println(keyword);
response.setContentType("text/html;charset=utf-8");
response.getWriter().println(keyword);
}
}
(69条消息) 设置Tomcat字符集为utf-8_皓月如我的博客-CSDN博客 注意doGet与doPost处理乱码方式不一样
web.xml常用配置
◆修改web应用默认首页 ◆Servlet通配符映射及初始化参数 ◆设置404、500等状态码默认页面
但没有输入任何URI时,会跳到首页,而不是404 在webapp下新建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>我是默认首页</h1>
</body>
</html>
web.xml配置
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>default.html</welcome-file>
</welcome-file-list>
不存在index.html,就会使用default.html
常见的URL用法
http://www.imooc.com/search?cid=785 http://www.imooc.com/class/785 http://www.imooc.com/785.class
我们不用注解配置,而使用xml配置,因为需要配置的多,后期便于维护
新建PatternServlet.java
package com.imooc.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class PatternServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*if(1==1){
throw new RuntimeException("未知错误");
}*/
String uri = request.getRequestURI();// URI:/class/785
// 只需要785这几个数字 +1表示不包括’/‘
String id = uri.substring(uri.lastIndexOf("/") + 1);
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<h1>");
if(id.equals("785")){
out.println("Vue3.0高阶实战");
}else if(id.equals("786")){
out.println("面霸修炼手册");
}else{
out.println("其他课程");
}
out.println("</h1>");
}
}
通过修改785,786控制不同网页访问 记得进行xml配置
<servlet>
<servlet-name>pattern</servlet-name>
<servlet-class>com.imooc.servlet.PatternServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>pattern</servlet-name>
<!--http://www.imooc.com/class/785-->
<url-pattern>/class/*</url-pattern>
</servlet-mapping>
<url-pattern>/class/*</url-pattern>
为通配符
我们可以对一个Servlet进行多个映射,可以添加
<servlet-name>pattern</servlet-name>
//http://www.imooc.com/785.class
<url-pattern>*.class</url-pattern>
</servlet-mapping>
注意,前缀加后缀的混合应用是不支持的的 比如下面代码
<servlet-mapping>
<servlet-name>pattern</servlet-name>
//http://www.imooc.com/class/785.class
<url-pattern>/class/*.class</url-pattern>
</servlet-mapping>
有一个特殊写法,对所有请求进行映射
<servlet-mapping>
<servlet-name>pattern</servlet-name>
<!– 对所有请求进行映射,Spring MVC框架中会使用到这个特性
<url-pattern>/</url-pattern>
</servlet-mapping>-->
启动时加载Servlet与错误页面设置
启动时加载Servlet
◆web.xml使用<load-on-startup>设置启动加载 ◆<load-on-startup>0~9999</load-on-startup> ◆启动时加载在工作中常用于系统的预处理
设置错误页面
tomcat默认提供的页面会暴露很多信息,导致受到攻击,所以一般会自己设置错误页面 webapp下新建目录error 新建404界面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
抱歉,您访问的页面不存在!
</body>
</html>
替换掉404,在web.xml文件中
<error-page>
<error-code>404</error-code>
<location>/error/404.html</location>
</error-page>
JavaWeb打包与发布
◆Java Web应用采用war包进行发布 ◆发布路径为:{TOMCAT HOME}/webapps ◆利用Maven实现war包导出
打包war包,核心在pom.xml中添加配置
<packaging>war</packaging>
修改war包名
<build>
<finalName>web-servlet</finalName>
</build>
然后运行右侧Maven栏package命令,如何不配置,打包的是jar包
target目录下可以看到war包存在
war包用压缩软件打开,是javaweb的标准工程
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
添加<scope>provided</scope>
再次生成war包,解压缩,发现WEB-INF下的lib目录不见了,说明3.1.0的javax.servlet并没有打包进来,我们这样做的原因是tomcat的lib目录自带了servlet-api.jar包
Maven的Scope属性
最后只要把war包复制在tomcat的webapps目录下即可
然后点击bin目录下startup.bat,war包就被自动解压缩了,可以直接在浏览器访问了,但是注意需要添加上URI即文件夹名/web-servlet/
此时出现一个问题,当网页跳转时会把URI给去掉(我们开发时没有使用web-servlet),会导致404,这是需要在tomcat的conf文件夹下对server.xml进行配置
在Host标签
下书写<Context docBase="web-servlet" path="/" />
即将上下文路径设置为默认的’/‘,这里的’/‘是我们开发时在tomcat运行配置界面自己设置的,所以就要和开发时设置的一样