一、Servlet 简介
Java Servlet 是运行在 Web 服务器(tomcat)或应用服务器上的程序,它可以接收来自 Web 浏览器或其他 HTTP 客户端的请求,并进行结果的响应。
使用 Servlet,可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。
记住几点:
1.servlet是一段Java程序,可以用于接收浏览器发来的请求和给浏览器作出响应。
2.servlet是一套标准和规范,需要按照官方要求进行代码开发。
3.编写servlet需要导入 servlet-api.jar
包
二、使用idea编写一个servlet
2.1 新建JavaWeb项目
① 新建一个java工程,在工程上右击选择 add framework support… 生成web项目目录结构
勾选 web application ,并创建web.xml
最终构建的项目结构如下:
项目名
|-- src目录
|-- 包
|-- 类
|-- web目录
|-- 静态资源(html,css,js,图片等,可被浏览器直接访问)
|-- WEB-INF(WEB-INF目录下的资源受保护的,无法被浏览器直接访问)
|-- lib (lib目录存项目放所需的jar包)
|-- web.xml
这里要注意,这是编写代码时的项目结构,项目编写完毕是需要部署到tomcat运行中运行的,部署到tomcat时结构会变化为:
项目名
|-- 静态资源(html,css,js,图片等,可被浏览器直接访问)
|-- WEB-INF(WEB-INF目录下的资源受保护的,无法被浏览器直接访问)
|-- classes (classes目录存放编译后的class文件)
|-- lib (lib目录存项目放所需的jar包)
|-- web.xml (web项目的核心配置文件)
2.2 导入servlet的包
从tomcat的lib目录中找到 servlet 的jar包,复制到项目的lib目录中。
在包上右击选择 add as library ,并选择 level为:project library,设置后如果jar可以展开,就说明添加成功。
2.3 编写servlet
/**
* 编写servlet的流程
* 1.继承 javax.servlet.http.HttpServlet
* 2.重写 service 方法
* 3.在web.xml中配置servlet
*/
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet执行了...");
}
// 还可以重写 doGet 或者 doPost方法
// 区别是:doGet方法只能处理get请求,doPost方法只能处理post请求,service方法都可以处理
}
2.4 配置servlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--配置servlet-->
<servlet>
<!--为servlet取别名-->
<servlet-name>helloServlet</servlet-name>
<!--配置servlet的全路径-->
<servlet-class>cn.msk.HelloServlet</servlet-class>
</servlet>
<!--配置请求映射关系-->
<servlet-mapping>
<!--使用servlet别名-->
<servlet-name>helloServlet</servlet-name>
<!--配置url路径-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
2.5 servlet路径写法
<!-- 1.完全匹配,只会配合 /hello 请求 -->
<url-pattern>/hello</url-pattern>
<!-- 2.模糊匹配, /* 表示匹配所有请求 -->
<url-pattern>/*</url-pattern>
<!-- /system/* 表示匹配以 /system开头的请求 -->
<url-pattern>/system/*</url-pattern>
<!-- 3.后缀匹配, *.do 匹配以do结尾的请求 -->
<url-pattern>*do</url-pattern> :
三、部署项目和测试
3.1 为idea配置tomcat环境
① 选择 add configuration…
② 点击 + 选择Tomcat Server中的 Local
一定一定注意是 Tomcat Server
③ 点击 configure… 关联tomcat
设置tomcat的家目录
④ 部署项目到tomcat中,点击 deployment -> +号 -> Artifact…
3.2 启动测试
① 启动tomcat
② 查看日志,说明启动成功,占用 8080 端口
③ 测试我们写的 HelloServlet:http://localhost:8080/hello
四、servlet的执行流程
五、servlet的生命周期
Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:
- Servlet 初始化后调用 init () 方法。
- Servlet 调用 service() 方法来处理客户端的请求。
- Servlet 销毁前调用 destroy() 方法。
为servlet添加相关方法进行测试:
public class HelloServlet extends HttpServlet {
//被访问时提供服务的方法
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet执行了...");
}
//构造方法
public HelloServlet(){
System.out.println("HelloServlet实例化");
}
//初始化方法
@Override
public void init() throws ServletException {
System.out.println("HelloServlet初始化");
}
//销毁方法
@Override
public void destroy() {
System.out.println("HelloServlet销毁了");
}
}
测试结论:
- 默认情况下,servlet是在第一次被访问时实例化并初始化,调用时提供服务,tomcat停止时销毁。
- 设置了
<load-on-startup>1</load-on-startup>
servlet就会在tomcat启动时就实例化并初始化,调用时提供服务,tomcat停止时销毁。该值只要大于0即可,值越小优先级越高。 - 相同点:实例化和初始化方法都只走一次,服务方法(service方法)调用就会走,销毁方法只走一次。
六、请求对象 HttpServletRequest
6.1 常用方法
//1.需要重点掌握的方法
(1) String getParameter(String name):根据参数名称,获取对应参数的值;
(2) void req.setCharacterEncoding("UTF-8"):为post请求设置编码,防止中文乱码
//2.其他需要了解的方法
(1) String getContextPath():获取上下文路径,<Context path="上下文" ../>;
(2) String getHeader(String headName):根据指定的请求头获取对应的请求头的值;
(3) String getRequestURI():返回当期请求的资源路径URI(上下文路径/资源名);
(4) StringBuffer getRequestURL():返回浏览器请求地址URL;
(5) String getRemoteAddr():返回请求服务器的客户端的IP;
(6) String getServletPath():返回请求,<url-pattern>中的值;
(7) String[] getParameterValues(String name):根据参数名称,获取该参数的多个值;
(8) Map<String,String[]> getParameterMap():返回请求参数组成的Map集合;
(9) void req.setCharacterEncoding("UTF-8"):能够正确获取post请求的中文参数而不出现乱码;
(10) String getProtocol()):获取协议版本HTTP/1.1
(11) String getMethod()):获取请求方式(GET or POST)
(12) int getServerPort():获取端口号
6.2 请求乱码处理
在获取请求参数时,中文会乱码,处理办法如下:
1.post的处理方式:request.setCharacterEncoding("UTF-8")
2.get的处理方式:tomcat8及以上无需处理,低版本tomcat需要在 server.xml中的Connector标签中进行设置。
七、响应对象 HttpServletResponse
//设置响应内容编码方式
response.setCharacterEncoding("UTF-8");
//设置响应内容的类型和编码(建议使用)
response.setContentType("text/html;charset=UTF-8");
//获取打印输出流
PrintWriter writer = response.getWriter();
//获取字节输出流
OutputStream outputStream = response.getOutputStream();
八、转发和重定向
8.1 转发-forward
请求转发是较为常用的一种跳转web资源的方式,他是在服务器内部进行的,整个过程浏览器是不知晓的,同时请求转发使用的是同一个request对象,所有他还可以进行参数的传递。
转发的语法:
request.getRequestDispatcher("跳转地址").forward(request,response);
1.请求转发可以访问WEB-INF下受保护的资源
request.getRequestDispatcher("/WEB-INF/xx").forward(request,response);
2.请求转发不能访问外部资源(不能跨域访问)
//跳转是失败的
request.getRequestDispatcher("http://www.baidu.com").forward(request,response);
3.请求转发可以使用request对象传递参数(使用的是同一个请求对象)
//Servlet1
request.setAttribute("name","tom");
request.getRequestDispatcher("/servlet2").forward(request,response);
Servlet2
String name = request.getAttribute("name"); //可以获取到tom
4.请求转发,浏览器地址栏不会发生变化
8.2 重定向-redirect
重定向的语法:
response.sendRedirect("跳转地址");
1.重定向是两次请求,所以会产生新的request对象,无法使用request对象传递参数
2.地址栏会变化
3.重定向的状态码是302
4.可以跳转外部资源(允许跨域访问)
5.无法访问WEB-INF下受保护的资源
九、cookie和session
由于http协议是一种无状态的协议(客户端和服务端互相不认识),也就是说只要客户端发来请求,地址是对的,服务端就会接收。但是这是有问题的,因为有些请求必须要用户登录才能访问,http的无状态特性导致它无法记录用户登录状态,因此,就有了cookie和session来进行补齐这个短板。
9.1 cookie
cookie存储在客户端,允许存储key-value形式的键值对,但是value只能是字符串。
cookie一般存储大小为4096字节。而且对于一个站点存储的cookie个数也有限制。
1.cookie原理
类似生活中去理发店办卡,第一次去办好卡以后自己带着卡离开,下一次去的时候带着卡去就可以了,店家看到卡就知道是自己的会员。
2.创建cookie相关方法
//方法1)创建cookie
Cookie cookie = new Cookie("key", "value");
//方法2)设置cookie过期时间,单位:秒
//正数:在指定时间后过期
//0 :立即删除该cookie
//负数:会话级别的cookie,关闭浏览器时失效
cookie.setMaxAge(60*60*24*7); //7天有效
//方法3)设置cookie的存储路径, 如果设置为 /cookie/xx ,那么/cookie开头的才能获取
cookie.setPath("/"); //建议设置为 / 方便获取
//方法4)将cookie回传给客户端保存
response.addCookie(cookie);
设置了cookie并回传客户端保存,就可以在响应报文中看到cookie的信息
3.获取cookie相关方法
一旦浏览器中保存了cookie,当浏览器再次发送请求时,cookie会自动发送给服务器。
//获取cookie
Cookie[] cookies = request.getCookies();
//遍历cookie获取key和value
for (Cookie c:cookies){
String name = c.getName(); //获取cookie的key
String value = c.getValue();//获取cookie的value
}
9.2 session 会话对象
session存储在服务器端,允许key-value的键值对,value是Object类型。
session对于存储个数和大小无限制。
1.session相关方法
//获取session
HttpSession session = request.getSession();
//向session中设置值
session.setAttribute("username","tom");
//从session中获取值
String username = (String)session.getAttribute("username");
//设置session过期时间,单位:秒, 默认过期时间为30分钟
session.setMaxInactiveInterval(60*30);
//销毁session
session.invalidate();
过期时间也可以在tomcat的配置文件中进行修改:tomcat/conf/web.xml
<session-config>
<session-timeout>30</session-timeout>
</session-config>
2.session的原理
由此可以看出,session的运行需要cookie的协助才能完成。
利用session我们可以实现用户登录信息的保存。大致实现思路是:用户登录后将信息保存在session中,当下次请求过来时,尝试从session中获取用户信息,能获取到表示已经登录,没有获取到表示用户没有登录过。
十、Filter过滤器
10.1 介绍
- Filter被称为过滤器,是Servlet2.3新增的一个特性,Filter在Servlet之前执行,因此开发人员可以通过Filter技术,能够实现对所有Web资源的管理,如实现权限访问控制、过滤敏感词汇等操作。
- Filter 过滤器它是 JavaEE 的规范,也就是一个接口。
10.2 编写Filter
编写Filter:
/**
* 1.实现Filter接口,重写相关方法
* 2.在web.xml中配置Filter
*/
public class MyFilter implements Filter {
//构造器: tomcat启动就执行,只走一次
public MyFilter(){
System.out.println();
}
//初始化方法:tomcat启动就执行,只走一次
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("MyFilter初始化了");
}
//doFilter方法:请求被调用时执行
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
System.out.println("MyFilter执行了");
//执行doFilter方法,请求才会继续向后执行,否则走到filter这儿就不会向后执行了
filterChain.doFilter(request,response);
}
//销毁方法:tomcat关闭时执行
@Override
public void destroy() {
System.out.println("MyFilter销毁了");
}
}
在web.xml 配置过滤器:
<filter>
<!--别名-->
<filter-name>myFiler</filter-name>
<!--过滤器的全限定名-->
<filter-class>cn.msk.filer.MyFilter</filter-class>
</filter>
<filter-mapping>
<!--别名-->
<filter-name>myFiler</filter-name>
<!--匹配所有路径-->
<url-pattern>/*</url-pattern>
</filter-mapping>