Servlet开发
Posted yumiaoxa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Servlet开发相关的知识,希望对你有一定的参考价值。
自MVC规范出现后,Servlet的责任开始明确下来,仅仅作为控制器使用,不再需要生成页面标签,也不再做为视图层角色使用。servlet通常被称为服务器端小程序,是运行在服务器端的程序 。用于处理用户的请求及响应。
一. Servlet 介绍
Servlet是特殊的Java类,这个Java类必须继承HTTPServlet,每个servlet可以响应用户的请求。Servlet提供不同的方法用于相应用户的请求
- doGet():用于相应客户端的get请求
- doPost():用于响应客户端的Post请求
- doPut():用于相应客户端的put请求
- doDelete():用于相应客户端的delete请求
事实上,客户端请求通常只有get和post两种,servlet为了响应这两种请求,必须重写doPost()和doGet()两个方法。
大部分时候,servlet对于所有请求的响应都是都是完全一样的。因此可以采用重写一个方法来代替上面四个方法:只需要重写service方法即可响应客户端所有请求。
另外,HTTPServlet还包括另外两个方法
- init(ServletConfig config):创建servlet实例时,使用该方法初始化Servlet资源。
- destroy():销毁Servlet实例时,自动调用该方法回收资源
通常无需重写这两个方法。除非需要初始化Servlet时,完成某些资源初始化的方法,才考虑重写init()方法。如果需要在销毁Servlet之前,先完成某些资源的回收,比如关闭数据库连接等,才需要重写destroy方法。
Servlet与JSP的区别在于:
- Servlet没有内置对象,原JSP中的内置对象必须由程序显示创建
- 对于静态的html标签,servlet必须使用页面输出流逐行输出
二. Servlet 配置
编辑好的servlet源文件并不能响应用户请求,还必须将其编译成class文件 。将编译后的class文件放在WEB-INF/classes路径下,如果servlet有包,则还应该将class文件放在对应的包路径下。
为了让Servlet响应用户请求,还必须将Servlet配置在web应用中。配置Servlet时,需要修改web.xml文件》
从servlet3.0开始,配置servlet的两种方式
- 在servlet类中使用@webServlet注解进行配置
- 通过在web.xml文件中进行配置
使用注解@webServlet配置Servlet时,常用的属性有
属性 | 是否必须 | 说明 |
asynsSupported | 否 | 指定该Servlet是否支持异步操作模式 |
displayName | 否 |
指定该Servlet的显示名 |
initParam | 否 | 用于为该Servlet配置参数 |
loadOnStartup | 否 | 用于将该servlet配置成load-on-startup 的 Servlet |
name | 否 | 指定该servlet的名字 |
urlPatterns/value | 否 | 都指定servlet处理的URL |
如果打算使用注解来配置Servlet,有两点需要指出:
- 不要在web.xml文件的根元素(<web-app.../>)中指定metadata-complete="true".
- 不要在web.xml文件中配置该servlet。
如果打算使用web.xml文件来配置该Servlet,则需要配置如下两个部分。
- 配置Servlet的名字:对应web.xml文件中的<servlet/>元素
- 配置servlet的URL,对应web.xml文件中的<servlet-mapping/>元素。这一步是可选的。但如果没有为Servlet配置URL,则该servlet不能响应该用户请求。
三. JSP/Servlet 的生命周期
当Servlet在容器中运行时,其实例的创建及销毁等都不是程序员决定的,而是由web容器进行控制的的
创建servlet实例有两个时机
- 客户端第一次请求某个Servlet时,系统创建该Servlet的实例:大部分的Servlet都是这种Servlet
- Web应用启动时立即创建Servlet实例,即load-on-startup Servlet.
每个Servlet运行都遵循如下生命周期
- 创建Servlet实例
- Web容器调用Servlet的init方法,对Servlet进行初始化。
- Servlet初始化后,将一直保存在容器中,用于响应客户端的请求,调用doGet()或者doPost()方法处理并响应请求,或者统一使用service方法
- web容器决定销毁Servlet时,先调用Servlet的destroy()方法,通常在关闭Web应用时销毁Servlet。
四. load-on-startup Servlet
应用启动时就创建的Servlet通常是用于某些后台服务的Servlet,或者拦截很多请求的Servlet,这种Servlet通常作为应用的基础Servlet使用,提供重要的后台服务。
配置load-on-startup的Servlet有两种方式
- 在web.xml文件中通过<servlet.../>的子元素<load-on-startup.../>进行配置
- 通过@webServlet注解的loadOnStartup属性指定
<load-on-startup.../>元素和loadOnStartup属性都只接受一个整型值,这个整型值越小,Servlet越优先实例化
五. 访问servlet的配置参数
配置Servlet时,还可以增加额外的配置参数。通过使用配置参数,可以实现提供更好的可移植性,避免将参数以硬代码的方式写在代码程序中。
设置参数的两种方式
- 通常@webServlet 的initParam属性来指定
- 通过在web.xml文件的<servlet.../>元素中添加<init-param.../>指定
访问Servlet参数通过servletConfig对象完成,ServletConfig提供如下方法。
String getInitParamter(String name):用于获取初始化参数
六. 使用Servlet作为控制器
在标准的Java EE的MVC设计模式中Servlet仅作为控制器使用。JSP作为表现层技术,其作用有两点
- 负责收集用户请求参数
- 将应用的处理结果,状态数据呈现给用户
servlet仅充当控制器角色,它的作用类似于调度员;所有用户请求都发给Servlet,Servlet调用Model来处理用户请求,并调用JSP来呈现处理结果;或者Servlet直接调用JSP将应用的状态数据呈现给用户
model通常由JavaBean充当,所有业务逻辑,数据访问逻辑都在model中实现。事实上,隐藏在Model下的可能还有很多丰富的组件,例如dao组件,领域对象等,下面介绍了一个使用Servlet作为控制器的MVC应用,该应用演示了一个简单的登录验证。
<%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="" %> <html> <head> <title>new document</title> </head> <body> <span style="color:red;font-weight: bold;"> <% if(request.getAttribute("err") != null){ out.println(request.getAttribute("err")+"<br/>"); } %> </span> 请输入用户名和密码:<br/> <form id="login" method="post" action="login"> 用户名: <input type="text" name="username"><br/> 密 码:<input type="password" name="pass"/><br/> <input type="submit" value="登录"> </form> </body> </html>
package java.gdut.servlet; import javax.servlet.RequestDispatcher; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpSession; import java.io.IOException; import java.sql.ResultSet; @WebServlet(name = "login",urlPatterns = "/login") public class LoginServlet extends javax.servlet.http.HttpServlet { protected void service(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { String errMsg = ""; RequestDispatcher rd; String username = request.getParameter("username"); String pass = request.getParameter("pass"); try{ DbDao db = new DbDao("jdbc:mysql://localhost:3306/tb_test","com.mysql.jdbc.Driver","sherman","a123"); ResultSet rs = db.querry("select pass from user_inf where name=?",username); if(rs.next()){ if(rs.getString("pass").equals(pass)){ HttpSession session = request.getSession(true); session.setAttribute("name",username); rd=request.getRequestDispatcher("/welcome.jsp"); rd.forward(request,response); }else{ errMsg+="您的用户密码不符合,请重新输入"; } }else{ errMsg+="您的用户名不存在,请先注册"; } }catch(Exception e){ e.printStackTrace(); } if(errMsg != null && !errMsg.equals("")){ rd = request.getRequestDispatcher("/login.jsp"); request.setAttribute("err",errMsg); rd.forward(request,response); } } }
package java.gdut.servlet; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class DbDao { private Connection conn; private String url; private String driver; private String user; private String pass; public DbDao(String url, String driver, String user, String pass) { this.url = url; this.driver = driver; this.user = user; this.pass = pass; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getDriver() { return driver; } public void setDriver(String driver) { this.driver = driver; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } public String getPass() { return pass; } public void setPass(String pass) { this.pass = pass; } /** * 获取数据库连接 */ public Connection getConn() throws Exception { if (conn == null) { Class.forName(this.driver); conn = DriverManager.getConnection(this.url, this.user, this.pass); System.out.println(conn); } return conn; } /** * 执行插入 * @param sql * @param args * @return * @throws Exception */ public boolean insert(String sql,Object... args) throws Exception{ PreparedStatement prst = getConn().prepareStatement(sql); for (int i = 0; i <args.length ; i++) { prst.setObject(i+1,args[i]); } if(prst.executeUpdate() != 1){ return false; } return true; } /** * 执行查询 * @param sql * @param args * @return * @throws Exception */ public ResultSet querry(String sql,Object... args)throws Exception{ PreparedStatement prst = getConn().prepareStatement(sql); for (int i = 0; i < args.length; i++) { prst.setObject(i+1,args[1]); } return prst.executeQuery(); } public void modify(String sql,Object... args)throws Exception{ PreparedStatement prst = getConn().prepareStatement(sql); for (int i = 0; i < args.length; i++) { prst.setObject(i+1,args[1]); } prst.executeUpdate(); prst.close(); } public void closeConn()throws Exception{ if(null != conn && !conn.isClosed()){ conn.close(); } } }
以上是关于Servlet开发的主要内容,如果未能解决你的问题,请参考以下文章
java.util.MissingResourceException: Can't find bundle for base name init, locale zh_CN问题的处理(代码片段