文章目录
一、含义
1.1 基础
1.1.1 含义
项目 | 含义 |
---|---|
本质 | 一个Servlet就是一个Java类,但需要在web.xml文件中注册。 |
运行位置 | 在服务器上运行的小程序。即不在客户端运行。 |
基础性 | JSP的前身。即先有servlet再有JSP。 |
访问模式 | 通过“请求-响应”编程模型,来访问这个驻留在服务器内存里的servlet程序。 |
MVC位置 | 相当于控制器角色(C)。 |
(1)Java Servlet 是运行在 Web 服务器或应用服务器上的程序。
(2)解码请求,格式化响应。
(3)Servlet是Java语言中编写Web服务器扩展功能的重要技术。
(4)是JSP技术的底层运行基础。JSP页面在编译期或运行期,都会先转化成Servlet文件。
(5)Servlet是一个基于java技术的Web组件,运行在服务器端,由servlet容器管理,用于生成动态内容。
1.1.2 作用
- 接收页面数据。
- 简单处理数据。
- 调用service层方法,并传入前端接收的参数。
- 接收service返回结果。
- 简单处理后,向前端传递数据。
- 页面跳转。
1.1.3 Servlet等级
1.1.4 Servlet生命周期
生命周期 | 说明 |
---|---|
初始化阶段 | 调用init()方法。 |
响应客户请求阶段 | 调用service()方法。 |
终止阶段 | 调用destroy()方法 |
初始化----->加载---->实例化---->服务---->销毁
注意:
servlet的生命周期由Servlet容器管理。因此,不需要new一个servlet的实例。也不用我们手动去销毁(初始化)它。
——初始化时间
即实例化时间。启动tomcat,打开浏览器访问这个Servlet时。可见一个servlet只会构造一次。
——销毁时间
servlet容器关闭时。
doget和dopost两个处理业务逻辑的执行次数:每一次用户访问时候都会执行。
1.1.5 Tomcat装载Servlet的三种情况
情况一:Servlet容器启动时,会自动装载某些Servlet。
——即添加< loadon-startup>标签。
实现自动装载,只需要在web.xml文件的< servlet></ servlet>之间添加如下代码:< loadon-startup>1< loadon-startup>。数字越小表示优先级越高。
情况二:Servlet容器启动后,客户首次向Servlet发送请求时。
——即点击页面请求时
情况三:Servlet类文件被更新后,会重新装载Servlet。
——即修改servlet代码,重新保存时。
注意:
- servlet实例被加载后,servlet对象会长期保存在服务器的内部。直至上述三种情况出现,才会被重新加载。
- Servlet被装载后,servlet容器创建一个servlet实例,并且调用servlet的init()方法进行初始化。在servlet的整个生命周期内,init()方法只被调用一次。
1.1.6 Servlet继承结构
接口或类 | 说明 |
---|---|
Servlet接口(interface) | init() + service() + destroy() |
GenericServlet基类(abstract) | 与协议无关的Servlet |
HttpServlet基类(abstract) | 实现了http协议的Servlet |
自定义servlet类(实现类) | 重写(覆盖)doGet()和doPost()方法。 |
1.2 比较
1.2.1 与CGI比较
CGI:Common Gateway Interface,公共网关接口。
比CGI实现的程序优势:
(1) 性能更好。
(2)在 Web 服务器的地址空间内执行。不必再创建一个单独的进程来处理每个客户端请求。
(3)独立于平台。因为它们是用 Java 编写的。
(4)可信的。服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。
(5)Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。
1.2.2 与JSP比较
相同点
jsp和servlet本质都是一样的,都是可以通过java程序动态的生产静态网页,因为jsp经编译后就变成了的java文件,其实就是一个功能增强的Servlet。
不同点
——输出html形式。jsp是感觉是在html中嵌入java代码。当然事实上jsp转译后也是输出html的。servlet是在java代码中输出html。
(1)Servlet擅长于流程控制和事务处理。控制层。
(2)JSP由HTML代码和JSP标签构成,可以方便地编写动态网页。视图层。
因此在实际应用中采用Servlet来控制业务流程,而采用JSP来生成动态网页。
——对象创建:
(1)JSP有很多内置对象可以直接使用
(2)Servlet需要自己定义。
二、步骤
2.1 创建servlet——继承HttpServlet类
(1)继承HttpServlet类。
(2)重写doGet、doPost、init等方法。
LifeServlet.java:
public class LifeServlet extends HttpServlet {
// 设置属性。接收初始化参数。与web.xml中的参数名一一对应。
private String username;
private String password;
public LifeServlet() {
}
// 方法。初始化。
@Override
public void init() throws ServletException {
this.setUsername(this.getInitParameter("username"));
this.setPassword(this.getInitParameter("password"));
}
// 接受get提交的方法
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html:charset=utf-8");
PrintWriter out = response.getWriter();
out.println("接受get提交的方法");
out.flush();
out.close();
}
// 接受post提交的方法
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response); //让doPost()做doGet()方法,目的是减少代码量。
}
// servlet的destroy销毁化方法
@Override
public void destroy() {
super.destroy();
}
}
2.2 注册Servlet
web.xml
<servlet>
<!-- 第一步:定义Servlet标识。名称 -->
<servlet-name>LifeServlet</servlet-name>
<!-- 第二步:映射后端中的Servlet类路径 -->
<servlet-class>pockageName.LifeServlet</servlet-class>
<!-- 第三步:初始化参数(个数不限),可省略。 -->
<init-param>
<param-name>username</param-name>
<param-value>admin</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</init-param>
</servlet>
<servlet-mapping>
<!-- 第四步:映射本文件中的Servlet标识符。 -->
<servlet-name>LifeServlet</servlet-name>
<!-- 第五步:映射前端请求的URL。 -->
<url-pattern>/actionValue|aHref</url-pattern>
</servlet-mapping>
三、示例-用户登录
需求:在登录界面。输入姓名和密码时,通过数据库存储的信息,判断登录成功与否。
3.1 数据库
3.1.1 数据库设计
数据库名(shopping)
表名(users):字段1(id)+ 字段2(username) + 字段3(password)
CREATE DATABASE IF NOT EXISTS shopping;
CREATE TABLE IF NOT EXISTS users(
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT COMMENT '用户id',
username VARCHAR(20) NOT NULL COMMENT '登录名',
password VARCHAR(30) NOT NULL COMMENT '密码',
gender VARCHAR(10) COMMENT '性别',
hobby VARCHAR(100) COMMENT '爱好'
)ENGINE = InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=UTF8;
3.1.2 数据库连接
DBUtil.java:
public class DBUtil{
private static final String driver = "com.mysql.jdbc.Driver";
private static final String url = "jdbc:mysql://127.0.0.1:3306/shopping?characterEncoding=utf8";
private static final String user = "root";
private static final String password = "123456";
private Connection conn = null;
private PreparedStatement ps = null;
private ResultSet rs = null;
static{
try{
Class.forName(driver);
}catch(ClassNotFoundException e){
e.printStackTrace();
}
}
// 方法1。连接数据库。
public static Connection getConnection(){
if(conn == null){
try{
conn = DriverManager.getConnection(url,user,password);
}catch(SQLException e){
e.printStackTrace();
}
}
return conn;
}
// 方法2。关闭SQL语句和结果集。
public void closeRsAndPs(){
try{
if(rs != null){
rs.close();
}
if( ps != null){
ps.close();
}
}catch(SQLException e){
e.printStackTrace();
}
}
// 方法3。关闭连接。
public void closeConnection(){
try{
if(conn != null){
conn.close();
}
}catch(SQLException e){
e.printStackTrace();
}
}
}
3.2 model层。
3.2.1 创建实体类
属性与数据库一一对应
Users.java:
private int id;
private String username;
private String password;
private String gender;
private String[] hobby;
// getter和setter使用自动生成。
3.2.2 DAO层
实现数据库访问层。
目的:
(1)增加用户:单增加(姓名+密码)。
(2)查询用户:单查询(姓名) + 多查询(无)
(3)删除用户:单删除(姓名 + 密码)
(4)修改用户:单修改(新旧姓名+新旧密码)。
UserDao.java:
public class UserDao{
private Connection conn = null;
private PreparedStatement ps = null;
private ResultSet rs = null;
// 方法1。设置用户属性。
public void setUserAttribute(Users user, ResultSet rs){
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setGender(rs.getString("gender"));
String[] hobbyArray = rs.getString("hobby").split(",");
user.setHobby(hobbyArray);
}
// 方法2。查询。形参:用户姓名。返回值:用户对象集。
public List<Users> queryByName(String username){
List<Users> users = null;
if(username != null){
try{
conn.setAutoCommit(false);
conn = DBUtil.getConnection();
String sql = "SELECT * FROM users WHERE username = ?;";
ps = conn.prepareStatement(sql);
ps.setString(1,username);
rs = ps.executeQuery();
Users user = null;
while(rs.next){
user = new Users();
setUserAttribute(user, rs);
users.add(user);
}
conn.commit();
}catch(SQLException e){
e.printStackTrace();
}finally{
DBUtil.closeRsAndPs();
}
}
return users;
}
// 方法3。查询。形参:无。返回值:用户对象集。
public List<Users> queryAll(){
List<Users> users = null;
try{
conn.setAutoCommit(false);
conn = DBUtil.getConnection();
String sql = "SELECT * FROM users";
ps = conn.prepareStatement(sql);
ps.setString(1,username);
rs = ps.executeQuery();
Users user = null;
while(rs.next){
user = new Users();
setUserAttribute(user, rs);
users.add(user);
}
conn.commit();
}catch(SQLException e){
e.printStackTrace();
}finally{
DBUtil.closeRsAndPs();
}
return users;
}
// 方法4。单查询。形参:用户姓名 + 密码。返回值:用户对象。
public Users queryByNameAndPass(String username, String password){
Users user = null;
if(username != null && password != null){
try{
conn.setAutoCommit(false);
conn = DBUtil.getConnection();
String sql = "SELECT * FROM users WHERE username = ? AND password = ?;";
ps = conn.prepareStatement(sql);
ps.setString(1,username);
ps.setString(2,password);
rs = ps.executeQuery();
user = new Users();
setUserAttribute(user, rs);
conn.commit();
}catch(SQLException e){
e.printStackTrace();
}finally{
DBUtil.closeRsAndPs();
}
}
return user;
}
// 方法5。删除。形参:用户姓名 + 密码。返回值:无。
public void deleteUser(String username, String password){
if(username != null && password != null){
if(queryByNameAndPass(username,password) != null){
try{
conn = DBUtil.getConnection();
String sql = "DELETE FROM users WHERE username = ? AND password = ?;"
ps = conn.prepareStatement(sql);
ps.setString(1,username);
ps.setString(2,password);
ps.executeUpdate();
}catch(SQLException e){
e.printStackTrace();
}finally{
DBUtil.closeRsAndPs();
}
}
}
}
// 方法6。增加。形参:用户姓名 + 密码。返回值:无。
public void addUser(String username, String password,String gender, String hobby){
if(username != null && password != null){
if(queryByName(username) == null){
try{
conn = DBUtil.getConnection();
String sql = "INSERT INTO users(username,password,gender,hobby) VALUES(?,?,?,?);"
ps = conn.prepareStatement(sql);
ps.setString(1,username);
ps.setString(2,password);
ps.setString(3,gender);
ps.setString(2,hobby);
ps.executeUpdate();
}catch(SQLException e){
e.printStackTrace();
}finally{
DBUtil.closeRsAndPs();
}
}
} else {
System.out.println("用户名为" + username + "已经存在,请重新命名!");
}
}
// 方法7。修改。形参:用户姓名(新旧) + 密码(新旧)。返回值:无。
public void modifyUser(String username, String password, String newUsername , String newPassword,String gender, String hobby){
if(username != null && password != null && newUsername != null && newPassword != null){
if(queryByName(username,password) != null){
try{
conn = DBUtil.getConnection();
String sql = "UPDATE users SET username = ?,password = ?,password = gender,password = hobby WHERE username = ? AND password = ? ;";
ps = conn.prepareStatement(sql);
ps.setString(1,newUsername);
ps.setString(2,newPassword);
ps.setString(3,gender);
ps.setString(4,hobby);
ps.setString(5,username);
ps.setString(6,password);
ps.executeUpdate();
}catch(SQLException e){
e.printStackTrace();
}finally{
DBUtil.closeRsAndPs();
}
}
}
}
}
3.3 Control层
实现servlet。
LoginServlet.java:
public class LoginServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response){
doPost(request,response)
}
@Override
protected void doPost(HttpServletRequest request,HttpServletResponse response){
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=utf-8");
// 获取用户名和密码。
String username = request.getParameter("username");
String password = request.getParameter("password");
// 调用DAO层。
DBUtil dbutil = new DBUtil();
User user = dbutil.queryByNameAndPass(username,password);
// 根据查询结果。返回给视图层。
if( user != null){
// 把信息保存在request作用域。
request。setAttribute("username",username);
// 请求转发。目的保存此次用户名和密码。
request.getRequestDispatcher("success.jsp").forward(request,response);
request.sendRedirect("success.jsp");
}else{
// 请求重定向。目的不保存此次的用户名和密码。
response.sendRedirect("error.jsp");
}
}
}
AddUserServlet.java:
public class AddUserServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response){
UserDao userDao=new UserDao();
//1、获得view信息,并封装成javaBean对象
String username=request.getParameter("username");
String password=request.getParameter("password");
int gender=Integer.parseInt(request.getParameter("gender"));
String [] hobbys=request.getParameterValues("hobby");
StringBuffer hobbytemp=new StringBuffer();
for(int i=0;i<hobbys.length;i++){
hobbytemp.append(hobbys[i]+",");
}
User user=new User();
user.setUsername(username);
user.setPassword(password);
user.setGender(gender);
user.setHobby(hobbytemp.toString());
// 2、添加到数据库
int result= userDao.addUser(user);
// 3、返回页面
if(result>0){
response.sendRedirect("servlet/UserListServlet");
}else{
response.sendRedirect("loginerror.jsp");
}
}
@Override
protected void doPost(HttpServletRequest request,HttpServletResponse){
doGet(request,response);
}
}
注册servlet(配置servlet)
web.xml:
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.servlet.LoginServlet</servlet-class>
</servlet>
<!-- servlet的url映射 -->
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>UserAddServlet</servlet-name>
<servlet-class>com.servlet.UserAddServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserAddServlet</servlet-name>
<url-pattern>/userAddServlet</url-pattern>
</servlet-mapping>
3.4 View层
界面设计。action路径要与url-pattern一致。
登录页面。
login.jsp:
<form action="login" method="post">
用户名:<input type="text" name="username" /><br/>
密码:<input type="passwor" name="password" /><br/>
性别:<input type="radio" value="boy" name="gender" />男
<input type="radio" value="girl" name="gender" />女<br/>
爱好:<input type="checkbox" value="羽毛球" name="hobby">羽毛球
<input type="checkbox" value="篮球" name="hobby">篮球
<input type="checkbox" value="足球" name="hobby">足球 <br />
<input type="submit" value="登录"/>
</form>