今日内容:
1. Servlet
2. HTTP协议
3. Request
1. Servlet:
- 概念
- 步骤
- 执行原理
- 生命周期
- Servlet3.0 注解配置
- Servlet的体系结构
- 出现的意义:++由于我们一般只用service方法,但是每次都要重写其他4个方法。++
//从上到下爷孙三人Servlet -- 接口|GenericServlet -- 抽象类|HttpServlet -- 抽象类
- GenericServlet【开发时不用这个】:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象
- ++将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可++
@WebServlet("/demo2")public class ServletDemo2 extends GenericServlet {@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("demo2...");}//想重写那个方法自己手动添加即可(输入init)}
- HttpServlet【开发时用这个】:对http协议的一种封装,简化操作
- HttpServlet原理(对http协议的一种封装,简化操作)
- 上面是原本要写的代码(多)
- 下面就是复写两个方法就可以了
- 使用步骤
- 定义类继承HttpServlet
- 复写(重写)doGet/doPost方法
- 演示:(注:通过浏览器访问时get请求)
@WebServlet("/demo3")public class ServletDemo3 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("doGet...");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("doPost");}}
- Servlet相关配置
- urlpartten:Servlet访问路径
- 一个Servlet可以定义多个访问路径 :
@WebServlet({"/d4","/dd4","/ddd4"})
- 路径定义规则:
- /xxx:路径匹配
- /xxx/xxx:多层路径,目录结构(作为了解)
- *.do:扩展名匹配(作为了解,前面不能加/)
//第一种:@WebServlet("/d4")//第二种:表示三个都可以访问@WebServlet({"/d4","/dd4","/ddd4"})//第三种:表示有层级关系,都写才可以@WebServlet({"/user/d4")//第四种:表示user后面跟什么都可以被访问(访问权限最低)@WebServlet({"/user/*")//第五种:必须要加.do,且前面不能加/@WebServlet({"*.do")
2. HTTP【重点】:
- 概念:Hyper Text Transfer Protocol 超文本传输协议
- 传输协议:++定义了,客户端和服务器端通信时,发送数据的格式++(格式如果不统一则没办法进行解析动作)
- 特点【知道】:
- ++基于TCP/IP的高级协议++
- 简述TCP和UDP
- TCP:安全的,通过三次握手来确保双方都连接通畅,传输速度慢,不会丢失数据
- UDP:不是很安全,且传输过程有可能丢失数据(优点:快)–>常用到语音的发送
- ++默认端口号++:80
- ++基于请求/响应模型的++:一次请求对应一次响应
- ++无状态的++:每次请求之间相互独立,不能交互数据
- 历史版本【了解】:
- 1.0:每一次请求响应都会建立新的连接
- 1.1:复用连接
- 简述:就是请求一个连接后就会等一会如果有新的请求,就会复用刚才的链接,否则就释放链接
- 请求消息数据格式
- 页面中
f12–>Network–>点入访问页面–>Headers

- 请求行
- 请求头:++客户端浏览器告诉服务器一些信息++
- 格式:
请求头名称: 请求头值
- 常见的请求头:
- User-Agent:++浏览器告诉服务器,我访问你使用的浏览器版本信息++
- 不同浏览器可以在服务器端获取该请求头的信息,解决浏览器的兼容性问题

- Referer:http://localhost/login.html
- 告诉服务器,我(当前请求)从哪里来?
- 作用:
- 防盗链:

- 统计工作:

- 请求空行
- 请求体(正文):(GET中就没有)
- 字符串格式:
//请求行和请求头一起的//请求行(请求方式 请求url 请求协议/版本)POST /login.html HTTP/1.1//请求头Host: localhost //请求主机User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 //告诉服务器,作为浏览器可以响应什么样的信息格式Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2//告诉服务器,作为浏览器可以支持的语言环境Accept-Encoding: gzip, deflate//告诉服务器,作为浏览器可以压缩的格式Referer: http://localhost/login.htmlConnection: keep-alive//连接可以被复用Upgrade-Insecure-Requests: 1//关于升级的//请求空行//请求体username=zhangsan
- 响应消息数据格式
3. Request:
- request对象和response对象的原理
- 下图是重点【掌握】

