GenericServlet:
是一个实现了Servlet接口的抽象类,目的是对于使开发人员不用再敲出不用实现的方法
具体实现步骤如下
这属于缺省适配器设计模式
一个类实现一个接口的大多数方法,但是留一些方法不实现定义为抽象方法,留给子类实现
先定义一个GenericServlet抽象类
public abstract class GenericServlet implements Servlet {
@Override
public void init(ServletConfig config) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
//把我们需要自己编写的内容定义为抽象方法,因为抽象方法是要再子类中实现的
//没有定义为抽象方法的方法,在子类中不用实现,直接就继承了
//抽象方法,在子类中必须要实现
@Override
public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException ;
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
在他的实现类中获取servletConfig对象
public class TestServlet extends GenericServlet {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
//获取servletConfig对象,通过getServletConfig对象来获取
ServletConfig servletConfig = this.getServletConfig();
System.out.println(servletConfig)
}
}
以上可以看出每次如果想要调用servletConfig的时候,都需要获取servletConfig对象,所以直接用GenericServlet实现ServletConfig接口,那么就成了servletConfig里的方法成了本地方法,可以直接调用
public abstract class GenericServlet implements Servlet ,ServletConfig{
private ServletConfig config;
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
}
@Override
public ServletConfig getServletConfig() {
return config;
}
//把我们需要自己编写的内容定义为抽象方法,因为抽象方法是要再子类中实现的
//没有定义为抽象方法的方法,在子类中不用实现,直接就继承了
//抽象方法,在子类中必须要实现
@Override
public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException ;
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
//实现ServletConfig里的方法,子类中就可以直接调用ServletConfig内部的方法
@Override
public String getInitParameter(String name) {
return config.getInitParameter(name);
}
@Override
public Enumeration<String> getInitParameterNames() {
return config.getInitParameterNames();
}
@Override
public ServletContext getServletContext() {
return config.getServletContext();
}
@Override
public String getServletName() {
return config.getServletName();
}
}
GenericServlet的Init()方法
1.主要问题发生有ServletConfig空指针异常,如果在子类中重写该方法,容易忘记
super.init(config)
2.在父类中专门定义一个拿个子类重写的init方法,并且在init方法中就直接调用
同时一下也是一种设计模式,称为模板方法设计模式
public void init(ServletConfig config) throws ServletException {
this.config = config;
init();
}
/*
* 为了防止出现config空指针异常的问题,自己定义一个init方法,在系统定义的init的放啊中访问
* */
//专门拿来给子类重写的
public abstract void init();
总结以上,调用系统定义好的GenericServlet,和我们之前的代码是一样的
httpServlet
观察从表单中所提交的信息
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<!-- 表单 -->
<body>
<form action="loginServlet" method = "POST"> <!-- POST提交时,不显示提交的内容 -->
用户名:<input type = "text" name = "username"/><br>
<input type = "submit" value = "登陆"/>
</form>
</body>
</html>
获取请求提交的方式,通过HttpServletRequest (ServletRequest的子类)
//先将其转化为HttpServletRequest
HttpServletRequest request= (HttpServletRequest)req;
//调用方法获取它的提交方式
System.out.println( request.getMethod());
定义一个HttpServlet类,然后我们定义的Servlet再直接继承与HttpServlet,目的在于可以对get,或者post请求进行区分
具体需求:如对于GET请求,可能是非法的,我们需要区别与POST请求处理
有 doGet 和 doPost 两个方法,分别处理不同的请求
POST请求更加的安全,
GenericServlet继承于Servlet, GenericServle特点实现了Servlet,ServletConfig
HttpServlet继承于GenericServlet,HttpServlet的特点是对浏览器提交的请求进行了分析有,doGet方法,doPost方法,两个方法,分别对Get和Post两种请求方式进行处理。
可以观察到HttpServlet的源码,service方法会自动执行,并且会在内部调用doGet方法与doPost方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200327164549463.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,sh
快速定义Servlet
不再是通过类,而是在web项目中直接找到servlet来创建
默认是继承与HttpServlet
HttpServletRequest
HttpServletRequest会将浏览器发生过来的协议存在内部
浏览器发送的HTTP协议如下
我们知道HttpServletRequest是一个接口,所以他具体实现类应该是一个实现了HttpServletRequest接口的类,但是面向抽象编程,不用关心他的具体实现类
一个请求对应一个HttpServletRequest
请求对象是服务器创建的
POST /09-httpServlet/loginServlet HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 9
Cache-Control: max-age=0
Origin: http://localhost:8080
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36
Sec-Fetch-Dest: document
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Referer: http://localhost:8080/09-httpServlet/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: _ga=GA1.1.1634150355.1576843207
*/
username =
请求参数:获取浏览器提交表单里的一些数据,比如username
1.获取指定名称的请求参数
方法:String getParameter(String name);
如果提取的表单里有age这个name,可以获取提交的值
String value = req.getParameter("age");
System.out.println(value);
2.获取提交的所有的name,是一个枚举类型
Enumeration<String> pn = req.getParameterNames();
while(pn.hasMoreElements()) {
String name = pn.nextElement();
String value = req.getParameter(name);
System.out.println("name="+name+"value="+value);
}
3.获取提交的数据,通过Map的形式
getParameterMap(String,String[])
key放的是name
value放的是name对应的值,是一个字符串数组
比如有一种复选框,就是一个name对应多个value值
<input type = "checkbox" name = "hobby" value = "running"/>跑步
<input type = "checkbox" name = "hobby" value = "swimming"/>游泳
<input type = "checkbox" name = "hobby" value = "reading"/>阅读
复选框的样式为
如果全部勾选并提交的话,会得到hobby=running&hobby=swimming&hobby=reading
这样一个name会有3个value值
//在servlet中进行读取
String[] strs = req.getParameterValues("hobby");
for(String str:strs) {
System.out.println(str);
}
以Map的方式获取name和value
/*
* 获取存放请求的Map
* */
Map<String, String[]> pm = req.getParameterMap();
Set<String> keySet = pm.keySet();
for(String s1:keySet) {
System.out.println("name = "+s1);
String[] pv = req.getParameterValues(s1);
for(String str:pv) {
System.out.println("value = "+str);
}
}
总结:
1.请求参数是存放在Map中的
2.这个Map的key为请求参数的名称,为String类型
这个Map的value为请求参数的所有值,为String[]类型
3.使用最多的是getParameter()方法,其等价于getParameterValues()[0]
Request中的域属性
作用:主要是用于和其他servlet共享request对象的数据,实现了跨servlet通信
1.在request中也存在域属性空间,用于存放有名称的数据。该数据只有在当前Request请求中进行访问
和域属性相关的方法
在ServletRequest中的方法
setAttribute()
removeAttribute()
getAttribute()
getAttributeNames()
将域属性传到另外一个Servlet(/NewServlet)中执行
request.getRequestDispatcher("/NewServlet").forward(request,resp);
在另外一个Servlet中可以通过getAttribute获得域属性
从请求中获取服务器的相关信息的一些需要掌握的方法
getRequestURL():获取请求的URL
getRequestURI():获取请求的URI
getContextPath:获取当前Web应用的根路径
getRemoteAddr():获取客户端IP
getServletPath():返回的是在web.xml中定义的精确匹配路径
getPathInfo():如果有使用同配符号’*’ ,代表的是通配符里填写的路径