文章目录
Servlet
Servlet的结构体系
Servlet是一个接口;其中有两个子类抽象类实现了该接口分别是GenericServlet
和HttpServlet
GenericServlet:将Servlet接口中的其他方法做了默认空实现;其中只将service()
方法作为抽象
因此;将来定义Servlet类时可以继承GenericServlet;实现Service()方法即可
例如:
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet("/demo1")
public class servlet_demo1 extends GenericServlet { //继承继承GenericServlet
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
}
HttpServlet:对http协议的一种封装;简化操作;比较常用
因此;Servlet类继承HttpSverlet;然后复写都doGet/doPost方法即可
例如:
@WebServlet("/demo3")
public class servlet_demo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost...");
}
}
Servlet相关配置
urlpartten:也就是Servlet访问路径;一个Servlet可以定义多个访问路径;例如下方
@WebServlet("/demo4")
//@WebServlet({"/d4","/dd4","demo4"}) //可以是数组
//@WebServlet("/user/demo4") //多层路径
//@WebServlet("/*") //通配符;优先级最低
//@WebServlet("*.action") //扩展名匹配
HTTP
概念
HTTP指的超文本传输协议(Hyper Text Transfer Protocol);定义了客户端和服务器端通信时发送数据的格式
特点:基于TCP/IP的高级协议;默认端口80;一次请求对应一次响应;每次请求之间相互独立
历史版本:1.0/每一次请求都会建立新的连接;1.1/复用连接
请求消息数据格式
请求行
请求行其实就是地址栏;请求方式有7种其中比较常用的就是get和post
-
GET:请求参数请求行中在url后;请求的url长度有限制的;不太安全
-
POST:请求参数在请求体中;请求的url长度没有限制的;相对安全
请求头
客户端浏览器告诉浏览器一些信息
常见的请求头:
- User-Agent/浏览器告诉服务器我反问你实用的浏览器版本信息
- Referer/告诉浏览器我从哪里来的;作用就是用于防盗链和统计工作
请求空行
用于分割POST请求的请求头和请求体
请求体
封装POST请求信息的请求参数
- 例如
Request
request对象和response对象的原理
- request和respon对象是由服务器创建的;我们来使用它们
- request独享是来获取请求请求信息的;response对象是来设置相应信息的
request对象继承体系结构
SerletRequest(接口)>HttpServletRequest(接口) /它们之间是继承关系
request对象功能
获取请求行数据
方法名 | 说明 |
---|---|
String getMethod() | 获取请求方式 |
String getContextPath() | 获取虚拟目录 |
String getServletPath() | 获取Servlet路径 |
String getQueryString() | 获取get方式请求参数 |
String getRequestURI() | 获取请求统一资源标识符(eg:共和国) |
StringBuffer getRequestURL() | 获取请求统一资源定位符(eg:中华人民共和国) |
String getProtocol() | 获取协议及版本 |
String getRemoteAddr() | 获取客户机的IP地址 |
获取请求头数据
方法名 | 说明 |
---|---|
String getHeader(String name) | 通过请求头的名称获取相对的值 |
Enumeration getHeaderNames() | 获取所有的请求头名称 |
获取请求体数据
要注意的是只有POST方式才有请求体;在请求体中封装了POST请求的请求参数
其他功能
获取请求数据通用方式
不论是get还是post请求方式都可以使用下列方法来获取请求参数
方法名 | 说明 |
---|---|
String getParameter(String name) | 根据参数名称获取参数值 |
String[] getParameterValues(String name) | 根据参数名称获取参数值的数组(eg:复选框) |
Enumeration getParameterNames() | 获取所有参数的参数名称 |
Map<String,String[]> getParameterMap() | 获取所有参数的map集合 |
中文乱码问题:
由于tomcat8已经将get方式乱码问题解决了;但是post方式还是会乱码;所以解决办法就是在获取参数前设置request的编码
request.setCharacterEncoding("utf-8");
综合例子:
import ...
@WebServlet("/demo5")
public class servlet_demo5 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8"); //中文乱码问题;只有post会出现
String username = req.getParameter("username"); //根据名称获取值
System.out.println(username);
String[] hobbies = req.getParameterValues("hobby");
for (String s : //对数组进行遍历
hobbies) {
System.out.println(s);
}
Enumeration<String> parameterNames = req.getParameterNames(); //获取所有请求参数名称
while (parameterNames.hasMoreElements()){
String s = parameterNames.nextElement();
System.out.println(s);
String value = req.getParameter(s); //然后根据名称获取值
System.out.println(value);
System.out.println("-----");
}
Map<String, String[]> parameterMap = req.getParameterMap(); //获取所有参数的map集合
Set<String> strings = parameterMap.keySet(); //获取所有的键
for (String name :
strings) {
System.out.println(name);
String[] values = parameterMap.get(name); //通过键的名称获取值
for (String value :
values) {
System.out.println(value);
}
System.out.println("---");
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp); //由于是通用方式所以执行方法可以一样
}
}
请求转发
请求转发是一种服务器内部的资源跳转方式;如何实现:
- 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
- 然后使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
例子://".demo4为转发路径;req和resp为当前的request对象和response对象"
req.getRequestDispatcher("/demo4").forward(req,resp); //请求转发
特点:浏览器地址栏路径不发生变化;只能转发到当前服务器内部资源中;转发是一次请求
共享数据
域对象:一个有范围的对象;可以在范围内共享数据
方法名 | 说明 |
---|---|
void setAttribute(String name,Object obj) | 存储数据 |
Object getAttitude(String name) | 通过键获取值 |
void removeAttribute(String name) | 通过键移除键值对 |
BeanUtils工具类
BeanUtils类的目的就是简化数据封装;使用BeanUtils类要导入jar包 BeanUtils 提取码:hexh
用于封装JavaBean的;有以下要求:
- 类必须被public修饰
- 必须提供空参的构造构造方法
- 成员变量必须使用private修饰
- 提供公共setter和getter方法
其中用的最多的方法就是
方法名 | 说明 |
---|---|
populate(Object obj , Map map) | 将map集合的键值对信息,封装到对应的JavaBean对象中 |
至于为什么要引入这个工具类;看看以下的代码
现在将获取的的参数将它封装成一个对象;那么一旦参数有成千上百个的时候封装时的代码量是不是变得很多
String username = req.getParameter("username");
String password = req.getParameter("password");
User user = new User();
user.setUsername(username);
user.setPassword(password);
如果用了BeanUtils类的话;只需要获取参数map集合然后创建对象;再然后通过populate()方法就可自动帮你封装对象
Map<String, String[]> parameterMap = req.getParameterMap();
User user = new User();
try {
BeanUtils.populate(user,parameterMap); //注意第一个参数填对象;第二个参数填map集合
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
有了以上的知识;就可以编写一个用户登录的案例了