- request和response对象是由服务器创建的。我们来使用它们
- request对象是来获取请求消息,response对象是来设置响应消息(比如通过获取的消息能)
- request对象继承体系结构【了解】:
ServletRequest-->接口(实现Servlet接口时候重写的service方法中的对象)| HttpServletRequest接口继承ServletRequest接口HttpServletRequest-->接口(继承HttpServlet类时候重写的doGet方法中的对象)| RequestFacade类实现了HttpServletRequest接口RequestFacade 类(tomcat编写的,包路径:org.apache.catalina.connector.RequestFacade)
- ServletRequeset对象【了解】
@WebServlet("/demo1")public class ServletDemo1 implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}//这里的参数类型@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("demo1...");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}}
- HttpServletRequest对象【掌握】
@WebServlet({"/d4", "/dd4", "/ddd4"})public class ServletDemo4 extends HttpServlet {//这里的参数类型@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("demo4");}}
- request功能【重点】:
- 获取请求消息数据
- 获取请求行数据
- 格式:
GET /day14/demo1?name=zhangsan HTTP/1.1
- 方法:(API中查ServletRequest)
- 获取请求方式 :GET
- (*)获取虚拟目录【重点掌握】:/day14
- 获取Servlet路径: /demo1
- 获取get方式请求参数:name=zhangsan
- (*)获取请求URI【重点掌握】:/day14/demo1
- String getRequestURI()
- StringBuffer getRequestURL()
- http://localhost/day14/demo1
- URI和URL的区别:
- URI:统一资源标识符 :
- URL:统一资源定位符 :
- http://localhost:8080/day14/requestDemo1 中华人民共和国
- 获取协议及版本:HTTP/1.1
- 获取客户机的IP地址:
- 案例:
/*** 演示request对象获取请求行数据*/@WebServlet("/requestDemo1")public class RequestDemo1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1. 获取==请求方式== :GETString method = req.getMethod();System.out.println(method);//2. (*)获取==虚拟目录【重点掌握】==:/day14String contextPath = req.getContextPath();System.out.println(contextPath);//3. 获取==Servlet路径==: /requestDemo1String servletPath = req.getServletPath();System.out.println(servletPath);//4. 获取==get方式请求参数==:name=zhangsanString queryString = req.getQueryString();System.out.println(queryString);//5. (*)获取==请求URI【重点掌握】==:/day14/requestDemo1String requestURI = req.getRequestURI();StringBuffer requestURL = req.getRequestURL();System.out.println(requestURI);System.out.println(requestURL);//6. 获取==协议及版本==:HTTP/1.1String protocol = req.getProtocol();System.out.println(protocol);//7. 获取==客户机的IP地址==:String remoteAddr = req.getRemoteAddr();System.out.println(remoteAddr);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}}//结果:GET/day14/requestDemo1name=zhangsan&age=2/day14/requestDemo1http://localhost:8080/day14/requestDemo1HTTP/1.10:0:0:0:0:0:0:1
- 获取请求头数据
- 方法:
- (*)String getHeader【重点掌握】(++String name++):通过请求头的名称获取请求头的值
- Enumeration getHeaderNames():获取所有的请求头名称
- 演示:
@WebServlet("/requestDemo2")public class RequestDemo2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//演示获取请求头数据//1.获取所有请求头名称Enumeration headerNames = req.getHeaderNames();//2.遍历while(headerNames.hasMoreElements()){String name = headerNames.nextElement(); //获取到请求头名称//根据名称获取请求头的值String value = req.getHeader(name);System.out.println(name + "----" + value);}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}}//结果:host----localhost:8080connection----keep-alivecache-control----max-age=0upgrade-insecure-requests----1user-agent----Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36accept----text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9sec-fetch-site----cross-sitesec-fetch-mode----navigatesec-fetch-user----?1sec-fetch-dest----documentaccept-encoding----gzip, deflate, braccept-language----zh-CN,zh;q=0.9cookie----JSESSIONID=9EA5C1B4199A1B36420D6F24517E9F8A; JSESSIONID=7AF53FE1F3D0702578BA3E3227A5339B
- 案例1:获取user-agent请求头数据,来解决浏览器的兼容性问题
//案例:获取user-agent请求头数据,来解决浏览器的兼容性问题String agent = req.getHeader("user-agent");if(agent.contains("Chrome")){//表示使用的谷歌浏览器System.out.println("谷歌来了。。。");}else if(agent.contains("Firefox")){//表示使用火狐浏览器System.out.println("火狐来了。。。");}
- 案例2:获取referer请求头数据,来解决防盗链问题和统计工作问题
- referer是告诉服务器,我(当前请求)从哪里来
- 不是从别的超链接点击过来的就为null,因为自己请求自己(需要别的网址访问该url)
String referer = req.getHeader("referer"); //referer是告诉服务器,我(当前请求)从哪里来//从login页面中获取到的http://localhost:8080/day14/login.htmlSystem.out.println(referer); //不是从别的超链接点击过来的就为null,因为自己请求自己(需要别的网址访问该url)//防盗链if(referer != null){ //表示不是自己请求自己if(referer.contains("/day14")){//正常访问://System.out.println("播放电影");//显示到服务器端的方式//这里是response方式//先设置一下可以中文显示resp.setContentType("text/html;charset=utf-8");//再显示到页面上resp.getWriter().write("播放电影...");}else {//盗链//System.out.println("请来正规网址观看电影");//这里是response方式//先设置一下可以中文显示resp.setContentType("text/html;charset=utf-8");//再显示到页面上resp.getWriter().write("请来正规网址观看电影...");}}//本项目访问该的网站demo4...//另一个项目访问该网站demo4...//结果:http://localhost:8080/day14/login.html播放电影http://localhost/index.html请来正规网址观看电影
- 同时启动两个tomcat操作【重点】

- 获取请求体数据:
- 请求体:++只有POST请求方式,才有请求体++,在请求体中封装了POST请求的请求参数
- 步骤:
- 获取流对象(++通过request获取的,不用关闭++)
- 再从流对象中拿数据
- BufferedReader getReader():获取字符输入流,++只能操作字符数据++
- 普通表单提交的都是字符的
- 例子:获取到post请求头数据
@WebServlet("/requestDemo5")
public class RequestDemo5 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取请求消息体-->请求参数//1.获取字符流BufferedReader br = req.getReader();//2.读取数据String line = null;while((line = br.readLine()) != null){System.out.println(line);}}
}
- ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
- 其他功能【都要掌握】:
- ++获取请求参数通用方式++:++不论get还是post请求方式都可以使用下列方法来获取请求参数++
- String getParameter【常用与单选框】(String name):根据参数名称获取参数值
- String[] getParameterValues【常用与复选框】(String name):根据参数名称获取参数值的数组
- Enumeration getParameterNames():获取所有请求的参数名称
- Map getParameterMap【常用】():获取所有参数的map集合
- ++就是来解决了复选框的时候只能获取一个的问题++
- 综合例子:
- 访问页面:

