Java Web学习--Servlet
什么是Servlet?
Servlet含义是服务器端的小程序
Servlet容器是一个web服务器,用来解析浏览器发出的请求,并且调用Java类中的特定的方法.并且将处理完数据响应给浏览器
在整个Web应用中,Servlet主要负责处理请求、协调调度功能。我们可以把Servlet称为Web应用中的『控制器』
Servlet如何运行?
当我们点击浏览器页面上面的一个超链接的时候,由Servlet来处理这个请求.
所以我们要创建一个当我们点击这个超链接的时候或者我们打开某个页面的时候,就会给我们的Servlet去发送请求.
比如在pro07-javaweb-begin这个项目里面当我们输入好数据之后点击提交会交给我们的Servlet组件去处理.同时为了我们点击超链接可以找到对应的Servlet组件,我们需要在配置文件:WEB-INF/web.xml里面配置让其可以正确的找到Servlet组件.
这是前端html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="add" method="post">
名称:<input type="text" name="fname"/><br/>
价格:<input type="text" name="price"/><br/>
库存:<input type="text" name="fcount"/><br/>
备注:<input type="text" name="remark"/><br/>
<input type="submit" value="添加" />
</form>
</body>
</html>
当我们点击添加给add发请求的时候就需要用到xml文件
<!-- 配置Servlet本身 -->
<servlet>
<!-- 全类名太长,给Servlet设置一个别名 -->
<servlet-name>AddServlet</servlet-name>
<!-- 这里是servlets的全类名-->
<servlet-class>com.atguigu.servlets.AddServlet</servlet-class>
</servlet>
<servlet-mapping>
<!-- 这里是刚才起的别名 -->
<servlet-name>AddServlet</servlet-name>
<!-- 这里对应刚才html页面上的add-->
<url-pattern>/add</url-pattern>
</servlet-mapping>
<!--
1. 用户发请求,action=add
2. 项目中,web.xml中找到url-pattern = /add -> 第12行
3. 找第11行的servlet-name = AddServlet
4. 找和servlet-mapping中servlet-name一致的servlet , 找到第7行
5. 找第8行的servlet-class -> com.atguigu.servlets.AddServlet
6. 用户发送的是post请求(method=post) , 因此 tomcat会执行AddServlet中的doPost方法
-->
这样就找到了AddServlet这个类,因为我们表单发送数据的方式为post所以我们必须要重写AddServlet的dopost方法否则会出错.
public class AddServlet extends HttpServlet {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String fname = request.getParameter("fname");
String priceStr = request.getParameter("price");
Integer price = Integer.parseInt(priceStr);
String fcountStr = request.getParameter("fcount");
Integer fcount = Integer.parseInt(fcountStr);
String remark = request.getParameter("remark");
FruitDAO fruitDAO = new FruitDAOImpl();
boolean flag = fruitDAO.addFruit(new Fruit(0 , fname , price , fcount , remark));
System.out.println(flag ? "添加成功!" : "添加失败!");
}
}
上面的代码就是说我们从request请求里面得到了,发送的信息,然后调用FruitDao将数据发送添加进了数据库,如下图所示
但是我们发现发送的中文的在数据库里面是乱码所以我们要在Servlet里面设置编码方式.
下面是post请求方式设置编码
post求方式
request.setCharacterEncoding("UTF-8");
tomcat8开始,设置编码,只需要针对post方式
request.setCharacterEncoding("UTF-8");
注意:
需要注意的是,设置编码(post)这一句代码必须在所有的获取参数动作之前
request.setCharacterEncoding("UTF-8");
Servlet的生命周期
先来看Servlet的接口和相关方法
void init(config) - 初始化方法
void service(request,response) - 服务方法
void destory() - 销毁方法
其中最重要的就是服务方法
HttpServlet 抽象子类中的service方法不是抽象的在这个子类中将service根据请求方式的不同调用不同的do方法.
继承关系为:HttpServlet -> GenericServlet -> Servlet
服务方法: 当有请求过来时,service方法会自动响应(其实是tomcat容器调用的)
所以在HttpServlet中我们会去分析请求的方式:到底是get、post、head还是delete方法
我们必须要实现对应的doxxx方法如果不进行实现的话就会报405错误.所以我们在新建Servlet时,我们才会去考虑请求方法,从而决定重写哪个do方法
Servlet的生命周期
- 从出生到死亡的过程就是生命周期。对应Servlet中的三个方法:init(),service(),destroy()
- 默认情况下:第一次接受请求的时候,Servlet才会进行实例化(调用构造方法)初始化(调用init()方法),然后进行服务.当容器关闭的时候,其中的Servlet实例会调用销毁方法被销毁.也就是说Servlet在第一次接收到请求的时候才开始创建对象.然后在tomcat中一直都是这一个实例来响应.
- Tomcat中,每一个请求会被分配一个线程来处理,所以可以说:Servlet是单实例,多线程方式运行的。
- .Servlet的初始化时机:
- 默认是第一次接收请求时,实例化,初始化. 但是我们仍然可以通过web.xml文件里面的配置来来设置servlet启动的先后顺序,数字越小,启动越靠前,最小值0.
<!-- 配置Servlet启动顺序 -->
<load-on-startup>1</load-on-startup>
名称 | 时机 | 次数 |
---|---|---|
创建对象 | 默认情况:接收到第一次请求 修改启动顺序后:Web应用启动过程中 | 一次 |
初始化操作 | 创建对象之后 | 一次 |
处理请求 | 接收到请求 | 多次 |
销毁操作 | Web应用卸载之前 | 一次 |
Servlet在容器中是:单例的、线程不安全的
单例:所有的请求都是同一个实例去响应
线程不安全:一个线程需要根据这个实例中的某个成员变量值去做逻辑判断。但是在中间某个时机,另一个线程改变了这个成员变量的值,从而导致第一个线程的执行路径发生了变化
- 我们已经知道了servlet是线程不安全的,给我们的启发是: 尽量的不要在servlet中定义成员变量。如果不得不定义成员变量,那么不要去:①不要去修改成员变量的值 ②不要去根据成员变量的值做一些逻辑判断