- 代码:
@WebServlet("/requestDemo6")public class RequestDemo6 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//get 请求参数//根据参数名称获取参数值String username = req.getParameter("username");/*System.out.println("get");System.out.println(username);*///结果:getadmin//根据参数名称获取参数值的数组String[] hobbys = req.getParameterValues("hobby");/*for (String hobby : hobbys) {System.out.println(hobby);}*///结果:gamestudy//获取所有请求的参数名称Enumeration parameterNames = req.getParameterNames();/*while(parameterNames.hasMoreElements()){String name = parameterNames.nextElement();System.out.println(name);String parameter = req.getParameter(name);System.out.println(parameter);System.out.println("-----");}*///结果:usernameadmin------------password123465------------hobbygame------------//获取所有参数的map集合Map parameterMap = req.getParameterMap();//遍历Map(使用keySet)/*Set keySet = parameterMap.keySet(); //获取到键for (String key : keySet) {//通过键获取值String[] values = parameterMap.get(key);System.out.println(key);for (String value : values) {System.out.println(value);}System.out.println("------------");}*///结果:usernameadmin------------password123465------------hobbygamestudy------------}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//post 请求参数//根据参数名称获取参数值//因为get,post都可以获取到,所以doPost访问doGet就可以了this.doGet(req, resp);}}
- ++中文乱码问题++:
- get方式(通过url获取值):tomcat 8 已经将get方式乱码问题解决了
- post方式(通过流获取值):会乱码
- 解决:在获取参数前,设置request的编码request.setCharacterEncoding(“utf-8”);
- 案例:
@WebServlet("/requestDemo7")public class RequestDemo7 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1.设置流的编码格式(字符集)req.setCharacterEncoding("utf-8");//获取请求参数usernameString username = req.getParameter("username");System.out.println(username);}}
- ++请求转发++:一种在服务器内部的资源跳转方式
- 步骤:
- 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
- 使用RequestDispatcher对象中forward方法来进行转发:forward(ServletRequest request, ServletResponse response)
- 特点【面试题】:
- ++浏览器地址栏路径不发生变化++
- 只能转发到当前服务器内部资源中。
- 转发只是一次请求
- 案例:将requestDemo8请求转发到requestDemo9中
//RequestDemo8的doPost中System.out.println("demo8被访问了");//请求转发到requestDemo9中req.getRequestDispatcher("/requestDemo9").forward(req, resp);//RequestDemo9的doPost中System.out.println("demo9被访问了");//结果:demo8被访问了demo9被访问了
- 共享数据:
- 域对象:一个有作用范围的对象,可以在范围内共享数据
- request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
- 方法:
- void setAttribute(String name,Object obj):存储数据
- Object getAttribute(String name):通过键获取值
- void removeAttribute(String name):通过键移除键值对
- 演示:
//RequestDemo8的doPost中System.out.println("demo8被访问了");//在请求转发之前,存储数据req.setAttribute("msg", "hello");//请求转发到requestDemo9中req.getRequestDispatcher("/requestDemo9").forward(req, resp);//RequestDemo9的doPost中//获取数据Object msg = req.getAttribute("msg");System.out.println(msg);System.out.println("demo9被访问了");//结果:demo8被访问了hellodemo9被访问了
- 获取ServletContext【现在了解,后面详细学】:
- ServletContext getServletContext()
4. 案例:用户登录【综合掌握上面的方法】
- 用户登录案例需求:
- 编写login.html登录页面
- username & password 两个输入框
- 使用Druid数据库连接池技术,操作mysql,day14数据库中user表
- 使用JdbcTemplate技术封装JDBC
- 登录成功跳转到SuccessServlet展示:登录成功!用户名,欢迎您
- 登录失败跳转到FailServlet展示:登录失败,用户名或密码错误
- 分析
- 开发步骤
- 创建项目,导入html页面,配置文件,jar包
- 创建数据库环境
CREATE DATABASE day14;USE day14;CREATE TABLE user(id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(32) UNIQUE NOT NULL,password VARCHAR(32) NOT NULL);
- 创建包cn.itcast.domain,创建类User
package cn.itcast.domain;/*** 用户的实体类*/public class User {private int id;private String username;private String password;public int getId() {return id;}public void setId(int id) {this.id = id;}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;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +'}';}}
- 创建包cn.itcast.util,编写工具类JDBCUtils
package cn.itcast.util;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;import javax.xml.crypto.Data;import java.io.IOException;import java.io.InputStream;import java.sql.Connection;import java.sql.SQLException;import java.util.Properties;/*** JDBC工具类 使用Durid连接池*/public class JDBCUtils {private static DataSource ds ;static {try {//1.加载配置文件Properties pro = new Properties();//使用ClassLoader加载配置文件,获取字节输入流InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");pro.load(is);//2.初始化连接池对象ds = DruidDataSourceFactory.createDataSource(pro);} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}/*** 获取连接池对象*/public static DataSource getDataSource(){return ds;}/*** 获取连接Connection对象*/public static Connection getConnection() throws SQLException {return ds.getConnection();}}
- 创建包cn.itcast.dao,创建类UserDao,提供login方法
package cn.itcast.dao;import cn.itcast.domain.User;import cn.itcast.util.JDBCUtils;import org.springframework.dao.DataAccessException;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate;/*** 操作数据库中User表的类*/public class UserDao {//声明JDBCTemplate对象共用private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());/*** 登录方法* @param loginUser 只有用户名和密码* @return user包含用户全部数据,没有查询到,返回null*/public User login(User loginUser){try {//1.编写sqlString sql = "select * from user where username = ? and password = ?";//2.调用query方法User user = template.queryForObject(sql,new BeanPropertyRowMapper(User.class),loginUser.getUsername(), loginUser.getPassword());return user;} catch (DataAccessException e) {e.printStackTrace();//记录日志return null;}}}
- 编写cn.itcast.web.servlet.LoginServlet类
package cn.itcast.web.servlet;import cn.itcast.dao.UserDao;import cn.itcast.domain.User;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("/loginServlet")public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1.设置编码req.setCharacterEncoding("utf-8");//2.获取请求参数String username = req.getParameter("username");String password = req.getParameter("password");//3.封装user对象User loginUser = new User();loginUser.setUsername(username);loginUser.setPassword(password);//4.调用UserDao的login方法UserDao dao = new UserDao();User user = dao.login(loginUser);//5.判断userif(user == null){//登录失败req.getRequestDispatcher("/failServlet").forward(req,resp);}else{//登录成功//存储数据req.setAttribute("user",user);//转发req.getRequestDispatcher("/successServlet").forward(req,resp);}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doGet(req,resp);}}
- 编写FailServlet和SuccessServlet类
@WebServlet("/successServlet")public class SuccessServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取request域中共享的user对象User user = (User) request.getAttribute("user");if(user != null){//给页面写一句话//设置编码response.setContentType("text/html;charset=utf-8");//输出response.getWriter().write("登录成功!"+user.getUsername()+",欢迎您");}} @WebServlet("/failServlet")public class FailServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//给页面写一句话//设置编码response.setContentType("text/html;charset=utf-8");//输出response.getWriter().write("登录失败,用户名或密码错误");}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request,response);}}
- login.html中form表单的action路径的写法
- BeanUtils工具类,简化数据封装(导入:commons-beanutils-1.8.0.jar)
- JavaBean的基本知识:标准的Java类
- 要求:
- 类必须被public修饰
- 必须提供空参的构造器
- 成员变量必须使用private修饰
- 提供公共setter和getter方法
- 功能:封装数据
- 概念:
- BeanUtils工具类中的方法:
- setProperty()
- getProperty()
- populate(Object obj , Map map):++将map集合的键值对信息,封装到对应的JavaBean对象中++
- 使用案例:
- import org.apache.commons.beanutils.BeanUtils;
//原来:LoginServlet类中//2.获取请求参数String username = req.getParameter("username");String password = req.getParameter("password");//3.封装user对象User loginUser = new User();loginUser.setUsername(username);loginUser.setPassword(password);//替换为://BeanUtils工具类,简化数据封装//2. 获取所有请求参数Map map = req.getParameterMap();//3. 创建User对象User loginUser = new User();//3.2 使用BeanUtils进行封装try {BeanUtils.populate(loginUser, map);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!