JavaWeb编程(九)

Servlet笔记 :114.132.126.14

 

gitee网址:https://gitee.com ----- 搜索开源 zing163

processon流程图官网 --- https://www.processon.com/?utm_source=360&utm_medium=sem&utm_term=45417586705&utm_content=4813041658

方便做笔记:

Ctrl+c+Ctrl+v eclipse项目 添加项目

```html 点 Enter 代码块

Shift+Tab 靠左

Tab 往右缩进

ALT+/ 代码提示

Ctrl+E 代码提示

Ctrl + Shift + o 导包

重置 Windoe--Perspective--Reset Perspective

追踪代码步骤 双击最左边的数字 -- 点击小虫子

WEB程序入门

1、软件结构

1)基于C / S 结构

  • C:Client,客户端

  • S:Server,服务端

 

2)基于B / S 结构

特殊的C / S 结构

  • B:Browser,浏览器(客户端)

  • S:Server,服务端

 

注意:

  • 我们开发的WEB程序就是基于B/S结构,程序员只专注于开发服务器端程序(JAVA)即可!

  • 但是浏览器中的界面由 HTML + CSS + JavaScript 实现!

  • 在服务器(运行在网络的计算机)中,需要安装一个专门软件,用于解释或运行WEB程序,这个软件我们称之为WEB服务器或WEB容器。

    • IIS(Internet Information Services)

    • Apache、Nginx

    • Tomcat、Resin、Jetty、 GlassFish、JBoss

    • WebLogic、WebSphere

 

 

2、Tomcat

1)网址

https://tomcat.apache.org/

 

2)安装

解压到指定目录,建议不要存在有中文或空格字符

 

3)启动Tomcat

Tomcat根据目录/bin/startup.bat

注意:

  • Tomcat是一个基于Java开发的程序,运行Tomcat之前,必须保证安装好JDK,且配置好JAVA_HOME

  • Tomcat启动后,不能关闭,否则无法提供相关的WEB服务

 

4)关闭Tomcat

  • Tomcat根据目录/bin/startup.bat

  • 在Tomcat服务容器中按Ctrl + c

  • 直接点击关闭按钮

 

5)测试是不是成功

http://localhost:8080

http://127.0.0.1:8080

 

3、第一个WEB程序

1)手动实现

第一:创建WEB项目,项目结构如下所示:

WEB程序根目录(规范)

WEB-INF

src:存放Java源代码

classes:存放字节码文件

lib:存入相关的jar文件

jsp:存放jsp页面(特殊HTML文件)

web.xml:文件,描述部署文件

META-INF

相关资源

根据需要创建子目录

资源有:html、css、js、图片、音频、视频、相关文件...

 

注意:

WEB程序,必须发布相关的WEB服务器(Tomcat)上运行

在Tomcat中,有一个目录叫webapps,用于存放运行的WEB程序

 

第二:把WEB程序(项目),发布到Tomcat中的webapps目录下

 

第三:启动Tomcat

 

第四:访问WEB项目

WEB项目基于 B / S 结构的软件,用户打开浏览器,在地址栏中输入服务器程序(项目)的访问URL即可 !URL的语法格式如下所示:

http://服务器地址:端口号/WEB应用/[路径]/资源(网页,图片,视频,音频...)

 

服务器地址:可以是IP地址,也可以是具体的域名(DNS)

http://localhost:8080/taobao/index.html

http://127.0.0.1:8080/taobao/news/20200524/1001.html

http://169.254.111.34:8080/taobao/news/20200525/1002.html

 

2)eclipse实现

第一:创建WEB项目

File - New - Project... - Web - Dynamic Web Project

 

 

第二:输入项目名称

 

 

第三:项目结构

 

第四:编写项目

  • 前端页面

    • HTML、 CSS、JavaScript

  • 后端Java代码

    • JAVA程序

    • JAVAWEB程序(三大组件)

      • Servlet

      • Filter

      • Listener

 

第五:配置JDK环境

 

第六:配置WEB服务器 - Tomcat

Window菜单 - Preferences - Server - Runtime Environments

 

 

第七:添加Tomcat服务器

 

 

第八:发布项目

 

 

第九:配置Tomcat

 

 

第十:启动Tomcat

在Servler面板中,右键Tomcat - start启动Tomcat

 

第十一:访问项目

http://localhost:8080/jd/index.html

 

4、HTTP协议

1)通信协议

指的是两台计算机之间沟通交互所遵循的规则、方式。

 

2)HTTP协议

http协议是其中的一种网络通信协议

我们开发的WEB程序就是基于Http协议进行通信的

 

3)HTTP协议的特点

  • 基于请求(Request)和响应(Response)两个过程。

  • 无状态
    • 服务器不会记住客户端

 

4)请求方式

  • 表示客户端向服务器请求,具体要做什么操作。

  • 能过请求方式规范化客户端请求操作

    • get请求:默认,查询操作

    • post请求:添加操作

    • put请求:修改操作

    • delete请求:删除操作

 <form action="" method="post">
     
 </form>

 

5)报文

客户端向服务器发起请求,以及服务器响应客户端的过程中,都会携带相关的信息,我们把这些信息称之为报文。

 

6)常见的响应状态码

200请求已成功
401 请求被禁止,未授权
404 请求的资源不存在
405 请求行的方法不被支持
500 服务器内部错误

 

5、Tomcat常用的配置

1)端口号

 <Connector connectionTimeout="20000" port="9999" protocol="HTTP/1.1" redirectPort="8443"/>

 

2)编码配置

 <Connector connectionTimeout="20000" port="9999" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

客户端发送GET请求时,如果请求的参数有中文字符,很有可能发生乱码。因为Tomcat默认是按ISO-8859-1进行URL解码

Tomcat--conf--server.xml(记事本)

 

Servlet入门

一、概念

  • Servlet是一个JAVA程序;

  • Servlet程序运行在服务器中(Tomcat)

  • Servlet的功能:处理客户端的HTTP请求(接受用户的请求,响应用户的请求)

 

WEB程序 = (HTML + CSS + JS) + (JAVA + Servlet + Filter + Listener)

 

二、开发步骤

第一:定义一个类,并继承HttpServlet

 public class HelloWorldServlet extends HttpServlet {
     
 }

 

第二:重写父类的doXxx方法,Xxx表示客户端请求的方式,如post、get等

 public class HelloWorldServlet extends HttpServlet {
     @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
         throws ServletException, IOException {
  // doPost方法用于处理客户端浏览器发起的post请求
    }
     
     @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
         throws ServletException, IOException {
  // doGet方法用于处理客户端浏览器发起的get请求
    }
 }

注意:Servlet程序不需要用户实例化,也就是不需要new!

Servlet程序由Servlet容器(Tomat)管理 ,同时Servlet相关的对象也是由Tomcat管理

 

第三:在doXxx方法中,编写代码,实现相关的业务逻辑功能(需求)

 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     // doPost方法用于处理客户端浏览器发起的post请求
     // 1.获取打印输出流对象
     PrintWriter out = resp.getWriter();
 
     // 2.打印输出内容到浏览器(响应结果)
     out.print("<h1>Hello,World - post</h1>");
 
     // 3.关闭流对象
     out.flush();
     out.close();
 }
 
 // ...

 

第四:配置web.xml文件,对外提供一个访问URL

 <!-- 1.定义Servlet -->
 <servlet>
     <servlet-name>hello</servlet-name>
     <servlet-class>com.servlet.HelloWorldServlet</servlet-class>
 </servlet>
 
 <!-- 2.映射Servlet,对外提供访问URL -->
 <servlet-mapping>
     <servlet-name>hello</servlet-name>
     <url-pattern>/sayHello</url-pattern>
 </servlet-mapping>

注意:Servlet程序中,不需要main方法作为程序的执行入口!

而是根据请求的URL + 请求的方式来决定调用哪个Servlet程序,以及哪个doXxx方法

三、请求和响应对象

1、概述

HttpServletRequest和HttpServletResponse都是接口,由Servlet容器实例化,程序员直接使用对象的相关方法进行相关的操作。

  1. 请求对象:HttpServletRequest

    • HttpServletRequest对象内封装了关于这个请求的相关详细信息。

  2. 响应对象:HttpServletResponse

    • HttpServletResponse对象专门用来封装HTTP响应消息。

 

2 、HttpServletRequest常见API方法

 // 获取表单中的数据
 String getParameter(String name)
   
 // 获取复选框中的数据
 String[] getParrameterValues(String name)
 
 // 设置请求的字符编码方式 - utf-8
 setCharacterEncoding(String encoding)
 
 //返回请求的URL地址,如:http://localhost:8080/sms/login
 StringBuffer getRequestURL()
 
 //返回URL中的一部分,从“/”开始,包括上下文,但不包括任意查询字符串
 //如:/sms/login
 String getRequestURI()
 
 //获取Servlet的请求地址,也就是url-pattern,如:/login
 String getServletPath()
 
 //返回指定Servlet上下文(WEB应用)的URL的前缀,如:/sms
 String getContextPath()
 
 //返回查询字符串,即URL中?后面的内容,如:u=zing&p=123
 String getQueryString()
 
 //转发,服务器端跳转
 getRequestDispatcher("跳转的页面/Servlet").forward(请求对象,响应对象)
 getRequestDispatcher("跳转的页面/Servlet").include(请求对象,响应对象)
 
 //属性操作
 setAttribute("属性名","属性值")
 getAttribute("属性名")
 removeAttribute("属性名")
 
 //返回一个cookie对象数组
 Cookie[] getCookies();
 
 //返回指定HTTP标题的值
 String getHeader(String var1);
 
 //返回生成这个请求HTTP的方法名称
 String getMethod();
 
 //返回与这个请求相关的会话对象
 HttpSession getSession();

3、HttpServletResponse常见API方法


 

四、乱码处理

1、请求

// post请求
请求对象.setCharacterEncoding("utf-8") ;
req.setCharacterEncoding("utf-8");

String name = req.getParameter("username") ;

// get请求 
// 方法一:配置Tomcat默认编码
// 方法二:编码
new String(中文数据.getbytes("iso8859-1"),"UTF-8"); 猫版本太低使用不了,如果想使用就要升级版本

 

2、响应

// 1.设置响应对象的编码
resp.setContentType("text/html;charset=utf-8");
resp.setCharacterEncoding("utf-8");

 

3、工作空间

Windows菜单 - Preferences - General - Workspace - text file encoding - 设置为utf-8

Windows菜单 - Preferences - web- JSP Fiels - Encoding - 设置为utf-8

另外,切换工作空间时,一般要做以下三件事情

  • 第一:设置编码

  • 第二:设置JDK环境

  • 第三:设置Tomcat

 

4、Tomcat默认编码

<Connector connectionTimeout="20000" port="9999" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="utf-8"/>

五、页面跳转

页面跳转:从一个页面(Servlet)跳转到另一个页面(Servlet)。

在以前,我们是通过超链接实现。

1、转发 - 服务器端跳转

1、转发封装在请求对象中

2、地址栏不发生改变,每次刷新都会执行一遍Servlet程序

http://localhost:9999/login-tiaozhuang-demo/login.html

http://localhost:9999/login-tiaozhuang-demo/login.do

注意:浏览器实际已经跳转到了success.html页面。因此,服务器跳转地址栏不发生改变

3、执行过程不一样 -- 在服务器中跳转

4、转发可以传递请求作用的数据

 

 

2、重定向 - 客户端跳转

1、重定向封装在响应对象中

2、地址发生改变

http://localhost:9999/login-tiaozhuang-demo/login.html

http://localhost:9999/login-tiaozhuang-demo/login.do

http://localhost:9999/login-tiaozhuang-demo/shibai.html

因此,客户端跳转地址栏发生改变

3、执行过程不一样 -- 回到客户端,发起一个新的请求

4、重定向不可以传递请求作用的数据

 

 

注意:把一个数据从一个Servlet传递给另一个Serlvet,必须满足以下两个条件:

  • 把数据设置在请求对象中

  • 转发

 

 

六、Eclipse导入Servlet源码

第一:打开官网

https://tomcat.apache.org

 

第二:下载对应版本的源码包

 

第三:在Eclipse中导入源码包

 

 

七、案例

1、Servlet实现HelloWorld

 

2、模拟实现用户登录

第一:设计登录页面(HTML + CSS + JS)

<h1>用户登录</h1>
<hr/>
<form method="post" action="login.do">
    帐号:<input type="text" name="username"/><br/>
    密码:<input type="password" name="password"/><br/>
    
    <input type="submit" value="登录"/>
    <input type="submit" value="注册"/>
    <input type="reset" value="重置"/>
</form>

 

第二:编写Servlet,实现登录功能

Servlet:服务器端程序 —— 在服务器上运行的JAVA程序。Servlet程序需要一个特殊的运行环境,这个环境我们称之为Servlet容器 —— Tomcat(WEB服务器)

package com.ld.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 实现用户登录
 * 
 * @author zhang
 *
 */
// 第一:定义一个类,继承HttpServlet
public class LoginServlet extends HttpServlet{
	
	// 第二:重写doXxx方法
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
        throws ServletException, IOException {
		// 第三:编写代码,实现相关的业务功能 - 登录功能
		// 注意:在Serlvet程序中,一般我们需要借助于“请求”、“响应”对象做相关的处理
		
		// 0.设置请求对象的编码
		req.setCharacterEncoding("utf-8");
		
		
		// 1.设置响应对象的编码
		resp.setContentType("text/html;charset=utf-8");
		
		// 2.获取打印输出流对象
		PrintWriter out = resp.getWriter() ;
		
		// 3.获取用户登录的数据
		String uname = req.getParameter("username") ;
		String upass = req.getParameter("password") ;
        // int uage = Integer.parseInteger(req.getParameter("age")) ;
		
		System.out.println(uname);
		
		// 4.合法性判断
		if("张三".equals(uname) && "123456".equals(upass)) {
			// 5.响应结果
			out.print("恭喜,登录成功");
		} else {
			out.print("对不起,错误的帐号或密码");
		}
		
		// 6.关闭流
		out.flush();
		out.close();
	}
}

 

第三:配置web.xml文件

<servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>com.ld.servlet.LoginServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/login.do</url-pattern>
</servlet-mapping>

 

注意:

  • 命名规范

  • 一般先访问前端页面,通过前端页面调用相关后台的服务器端程序(Servlet)

 

第四:测试

http://localhost:8080/login-demo/login.html

 

说明

  • http://localhost : 找到网络某台服务器

  • 8080:这台服务器中某个WEB服务器

  • login-demo:WEB服务器中部署的某个项目

  • login.html:客户端请求的资源

 

3、结合JDBC,实现用户登录

用户登录 - JDBC

一、创建数据表

-- 创建数据库
create database ums ;
use ums ;

-- 创建数据表
create table userinfo 
(
	id int primary key identity(1,1) ,
	username varchar(50) not null  check( len(username) > 5 ),
	[password] char(6) not null ,
	tel char(11)  unique ,
	sex char(2) default '男' ,
	[weight] float ,
	birth date,
	hobby varchar(50) ,
	reg_time datetime default getdate()
) ;

-- 添加初始化数据
insert into userinfo(username,[password]) values ('admin888','123456') ;

select * from userinfo ;

 

二、创建项目

1、配置工作空间的编码

2、JDK

3、Tomcat

4、创建Dynamic Web Project ...

 

三、创建前端页面

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户管理系统 - 用户登录</title>
</head>
<body>
	<form action="" method="post">
		帐号:<input type="text" name="username"/><br/>
		密码:<input type="password" name="password"/><br/>
		<input type="submit" value="登录"/>
		<!-- todo:使用样式修改按钮,并使用JS实现页面跳转到注册页面 -->
		<button>用户注册</button>
	</form>
</body>
</html>

 

四、编写后台JAVA代码

com|org.公司名称.组织名称.项目名称.模块名称.Xxxx.java

1、工具包(utils)

org.nf.s186.ums.utils

package org.nf.s186.ums.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 连接数据库
 * 注意:要把连接驱动jar包(jtds-1.3.1.jar),添加到项目的lib目录
 * @author zhang
 *
 */
public class DBUtil {
	/**
	 * 连接驱动程序
	 */
	private  static final String DRIVER = "net.sourceforge.jtds.jdbc.Driver" ;
	/**
	 * 连接URL
	 */
	private  static final String URL = "jdbc:jtds:sqlserver://localhost:1433;DatabaseName=ums" ;
	/**
	 * 帐号
	 */
	private  static final String USER = "sa" ;
	/**
	 * 密码
	 */
	private  static final String PASS = "123" ;
	
	
	
	static {
		// 加载驱动程序
		try {
			Class.forName(DRIVER);
		} catch (ClassNotFoundException e) {
			System.out.println("加载驱动程序失败...");
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取连接对象 -- Java程序 与 数据库之间的桥梁
	 * @return
	 */
	public static Connection getConnection() {
		Connection conn = null ;
		try {
			conn = DriverManager.getConnection(URL, USER, PASS);
		} catch (SQLException e) {
			System.out.println("获取连接对象失败...");
			e.printStackTrace();
		}
		return conn ;
	}
	
	/**
	 * 关闭相关的 JDBC 对象
	 *  DriverManager:驱动管理对象,获取连接对象
	 *  		DriverManager.getConnection(URL, USER, PASS);
	 *  
	 * 	ResultSet:结果集对象
	 * 			用于接收查询数据时,返回的结果
	 * 
	 *  Statement:语句对象 用数据库(sql)的
	 *  		用于执行SQL语句(PreparedStatement、CallableStatement)
	 *  			增、删、改:executeUpdate()
	 *  			查询:executeQuery()
	 *  		
	 *  
	 *  Connection:连接对象
	 *  		建立JAVA程序与数据库之间的桥梁
	 * 
	 * @param rst 
	 * @param stmt 
	 * @param conn 
	 */
	public static void close(ResultSet rst,Statement stmt,Connection conn) {
		if(rst!=null) {
			try {
				rst.close() ;
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		
		if(stmt!=null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		if(conn!=null) {
			try {
				conn.close() ;
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	// executeUpdate()、executeQuery() - 略 
	public static void main(String[] args) {
		System.out.println(DBUtil.getConnection());
	}
}

 

2、实体包(entity、domain)

org.nf.s186.ums.entity

package org.nf.s186.ums.entity;

import java.util.Date;

/**
 * 实体对象 - 用户对象 - 用于封装数据、传递数据
 * 
 * 一般有多个数据表,就有多少个实体对象 
 * 	1)表中的字段就是实体对象的属性 
 *  2)对象的属性一般要私有化,且生成相关的setter/getter方法
 * 	3)根据需要,可以定义重载构造方法,而默认的构造方法一般要显示写出来
 * 
 * 命名规范: 属性名首字母小写 驼峰标识 命名有意义
 * 
 * @author zhang
 *
 */
public class UserInfo {
	private int id;
	private String username;
	private String password;
	private String tel;
	private String sex;
	private double weight;
	private Date birth;
	private String hobby;
	private Date regTime;
	
	/**
	 * 默认(缺省)构造方法
	 * 
	 * 注意:当重载构造方法后,缺省构造方法就会被丢失
	 * 因此,一般我们会手动补回来
	 */
	public UserInfo() {}
	/**
	 * 重载构造方法 - 便于初始化对象 - 帐号、密码、手机号码
	 * @param username
	 * @param password
	 * @param tel
	 */
	public UserInfo(String username, String password, String tel) {
		this.username = username;
		this.password = password;
		this.tel = tel;
	}
	
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public double getWeight() {
		return weight;
	}
	public void setWeight(double weight) {
		this.weight = weight;
	}
	public Date getBirth() {
		return birth;
	}
	public void setBirth(Date birth) {
		this.birth = birth;
	}
	public String getHobby() {
		return hobby;
	}
	public void setHobby(String hobby) {
		this.hobby = hobby;
	}
	public Date getRegTime() {
		return regTime;
	}
	public void setRegTime(Date regTime) {
		this.regTime = regTime;
	}
}

3、数据访问对象包(dao)

1)DAO接口

org.nf.s186.ums.dao

实体名称Dao

package org.nf.s186.ums.dao;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 定义 用户信息表(用户对象) 的相关数据操作接口
 * 
 * 接口定义了相关的标准、规范,用于指定对象能做什么事情,
 * 		具体什么行为,但没有具体的实现。
 * 		具体的实现根据实际情况,定义相关的实现类实现(多态)。
 * 
 * 便于程序的扩展和维护
 * 	
 * 
 * DAO:数据访问对象(Data Access Object),
 * 		数据相关操作的对象,一般服务于业务对象,不包含相关的业务操作,只是单纯的实现数据操作(CRUD)
 * 		如果有相关业务就提取到业务对象实现;
 * 		如果没有相关业务代码或简单的业务可以直接在Servlet实现,而不需要业务对象
 * 
 * @author Administrator
 *
 */
public interface UserInfoDao {
	/**
	 * 根据帐号和密码查询用户,服务于登录业务
	 * @param username
	 * @param password
	 * @return
	 */
	public UserInfo queryUser(String username,String password) ;
	
	// 增、删、改、各种查询...
}

 

2)DAO接口实现

org.nf.s186.ums.dao.impl

实体名称DaoImpl

package org.nf.s186.ums.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DBUtil;

/**
 * UserDao接口的实现类
 * 
 * 根据需要,可以定义多个DAO接口的实现类,从而解决不同需求的情况
 * 
 * 
 * @author Administrator
 *
 */
public class UserInfoDaoImpl implements UserInfoDao{

	@Override
	public UserInfo queryUser(String username, String password) {
		
        //声明对象
		UserInfo user = null ;
		
		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "select * from userinfo where username=? and password=?" ;
		
		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();
		
		// 第三:获取语句对象
		PreparedStatement stmt = null ;
		ResultSet rst = null ;
		
		try {
			// 1.预编译SQL语句
			stmt = conn.prepareStatement(sql);
			// 2.填充数据
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			stmt.setString(1,username) ;
			stmt.setString(2,password) ;
			
			
			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			rst = stmt.executeQuery();
			
			// 第五:处理SQL语句返回的结果
			if(rst.next()) {
				// 1.实例化对象
				user = new UserInfo() ;
				
				// 2.读取各个字段的数据
				// 语法如下:
				// 1)结果集对象.getXxx(字段索引)
				// 2)结果集对象.getXxx(字段列名)
				String name = rst.getString(2) ;
				String sex = rst.getString("sex");
				
				// 3.封装数据
				user.setUsername(name);
				user.setSex(sex);
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(rst, stmt, conn);
		}
	
		return user;
	}
}

4、业务包(service)

1)Service接口

org.nf.s186.ums.service

实体名称Service

package org.nf.s186.ums.service;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 业务接口
 * 	如果业务单一或在确定的情况下,可以不需要定义接口
 * 	或者也可以根据实际情况,后期根据需求,重构代码再定义此接口
 * 
 * @author Administrator
 *
 */
public interface UserInfoService {
	/**
	 * 登录
	 * @param username
	 * @param password
	 * @return
	 */
	public UserInfo login(String username,String password) ;
}

 

2)Service接口实现

org.nf.s186.ums.service.impl

实体名称ServiceImpl

package org.nf.s186.ums.service.impl;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;

public class UserInfoServiceImpl implements UserInfoService {

	@Override
	public UserInfo login(String username, String password) {
		// 第一:实例化DAO对象 
		UserInfoDao userInfoDao = new UserInfoDaoImpl() ;
		
		// 第二:查询数据
		UserInfo userInfo = userInfoDao.queryUser(username, password);
		
		// 第三:返回结果
		return userInfo;
	}
}

5、Servlet包(servlet、controller、web)

浏览器(操作界面) ---- Servlet(桥梁) ----- 后台JAVA代码

org.nf.s186.ums.servlet

package org.nf.s186.ums.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;
import org.nf.s186.ums.service.impl.UserInfoServiceImpl;

/**
 * 处理登录的服务器程序
 * @author Administrator
 *
 */
public class LoginServlet extends HttpServlet{
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		// 第一:获取用户输入的数据
		String username = req.getParameter("username");
		String password = req.getParameter("password");
		
		// 第二:实例化业务对象
		UserInfoService userInfoService = new UserInfoServiceImpl() ;
		
		// 第三:处理
		UserInfo userInfo = userInfoService.login(username, password);
		
		// 第四:响应
		String path = "welcome.html" ;
		
		if(userInfo==null) {
			path = "error.html" ;
		}
		
		// 1.页面跳转 -- 重定向
		// resp.sendRedirect(path);
		
		// 2.页面跳转 -- 转发
		req.getRequestDispatcher(path).forward(req, resp);
		
		
	}
}

五、测试、运行

package org.nf.s186.ums.test;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;

public class MainTest {

	public static void main(String[] args) {
		// 第一:定义帐号密码(模拟用户输入 )
		String username = "admin888" ;
		String password = "123456" ;
		
		// 第二:定义DAO对象,查询数据
		UserInfoDao userInfoDao = new UserInfoDaoImpl() ;
		
		// 第三:调用方法
		UserInfo user = userInfoDao.queryUser(username, password);
		
		// 第四:判断是否登录成功
		if(user==null) {
			System.out.println("登录失败");
		} else {
			System.out.println("恭喜"+user.getUsername()+",登录成功");
		}	
		
	}

}

 

六、会话跟踪

一、概念

1、什么是会话

客户端浏览器与服务器之间的连接对话;

在整个对话过程中,会产生相关请求和响应操作;

 

2、什么是会话跟踪

监视或跟踪同一个用户,在某个会话中,所做的一系列工作。

 

3、为什么需要会话跟踪

HTTP 协议是“无状态”的协议;

用户做某个操作,可能需要发起多个请求才能完成

会话跟踪就记录相同的这些相关操作

 

4、Servlet相关的对象

1)HttpServletRequest:请求对象

  • getParameter(String param):获取客户端参数值

  • setCharacterEncoding(String encoding):设置请求字符编码

  • getRequestDispatcher(String path):获取转发对象

  • getCookies():获取客户端发送过来的Cookie对象

  • getSession():获取HttpSession对象的实例

  • setAttribute():设置请求作用域属性值

  • getAttribute():获取请求作用域属性值

  • removeAttribute():移除请求作用域属性值

2)HttpServletResponse:响应对象

  • setContentType("text/html;charset=utf-8"):设置响应内容及编码

  • setCharacterEncoding(String encoding):设置响应字符编码

  • sendRedirect(String path):重定向

  • addCookie(Cookie ck):服务器向客户端发送Cookie对象

3)Cookie

  • getName():获取Cookie对象的键名称

  • getValue():获取Cookie对象的值

4)HttpSession:会话对象

  • getId():获取会话ID

  • setAttribute():设置会话作用域属性值

  • getAttribute():获取会话作用域属性值

  • removeAttribute():移除会话作用域属性值

 

5)ServletContext:上下文对象

6)ServletConfig:配置对象

 

二、实现会话跟踪

1、Cookie

1)概念
  • 客户端浏览器的一个文本文件,用于记录服务器发送的相关信息

    • Cookie封装的数据,以是键值对的方式存储的

  • 客户端浏览器每次请求时,都会把Cookie携带到服务器

  • 服务器可以读取Cookie的相关信息

  • 服务器根据需求可以更新Cookie信息,并发回给客户端浏览器

从而,实现会话跟踪

 

2)操作
设置Cookie
public class SetCookieServlet extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
		// 第一:实例化Cookie对象,同时初始化键值对的数据
		// Cookie Cookie对象名称 = new Cookie("key","value") ;
		Cookie yingHuaKaPian = new Cookie("number","5") ;
		
		// 第二:发送给客户端浏览器 -- 响应过程 -- 得找响应对象去
		resp.addCookie(yingHuaKaPian);
	}
}

 

获取Cookie
public class GetCookieServlet extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
		// 第一:服务器读取Cookie对象的数据
		// 1.获取客户端浏览器传递过来的Cookie对象 -- Cookie对象的数组
		Cookie[] cookies = req.getCookies() ;
		
		// 2.循环遍历 
		Cookie ck = cookies[0];
		
		// 3.分别获取Cookie对象中的键值数据
		String key = ck.getName();
		String value = ck.getValue();
		
		System.out.println(key + "-" + value);
	}
}

 

3)中文处理
// 编码 - 注意:Cookie对象的键不支持中文,必须经过编码处理
String key = URLEncoder.encode("姓名", "UTF-8") ;

// 解码
String key2Name = URLDecoder.decode(key2, "UTF-8");

 

4)生命周期

从出生到死亡这个过程,就是生命周期

  • 默认情况下,Cookie对象在关闭浏览时就销毁

  • 我们可以设置Cookie对象的有效时间

    • cookie对象.setMaxAge(时间):时间单位为秒

 

2、HttpSession

1)概念
  • HttpSession和Cookie对象都可以存储用户的相关信息

    • HttpSession是存储在服务器中

    • Cookie是存在在客户端中

  • 每个客户端发起请求时,服务器都会创建一个唯一的HttpSession对象

    • Session 对象有一个唯一标识,叫做 SessionID(会话ID)

    • SessionID 是以 cookie 的机制保存在客户端浏览器

  • 工作原理

    • 客户端发起请求(第一次请求)

      • 注意:客户端每次请求都会把浏览器的Cookie对象带回给服务器

    • 服务器创建一个HttpSession对象

    • 服务器把HttpSession对象的唯一标识(SessionID)以Cookie对象存储在客户端器中

    • 客户端再次发起请求时,会把Cookie对象存储的SessionID带回给服务器

    • 服务器根据SessionID获取对应的HttpSession对象

    • 在请求和响应过程中,我们可以通过HttpSession对象存储和访问相关的数据

    • 注意:

      • 浏览关闭,HttpSession并没有销毁

      • HttpSession在默认30分钟内如果没有访问,则会自动销毁

 

超市会员卡机制

 

2)操作
// 1.获取HttpSession对象的实例
HttpSession session = req.getSession() ;

// 2.操作 - 调用HttpSession对象中的相关方法
// 2.1)获取会话ID
String sessionID = session.getId() ;

// 2.2)数据的设置、获取、移除
setAttribute() / getAttribute() / removeAttribute()
    
// 2.3)设置有效时间

 

3)生命周期

 

3、URL重写

 

4、表单隐藏域

七、监听器

一、概念

JEE中三大组件的其中一个

Servlet:获取客户端浏览器请求,处理请求(结合业务),响应结果

Filter:在请求和响应的过程中进行拦截,并做相关拦截处理(特殊、特定场景)

Listener:监听作用域对象的相关操作,并做相关的监听处理

  • 监听作用域对象的生命周期

    • 创建

    • 销毁

  • 监听作用域对象的属性操作

    • 设置属性:第一次调用setAttribute()

    • 替换属性:重复调用setAttribute()

    • 移除属性:removeAttribute()

 

父母监听孩子

  • 是否乱吃东西

  • 是否做危险动作

 

二、监听器分类

1、HttpServletReuqest

1)生命周期
  • ServletRequestListener

 

2)属性操作
  • ServletRequestAttributeListener

 

 

 

2、HttpSession

1)生命周期

HttpSessionListener

 

2)属性操作

HttpSessionAttributeListener

 

3)对象绑定监听器

HttpSessionBindingListener

 

4)对象迁移监听器

HttpSessionActivationListener

 

3、ServletContext

1)生命周期
  • ServletContextListener

 

2)属性操作
  • ServletContextAttributeListener

 

三、监听器的实现

第一:定义一个类,实现相关监听器的接口

public class MyListener implements XxxListener {
    // ....
}

注意:其中XxxListener就是具体的监听器分类(8个),不同监听器分类作用不一样,根据实际需求选择使用。

 

第二:重写监听接口的相关方法

 

第三:在重写方法中,编写代码,实现具体的监听处理

 

第四:配置web.xml —— 注册监听器

<listener>
	<listener-class>xxx.xxx.MyListener</listener-class>
</listener>

 

四、案例

统计在线人数

  • 需求:

    • 查看在线人数

    • 查看具体在线用户

  • 实现

    • 登录

    • 登录成功后把当前登录的用户存储在HttpSession中

      • session.setAttribteu("user",user) ;

      • 创建会话对象属性操作监听器,实现集合的添加和移除操作

    • 把所有登录的用户存在起来,每个用户都能查看 -- 上下文对象

      • 定义一个集合(Map<key,value>),用于存储所有的用户

      • 把集合共享到上下文对象中

      • 创建上下文对象生命周期监听器,用于创建集合对象

====================================

CH01-WEB程序入门

zing 2021-06-01

一、概念

1、WEB 程序

基于 B/S 结构,利用 WEB 技术开发的程序。

  • B:Browser(浏览器),客户端程序

    • HTML、CSS、JAVASCRIPT

  • S:Server(服务器)

    • Servlet/JSP、PHP、ASP、CGI 等。

2、服务器

服务器通常由硬件和软件部分构成,对用户提供相应服务的计算机。

硬件:包括相应的 CPU、内存、磁盘等等

软件:包括操作系统、运行环境、服务端软件、数据库等等

3、WEB 服务器

运行在服务器的软件,它是 WEB 程序运行的环境。

  • 运行于某服务器(计算机)的程序,用于提供 WEB 应用程序执行的环境。

  • 常见的 web 服务器有

    • IIS(Internet Information Services)

    • Apache、Nginx

    • Tomcat、Resin、Jetty、 GlassFish、JBoss

    • WebLogic、WebSphere

  • 而 Tomcat、Jetty 这些 web 服务器更准确的说是一个 Servlet 容器。

4、WEB 程序原理

1)请求:浏览器通过地址栏输入 URL 地址向相应的服务器发送请求

2)响应:服务器把处理结果响应给客户端

3)基于 HTTP 协议

5、WEB 程序(项目)目录结构

项目根目录,例如:myweb、ch01  通常存放静态资源文件(如:html 等等)
  WEB-INF   这个目录是当前项目私有的一个文件夹,只能提供给项目内部访问,对于客户端来说是访问不到了,通常这个目录下存放的是 Java 源代码、编译后的字节码文件以及 Servlet 的核心配置文件 web.xml
    src 存放 Java 源代码的目录
    classes 存放编译后的字节码文件
    lib lib 目录存放当前项目所需要的 jar 文件
    jsp 用于存放 JSP 动态页面
    web.xml 项目的配置文件,用于配置 Servlet 的请求映射、过滤器、监听器等等信息。每一个 web 项目都对应一个 web.xml 配置文件
  META-INF   配置应用程序、扩展程序、类加载服务等等

二、HTTP 协议

1、概述

超文传输协议,是一种通信协议,架构在 TCP/IP 之上的应用层协议。所谓通信协议,指的是两台计算机之间沟通交互所遵循的规则、方式。

2、特点

1)基于请求(Request)和响应(Response)模型。

HTTP 是一种基于请求/响应的通信协议,客户端对服务器发出一个获取资源的请求,服务器将请求的资源响应给客户端。每次的联机只做一次请求/响应。是一种简单的通信协议,没有请求就不会有响应。

image-20190616164033671

2)无状态

在 HTTP 协议之下,服务器端是一个健忘的家伙,它响应客户端后,就不会记得客户端的信息,更不会去维护与客户端有关的状态。因此,HTTP 又称为无状态的通信协议。

image-20190616164544014

说明:每一次的请求/响应都是重新发起的,都是新的请求/响应。

3、请求方法

在 HTTP/1.1 协议中,请求方法主要包括 8 个,下面列举常用的请求方法进行说明。

方法说明
GET 向服务器请求指定的资源,并返回响应主体。一般来说 GET 方法应该只用于数据的读取(类似于查询)
POST 向指定的服务器提交数据(例如:表单数据的提交、文件上传等),并且提交的数据会放入请求体中(类似于新增)
PUT 向服务器提交数据,但是和 POST 有所区别。如果服务器不存在此资源的时候,则执行新增,如果存在则执行修改(类似于修改)
DELETE 根据 uri 的标识删除服务器上的某个资源(类似于删除)
其他

备注:GET 与 POST 区别:

1)GET 主要用于获取数据,POST 用于提交数据。

2)GET 请求所带的参数是放在请求行的 url 地址后面,而 POST 这是放在请求体中。

3)通常浏览器会对 GET 请求的 url 长度有所限制,而 POST 提交的数据在请求体中,可以提交更多的内容。

4)浏览器会对 GET 请求进行缓存。

4、基本组成

HTTP 报文:用于 HTTP 协议交互的信息称之为HTTP 报文。报文本身是由多行数据构成的字符串文字。HTTP 报文通常由报文首部和报文主体两部分组成,两者之间由最初出现的空行划分。

  • 报文首部:客户端或服务器端发送的请求或响应报文的内容及属性。

  • 空行(回车+换行):用来区分报文首部和报文文体。

  • 报文主体:所有需要的用和资源的信息。

1)请求报文

客户端发出的报文叫做请求报文

image-20190616221616665

请求行:包括了客户端请求的方法,URL 和 HTTTP 协议版本

请求首部字段:包括了请求的附加信息,如客户端的信息、响应的优先级(键值对)。

通用首部字段:请求报文和响应报文都会使用的报文。

实体首部字段:补充了与实体有关的资源信息,如实体更新的时间。

报文主体:一般来说请求报文在使用 GET 方法的时候没有报文主体,在使用 POST 方法的时候才有。

2)响应报文

服务器端发出的报文叫做响应报文。

image-20190616222046684

状态行:包括响应结果的状态码,状态描述和 HTTP 版本。

响应首部字段:服务器端向客户端发送响应报文使用的首部包括相应的附加内容,要求客户端补充的消息等。

通用首部字段:请求报文和响应报文都会使用的报文。

实体首部字段:补充了与实体有关的资源信息,如实体更新的时间。

报文主体:对于响应报文来说报文体一般是传给客户端的数据。

5、常见的响应状态码

状态码说明
200 请求已成功
401 请求被禁止,未授权
404 请求的资源不存在
405 请求行的方法不被支持
500 服务器内部错误
其他

三、开发 WEB 项目的步骤

1、手动

1)下载、解压 Tomcat

2)编写 WEB 应用程序

WEB 应用程序必须遵循以下的目录结构规范

  • 项目名称

    • WEB-INF

      • classes

      • lib

      • web.xml

    • 目录/资源(HTML+CSS+JS、JSP、图片、声音)

3)把 WEB 应用程序放在 Tomcat/webapps 目录中

4)启动 WEB 服务器

5)打开客户端浏览器,输入请求 URL

http://服务器地址:端口号/WEB应用/[路径]/资源(网页,图片,视频,音频...)
http://www.baidu.com:80/news/20010123123.html
http://localhost:8080/myweb/index.html
http://127.0.0.1:8080/myweb/index.html
http://服务器的IP地址:8080/myweb/index.html
http://域名:8080/myweb/index.html

2、工具

1)安装相关的工具

  • JDK——下载、安装、并配置环境变量:JAVA_HOME、Path

  • TOMCAT——下载、解压 Tomcat

  • Eclipse——下载、解压 Eclipse

2)在 Eclipse 工具中新建项目

  • new Dynamic Web Project

  • 给项目指定一个 Web 服务器

  • web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
  <display-name>abc</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

3)编写程序:编写 Servlet、JAVA、JSP、HTML….

4)部署 Web 应用程序:把 Web 应用程序发布到 Tomcat 中

5)Tomcat 和 Eclipse 整合在一起

  • serves : new Server

  • 把当前的项目发布到 Tomcat 中(add and remove)

6)启动 Tomcat

7)打开浏览器(客户端),输入 URL

http://服务器地址[:端口号]/路径/.../目标文件(jsp,html,jpg,css,js)
http://localhost:8080/myweb/helloChina.jsp

8)测试运行

四、Tomcat

1、概述

Tomcat 是一个免费的、开放源代码的、支持 Jsp 和 Servlet 技术的容器,它同时又是一个 Web 服务器软件。

Tomcat 的特点:运行时占用的系统资源小,扩展性好,支持负载平衡和邮件服务等开发应用系统常用的功能。Tomcat 是一个小型的轻量级应用服务器,是开发和调试 Jsp 程序的首选。常用的 Web 服务器还有:JBoss,WebLogic,WebSphere、Apache、Nginx、Jetty。

安装 Tomcat 服务器要得到 JDK 的支持。因此,在安装 Tomcat 之前,必须安装 JDK。

2、目录结构

  • bin:Tomcat 执行脚本目录

  • common:Tomcat 公用类包

  • conf:Tomcat 配置文件(server.xml,web.xml

  • shared:Tomcat 共享类包

  • logs:Tomcat 执行时的 LOG 文件

  • server:Tomcat 服务包

  • work:Tomcat 工作目录

  • webapps:Tomcat 的主要 Web 发布目录

    • ROOT:Tomcat 主目录

    • tomcat-docs:Tomcat 文档

    • jsp-examples:Tomcat 的 Jsp 样例

    • servlets-examples:Tomcat 的 Servlet 样例

3、Tomcat 常用的配置

Tomcat 主目录/conf 文件夹下的 server.xml 文件是对 Web 服务器的配置。

1)端口号的设置
<Connector port="8080" maxHttpHeaderSize="8192"
           maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
           enableLookups="false" redirectPort="8443" acceptCount="100"
           connectionTimeout="20000" disableUploadTimeout="true" />

Tomcat 默认的端口号为:8080,修改为 80。但要注意端口号是否已占用,如 IIS 服务器的端口号是默认是 80。

<Connector port="80" maxHttpHeaderSize="8192"
           maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
           enableLookups="false" redirectPort="8443" acceptCount="100"
           connectionTimeout="20000" disableUploadTimeout="true" />
2)配置站点

当你不想把你的 jsp 页放到 Tomcat 主目录/webApps/Root 时,我们可以通过配置 server.xml 文件。打开 server.xml,ctrl+F 找到<Host>元素,然后在<Host>元素内加入<Context>元素,如下:

<Context path="/myweb" docBase="D:\jspweb" />

其中,属性 path 代表是网络访问上下文路径。docBase 属性表示你的应用程序的路径(Jsp 文件的存放目录)

测试:如果在 D:\jspweb 目录下有 HelloWorld.html 文件,则可以输入以下地址测试是否配置成功:

http://localhost:8080/myweb/HelloWorld.html
3)编码配置
<Connector port="8080" maxHttpHeaderSize="8192"
           maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
           enableLookups="false" redirectPort="8443" acceptCount="100"
           connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="UTF-8"/>

客户端发送 GET 请求时,如果请求的参数有中文字符,很有可能发生乱码。因为, Tomcat 默认是按 ISO-8859-1 进行 URL 解码,ISO-8859-1 并未包括中文字符,这样的话中文字符肯定就不能被正确解析了。因此,Tomcat 在解析参数的时候应该使用正确的编码格式(UTF-8)进行解码——通过 URIEncoding 进行配置。

 

CH02-Servlet

zing 2021-06-02

一、概念

Servlet 是 JavaEE 中的标准组件之一,专门用于处理客户端的 HTTP 请求。并且它必须依赖于 Servlet 容器(Tomcat 就是一个标准的 Servlet 容器)才可以运行,而不能脱离这个环境而单独执行。因为 Servlet 实例的创建和销毁都是由容器负责管理的,我们不能自行通过 new 关键去创建和使用它。

  • Servlet 是一个 JAVA 程序;

  • Servlet 程序运行在服务器中;

  • Servlet 的功能:处理客户端的 HTTP 请求(接受用户的请求,响应用户的请求)

说明:

运行 Servlet 程序的 Web 服务器也叫 Servlet 容器。

Servlet 容器与 Servlet 程序之间的关系:超市 & 服务员。

image-20190618134349995

<servlet>
	<servlet-name>hello</servlet-name>
	<servlet-class>zing.servlet.HelloWorld</servlet-class>
</servlet>

<servlet-mapping>
	<servlet-name>hello</servlet-name>
	<url-pattern>/sayhello</url-pattern>
</servlet-mapping>

Servlet 执行过程

客户端浏览器发起 HTTP 的请求,这个请求首先会被 Servlet 容器(如 Tomcat)截获,然后容器会根据 web.xml 文件中配置 Servlet 的<url-pattern>找到相应的<servlet-name>这个别名,然后再根据这个别名找到具体 Servlet 的类,最后容器会创建这个 Servlet 类的实例并调用 service 方法来处理这个请求。

在 HttpServlet 中的 service 方法中,会根据请求的方法,执行相关的 doXxx()方法。

//源码
protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

        String method = req.getMethod();

        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                } catch (IllegalArgumentException iae) {
                    // Invalid date header - proceed as if none was set
                    ifModifiedSince = -1;
                }
                if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);

        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);

        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);

        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);

        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);

        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);

        } else {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
            //

            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);

            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }

因此,在继承 HttpServlet 的类中,可以重写相关的 doXxx()方法,对 Xxx 的请求方法进行处理。

public class HelloWorld extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {

		//处理get请求
	}

  @Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {

		//处理post请求
	}
}

当然,在继承 HttpServlet 的类中,可以重写父类的 service()方法,覆盖父类的 service()方法,Servlet 容器就直接调用子类重写父类的 service()方法,这样就可以处理客户端所有的请求方法。

public class HelloWorld extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {

		//覆盖父类HttpServlet的service()方法,处理所有的请求
	}
}

二、开发步骤

1、创建 WEB 项目

2、定义一个继承 HttpServlet 的类

public class HelloServlet extends HttpServlet{

}

3、重写父类的 service 方法,这个就是专门处理客户端请求的方法,WEB 容器会为这个方法传入两个参数 HttpServletRequest 和 HttpServletResponse,并且这个方法还需要抛出 ServletException 和 IOException 给容器捕获。

public class HelloServlet extends HttpServlet {
	public void service(HttpServletRequest request, HttpServletResponse response)
    throws ServletException,IOException{

    //设置响应类型及编码
    response.setContentType("text/html;charset=UTF-8");
    //获取字符输出流输出html信息
    response.getWriter().println("<h1>Hello Servlet</h1>");
	}
}

4、编译 Servlet,需要依赖 servlet-api.jar 文件,将它添加到 classpath 中。

javac -cp d:\servlet-api.jar -encoding utf-8 -d . HelloServlet.java

5、将编译后的 HelloServlet.class 文件剪切到 classes 目录中。

6、在 WEB-INF 目录下创建并编辑 web.xml 文件,为 servlet 配置请求映射

<?xml version="1.0" encoding="utf-8"?>
<!-- 配置根节点 -->
<web-app>
   <!-- 定义servlet类 -->
   <servlet>
   	  <!-- 指定servlet的别名 -->
   	  <servlet-name>hello</servlet-name>
   	  <!-- 指定Servlet的完整类名(包名.类名)-->
   	  <servlet-class>org.zing.HelloServlet</servlet-class>
   </servlet>

   <!-- 配置请求映射-->
   <servlet-mapping>
   	   <!-- 这里的servlet-name和上面的servlet-name要一一对应 -->
   	  <servlet-name>hello</servlet-name>
   	  <!-- 配置请求映射的url,必须以“/”开头-->
   	  <url-pattern>/hello</url-pattern>
   </servlet-mapping>
</web-app>

url-pattern 匹配顺序

  • 完全匹配:/test

  • 路径匹配:/a/b/test

  • 后缀匹配:.jsp、.do

  • 匹配所有:/*

7、将项目部署都 tomcat 的 webapps 目录中,并执行 bin 目录下的 startup.bat 启动容器

8、打开浏览器,在地址栏输入 http://localhost:8080/myweb/hello 访问 Servlet

三、生命周期

1、概念

所谓的生命周期,就是 Servlet 从创建服务一直到它销毁的这个过程。并且它的这个生命周期都是由 Servlet 容器(Tomcat)负责管理和维护的。

在 Tomcat 中,Servlet 是以单实例多线程的方式处理客户端请求。

image-20190618183945671

2、 Servlet 对象创建的过程

Servlet 容器只创建一个 Servlet 实例(单例)。当第一次请求某个 Servlet 的时候,容器会先查找是否已经存在这个 Servlet 的实例。如果存在,则创建线程处理并响应客户端请求;如果不存在,则创建一个 Servlet 实例。然后,创建线程并响应客户端请求。在创建 Servlet 实例时,会调用 init()方法进行初始化工作,并把实例缓存到容器中,后续相同的请求都由这个缓存的对象来处理。

注意:这里说的是第一次请求时创建。另外一种情况则是在容器启动的时候就创建 Servlet 的实例,在 web.xml 中为 Servlet 指定<load-on-startup>配置,这个配置的值是一个整型,数值越小,则初始化的优先级别越高。

在客户端发起请求时,Servlet 容器对请求的资源进行解析,接收客户端的数据,创建请求对象并封装客户端数据。同时,创建响应对象,用于封装服务端传递给 WEB 客户的响应消息。在调用 service()方法时,把请求对象和响应对象传递到 service()方法的参数中。

通过调用 Servlet 中的 service()方法来处理和响应客户端的请求,HttpServlet 中的 service()方法会根据客户端不同的请求方式,调用相关的 doXxx()方法,如 doGet()方法用于处理客户端的 get 请求,doPost()方法用于处理客户端的 post 请求。

服务器关闭或超时,Servlet 容器会销毁 Servlet 实例,在销毁之前,会调用 Servlet 实例的 destroy()方法,做一些释放资源的工作。

3、处理请求(服务)过程

客户端的每个请求,都会创建一个线程。该线程调用 servlet 实例的 service 方法。Service 方法根据收到 HTTP 请求得类型,调用 doGet,doPost 或者其他方法。

4、生命周期方法

方法名描述
init 在 Servlet 对象创建之后立即执行的初始化方法,且只执行一次
service 核心的请求处理方法,这个方法可以执行多次
destroy 容器准备销毁 Servlet 实例之前执行这个方法,也是执行一次(容器重启或关闭)

四、请求与响应对象

1、请求对象

Servlet 容器对于接受到的每一个 Http 请求,都会创建一个 ServletRequest 对象,并把这个对象传递给 Servlet 的 Sevice( )方法。其中,ServletRequest 对象内封装了关于这个请求的许多详细信息。HttpServletRequest 表示 Http 环境中的 Servlet 请求,它扩展于 javax.servlet.ServletRequest 接口。

1)常用的方法
//获取表单中的数据
String getParameter(String name)

//获取复选框中的数据
String[] getParrameterValues(String name)

//设置请求的字符编码方式
setCharacterEncoding():

//返回请求的URL地址,如:http://localhost:8080/sms/login
StringBuffer getRequestURL()

//返回URL中的一部分,从“/”开始,包括上下文,但不包括任意查询字符串
//如:/sms/login
String getRequestURI()

//获取Servlet的请求地址,也就是url-pattern,如:/login
String getServletPath()

//返回指定Servlet上下文(WEB应用)的URL的前缀,如:/sms
String getContextPath()

//返回查询字符串,即URL中?后面的内容,如:u=zing&p=123
String getQueryString()

//转发,服务器端跳转
getRequestDispatcher("跳转的页面/Servlet").forward(请求对象,响应对象)
getRequestDispatcher("跳转的页面/Servlet").include(请求对象,响应对象)

//属性操作
setAttribute("属性名","属性值")
getAttribute("属性名")
removeAttribute("属性名")

//返回一个cookie对象数组
Cookie[] getCookies();

//返回指定HTTP标题的值
String getHeader(String var1);

//返回生成这个请求HTTP的方法名称
String getMethod();

//返回与这个请求相关的会话对象
HttpSession getSession();
2)防盗链

实现防盗链的方法很多。在这里,可以通过对引用地址的判断来实现防盗链。判断引用地址,就是判断浏览器请求时 HTTP 头的 Referer 字段的值。

@WebServlet("/aa")
public class HelloWorld extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req,
                         HttpServletResponse resp) throws ServletException, IOException {
		// 获取referer字段的值,即获取请求是从哪里来的
		String referer = req.getHeader("referer");
		// 如果是直接输入的地址(返回null)
		// 或者不是从本网站访问的重定向到本网站的首页
		if (referer == null || !referer.startsWith("http://localhost")) {
			// 重写向到首页
			resp.sendRedirect("index.html");
			// return返回,不往下执行
			return;
		}

    //以下是盗链接请求的资源
		String date = "连接请求的资源";
		System.out.println(date);
	}
}

2、响应对象

javax.servlet.ServletResponse 接口表示一个 Servlet 响应,在调用 Servlet 的 Service( )方法前,Servlet 容器会先创建一个 ServletResponse 对象,并把它作为第二个参数传给 Service( )方法。ServletResponse 隐藏了向浏览器发送响应的复杂过程。

在 Servlet API 中,定义了一个 HttpServletResponse 接口,它继承自 ServletResponse 接口,专门用来封装 HTTP 响应消息。由于 HTTP 请求消息分为状态行,响应消息头,响应消息体三部分,因此,在 HttpServletResponse 接口中定义了向客户端发送响应状态码,响应消息头,响应消息体的方法。

//重定向,客户端跳转
void sendRedirect("跳转的页面/Servlet");

//获取字符输出流:PrintWriter
PrintWriter getWriter();

//获取字节输出流:ServletOutputStream
ServletOutputStream getOutputStream();

//设置响应内容类型、字符编码
setContentType(“text/html;charset=utf-8”);

//添加、设置响应头信息
//添加(add)响应头,不管存不存在都会新加入一个
//设置(set)响应头,如果存在响应头信息,则执行更新
addHeader(String name, String value);
addIntHeader(String name, int value);
addDateHeader(String name, long date);
setHeader(String name, String value);
setDateHeader(String name, long date);
setIntHeader(String name, int value);

//设置头信息,三秒钟刷新并跳转到新的页面
setIntHeader(“refresh”,”3;URL=地址”);

//设置响应状态码
setStatus(int code);

//将一个Set-Cookie头标加入到响应
addCookie(Cookie cookie);

encodeRedirectURL(String url);
encodeRUL(String url);

注意:虽然 response 对象的 getOutSream()和 getWriter()方法都可以发送响应消息体,但是他们之间相互排斥,不可以同时使用,否则会发生异常。

五、乱码

1、请求

//POST请求
request.setCharacterEncoding("UTF-8");

//GET请求
new String(parameter.getbytes("iso8859-1"),"UTF-8");

2、响应

默认情况下,PrintWriter 对象使用 ISO-8859-1 编码(该编码在输入中文时会发生乱码)。

//设置内容类型、编码
response.setContentType("text/html;charset=UTF-8") ;

PrintWriter out = response.getWriter() ;
out.print("<h1>hello,张三</h1>") ;

out.flush();
out.close();

3、设置工作空间文本文件编码方式

image-20190619160311186

4、配置 Tomcat 默认编码方式

<Connector port="8080" maxHttpHeaderSize="8192"
           maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
           enableLookups="false" redirectPort="8443" acceptCount="100"
           connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="UTF-8"/>

客户端发送 GET 请求时,如果请求的参数有中文字符,很有可能发生乱码。因为, Tomcat 默认是按 ISO-8859-1 进行 URL 解码,ISO-8859-1 并未包括中文字符,这样的话中文字符肯定就不能被正确解析了。因此,Tomcat 在解析参数的时候应该使用正确的编码格式(UTF-8)进行解码——通过 URIEncoding 进行配置。

六、跳转

1、转发——服务器端跳转

1)概念

所谓转发,就是在多个 Servlet 之间共享请求和响应对象,所有参与转发过程的 Servlet 都可以共享同一个请求对象的信息,在 Servlet 的 API 中,转发的操作是由 HttpServletRequest 对象完成的。

2)转发的特点
  1. URL 地址栏不会发生改变

  2. 转发的过程是在服务端自动完成

3)示例代码
public class ServletA extends HttpServlet{
	public void service(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException, IOException{
		//获取页面提交的参数
		String name = request.getParameter("userName");		//zss
		//转发由HttpServletRequest完成
		//第一步先获取一个请求转发器RequestDispatcher
		//获取请求转发器的同时要告诉转发器转发到哪里,转发给谁
		//如果要转发给ServletB,那么就是对应ServletB的url-pattern
		RequestDispatcher rd = request.getRequestDispatcher("servletB");
		//调用转发器的forward方法执行转发,同时将request和response对象一并转发ServletB
		rd.forward(request, response);
	}
}
public class ServletB extends HttpServlet{
	public void service(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException, IOException {
		//这里可以获得同一个请求的参数
		String name = request.getParameter("userName");		//zss
		System.out.println("ServletB获取请求参数:"+name);
	}
}
4)请求作用域

每一个请求对象都有一个独立的空间,这个空间我们称之为请求作用域(RequestScope)。可以为当前这个请求携带额外的一些数据信息,这些信息同样可以在多个 Servlet 之间进行共享。

public class ServletA extends HttpServlet {
	public void service(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException, IOException{
		//在ServletA中为request对象设置请求作用域
    request.setAttribute("age", 35);
	}
}
public class ServletB extends HttpServlet{
	public void service(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException, IOException{
		//在ServletB中获取统一个请求对象作用域的值
   	Integer age  = (Integer)request.getAttribute("age");
	}
}

2、重定向——客户端跳转

1)概念

重定向的机制和转发不同,首先重定向是通过 HttpServletResponse 对象来完成。一次重定向的过程中会有两次请求和两次响应,服务器在接收第一次请求后会先做一次 302 的响应(302 表示重定向状态码),告诉客户端浏览器必须发起一个新的请求地址,服务端再次接收这个请求处理,最后再次响应客户端。由于会产生不同的请求对象,因此并不同共享同一个请求中的参数。

2)重定向的特点
  1. URL 地址栏会发生改变

  2. 重定向的操作是在客户端浏览器完成的

3)示例代码

方法一

public class ServletC extends HttpServlet {

	@Override
	protected void service(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException, IOException {
		//方式一:设置302响应状态码,并在响应头中添加location属性指定重定向的地址
		response.setStatus(302);
		response.addHeader("location", "http://localhost:8080/ch06/servletD");
	}
}

方法二

public class ServletC extends HttpServlet {

	@Override
	protected void service(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException, IOException {
		//方式二:使用response的sendRedirect方法
		response.sendRedirect("servletD");
	}
}

七、会话跟踪

1、概述

1)什么是会话 客户端打开与服务器的连接发出请求到服务器响应客户端请求的全过程称之为会话。

2)什么是会话跟踪 对同一个用户对服务器的连续的请求和接受响应的监视 。

3)为什么需要会话跟踪 浏览器与服务器之间的通信是通过 HTTP 协议进行通信的,而 HTTP 协议是“无状态”的协议,它不能保存客户的信息,即一次响应完成之后连接就断开了,下一次的请求需要重新连接。服务器不会记得这次请求与下次请求之间的关系(是否为同一请求,同一客户端?)。在实际的应用中,我们实现某些功能时可能要发送多次请求才能完成,而这些请求我们必须保证是同一个客户所为(如购物车)。因此需要会话跟踪技术来实现这些需求 。

  • 顾客与自动售货机

  • 普通顾客(非会员)与商场

4)原理

当服务器响应客户端的第一次请求时,Servlet 容器将会创建一个新的 session 对象(该对象实现了 HttpSession 接口),可以通过此对象保存客户状态的信息。

Servlet 容器会分配一个唯一的 ID,叫 Session ID(会话 ID),发送到客户端使用 Cookie 对象保存在浏览器中。

以后每次发出 HTTP 请求时,Servlet 容器可以从 HttpServletRequest 对象中读取 Session ID,然后根据 Session ID

找到相应的 HttpSession 对象,从而获取客户的状态信息。

2、Cookie

Cookie 是客户端浏览器内部的一个文本文件,专门用于记录服务器发送过来的一些文本信息,那么在每次请求的时候,客户端会都把这个 cookie 信息带回给相应的服务器,服务器就可以获取 cookie 的信息,达到会话跟踪的目的。使用 Cookie 的机制是基于客户端浏览器来维护与服务端的状态跟踪。

1)示例代码

设置 Cookie

public class SetCookieServlet extends HttpServlet{

	protected void service(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException, IOException {
		//创建一个Cookie的实例
		Cookie cookie = new Cookie("userId","10001");
		//将cookie对象设置到响应对象中
		response.addCookie(cookie);
		System.out.println("成功设置cookie");
	}
}

获取 Cookie

public class GetCookieServlet extends HttpServlet{

	@Override
	protected void service(HttpServletRequest request,
                         HttpServletResponse repsonse) throws ServletException, IOException {
		//cookie是通过request对象来得到的
		//从请求中可以获取多个cookie对象
		Cookie[] cookies = request.getCookies();
		for (Cookie cookie : cookies) {
      //System.out.println(cookie.getName()+"->"+cookie.getValue());

			//判断cookie,只获取name为userId的cookie对象
			if("userId".equals(cookie.getName())) {
				System.out.println(cookie.getValue());
			}
		}
	}
}

保存中文

在保存 Cookie 的时候如果需要保存中文,那么中文信息需要经过编码后才可以写入 Cookie。

编码使用 URLEncoder

String str = URLEncoder.encode("张三", "utf-8");
Cookie cookie = new Cookie("userName", str);

解码使用 URLDecoder

String str = URLDecoder.decode(cookie.getValue(), "utf-8");
System.out.println(str);
2)生命周期

默认 cookie 只会保存在浏览器进程的内存中,并不会写入 cookie 文件,如果关闭了浏览器,那么浏览器的进程也就消失了,那么对应的内存就会释放空间,因此 cookie 也就销毁。如果想将 cookie 写入文件,那么就必须设置 cookie 的生命时长,一旦设置了生命时长,那么就表示这个 cookie 会在文件中保留多长的时间,到了这个时间之后,浏览器就会自动销毁这个 cookie。

设置 cookie 存活时间:

//设置为0表示立即删除cookie
cookie.setMaxAge(0);
//设置为正数表示cookie在cookie文件的存活时间,单位:秒
cookie.setMaxAge(5);
//设置为-1表示cookie只保留在浏览器器的进程中,关闭浏览器之后会销毁cookie
cookie.setMaxAge(-1);

2、Session

Session 是基于服务端来保存用户的信息,这个是和 Cookie 的最大区别。不同的客户端在请求服务器的时候,服务器会为每一个客户端创建一个 Session 对象并保存在服务器端,Session 对象是每个客户端所独有的,相互之间不能访问。服务器为了区别不同的 Session 属于哪一个客户端,因此 Session 对象也有一个唯一标识,叫做 SessionID。需要注意的是这个 SessionID 是以 cookie 的机制保存在客户端浏览器。每次请求的时候,浏览器都会把这个 SessionID 带回服务端,服务端根据这个 SessionID 就可以找到对应的 Session 对象。

1)示例代码
public class SessionServlet extends HttpServlet{
	@Override
	protected void service(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException, IOException {
		//HttpSession对象是在第一次调用request的getSession()方法时才会创建
		//注意:getSession()的方法会先判断之前是否为客户端创建了session实例,
		//如果创建了,则使用之前创建好的Session对象,没有则创建一个新的Session
		HttpSession session = request.getSession();
		//创建HttpSession的同时,会创建一个唯一的标识SessionID
		//这个sessionId会保存在浏览器的cookie中,每次请求会带回这个id找到相应的session对象
		String sessionId = session.getId();
		System.out.println(sessionId);
	}
}
2)生命周期

SessionId 是保存在浏览器的 cookie 中,但是不会写入 cookie 文件,这也就表示当关闭浏览器之后,SessionId 就会销毁。SesisonId 销毁以后,服务端的 Session 就没有任何作用了。但是,服务器并不会立刻销毁这个 Session 对象,至于什么时候销毁是由服务器自己决定的。除非我们手动调用了 session.invalidate() 方法,服务器就会立即销毁这个 session 实例。

HttpSession session = request.getSession();
//立即销毁session
session.invalidate();

Session 默认也有存活时间,服务器在创建 Session 的时候为 Session 设置默认的存活时间为 30 分钟,如果在 30 分钟之内,客户端没有发起任何请求到服务器,那么服务器就会销毁这个 Session 对象。我们也可以设置 Session 的存活时间。可以为当前的 Session 设置,也可以为全局(服务器端的所有 Session)的 Session 设置。

设置当前 Session 的存活时间

HttpSession session = request.getSession();
//设置当前Session的存活时间,单位:秒
session.setMaxInactiveInterval(3600);

设置全局的 Session 的存活时间

在 web.xml 中进行设置

<!-- 设置全局Session的存活时间,单位:分钟 -->
<session-config>
  <session-timeout>60</session-timeout>
</session-config>
3)Session 的作用域

当我们需要将一些数据信息存入 Session 的时候,就需要操作 Session 作用域(SessionScope),它和请求作用域类似,也有相应的 setAttribute 和 getAttribute 方法,只不过 Session 作用域的范围要比请求作用域更宽。请求作用域在一次请求响应之后就会消失(因为相应之后请求对象就会销毁)。而 Sesison 对象只要浏览器不关闭或者 Session 对象未超时,那么 Session 对象会一直驻留在服务器端,因此不管重新请求多少次还是转发和重定向,都可以从 Session 中获取之前保存的数据信息。

示例代码:

User user = new User();
user.setUid("1001");
user.setUserName("wangl");
HttpSession session = request.getSession();
//将数据保存在会话作用域中
session.setAttribute("user", user);

从会话作用域取值

HttpSession session = request.getSession();
//取值
User user = (User)session.getAttribute("user");

3、URL 重写

浏览器是可以禁用 Cookie 的,一旦禁用了 Cookie,那么 SessionId 将无法写入 Cookie 的缓存中,这样就导致无法实现会话跟踪了,因此解决办法就是使用 URL 重写。URL 重写的目的就是把 SessionId 在放在请求 URL 地址的后面提交回服务器(类似 GET 请求后面带上参数,而这个参数就是一个 SessionId),服务器会解析这个 URL 的地址并得到 SessionId。

示例代码:

//重写请求的URL地址,这个地址后面会自动带上SessionId
String url = response.encodeRedirectURL("getSession");
//重定向URL
response.sendRedirect(url);

浏览器地址演示

http://localhost:8080/ch07/getSession;jsessionid=4BA4A5C6F5268E1FE3227AEB1A251E97

URL地址?参数名1=值1&参数名2=值2&...&参数名n=值n&jsessionid=4BA4A5C6F5268E1FE3227AEB1A251E97

注意:;号后面跟着就是 SessionId

4、表单隐藏域

<form action="" method="">
  相关的表单控件...
  <input type="hidden" name="参数名1" value="参数值1" />
  ...
  <input
    type="hidden"
    name="jsessionid"
    value="4BA4A5C6F5268E1FE3227AEB1A251E97"
  />
  <input type="hidden" name="参数名n" value="参数值n" />
</form>

八、上下文对象

WEB 容器在启动时会为每一个 WEB 应用创建唯一的上下文对象(ServletContext),这个对象就是 Servlet 上下文对象。此对象可以理解为是当前项目的一个共享内存空间,为项目中的所有 Servlet 提供一个共享的区域。

1、常用 API

//属性操作
setAttribute("属性名","属性值");
getAttribute("属性名");
removeAttribute("属性名");

//获取上下文初始参数
getInitParameter():

//获取项目的相对路径
getContextPath()

//获取项目的绝对路径
getRealPath(String path)

2、上下文作用域

上下文作用域是为当前项目所有 Servlet 提供的一个共享内存区域,可以将需要的数据信息保存在作用域中。这个作用域的的范围是最大的,只要容器没有停止,它就会一直存在。

3、三个作用域对象

  • 请求作用域

  • 会话作用域

  • 上下文作用域

范围从小到大来划分:请求作用域 < 会话作用域 < 上下文作用域

九、过滤器

1、概述

在数据源和数据之间起过滤作用的中间组件,就像污水净化设备,过滤器是一个驻留在服务器端的 Web 组件,可以截取客户端和资源之间的请求与响应信息

当 Web 容器接收到一个对资源的请求时,它将判断是否有过滤器与这个资源相关联。如果有,则容器将请求交给过滤器进行处理。在过滤器中可以改变请求的内容,或者重新设置请求的报头信息,然后将请求发送给目标资源。

当目标资源对请求做出响应时,容器同样会将响应先转发给过滤器,在过滤器中,可以对响应的内容进行转换,然后再将响应发送给客户端。

简单说,就是可以实现 Web 容器对某资源的访问前截获进行相关的处理,还可以在某资源向 Web 容器返回响应前进行截获进行处理。

image-20190621145331290

2、工作原理

当客户端发出 Web 资源的请求时,Web 服务器根据应用程序配置文件设置的过滤规则进行检查,若客户请求满足过滤规则,则对客户请求/响应进行拦截,对请求头和请求数据进行检查或改动,并依次通过过滤器链,最后把请求/响应交给请求的 Web 资源处理。请求信息在过滤器链中可以被修改,也可以根据条件让请求不发往资源处理器,并直接向客户机发回一个响应。当资源处理器完成了对资源的处理后,响应信息将逐级逆向返回。同样在这个过程中,用户可以修改响应信息,从而完成一定的任务。

FilterChain:过滤链,如果在过滤器中调用 chain.doFilter(request,response)方法,则请求就会通过过滤器到达要请求的资源,如果没有调用则不会到达资源。

image-20190621145639509

注意,如果两个过滤器同时过滤一个请求时谁先谁后呢?这就涉及到了过滤链 FilterChain。服务器会按照 web.xml 中过滤器定义的先后循序组装成一条链,然后依次执行其中的 doFilter()方法。如上图所示,两个过滤器执行的过程是:执行第一个过滤器的 chain.doFilter()之前的代码,第二个过滤器的 chain.doFilter()之前的代码,请求的资源,第二个过滤器的 chain.doFilter()之后的代码,第一个过滤器的 chain.doFilter()之后的代码,最后返回响应。

3、过滤器链

如果请求的资源与多个过滤器关联,这就会形成过滤器链

image-20190621145742715

4、实现

第一:定义一个类,此类必须要实现 Filter 接口

public class HelloFilter implements Filter {
	...
}

第二:重写 Filter 接口中的相关方法

public class HelloFilter implements Filter {

	public void destroy() {
   System.out.println("销毁...");
	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
   throws IOException, ServletException {

   System.out.println("请求...");
   chain.doFilter(request, response);	//放行
   System.out.println("响应...");
	}

	public void init(FilterConfig fConfig) throws ServletException {
   //可以通过FilterConfig对象获取初始化参数
   System.out.println("初始化...");
	}

}

第三:配置 web.xml 文件

<filter>
  <filter-name>过滤器名称</filter-name>
  <filter-class>过滤器包名.类名</filter-class>
  <!--初始化参数-->
  <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
  </init-param>
</filter>

<filter-mapping>
  <filter-name>过滤器名称</filter-name>
  <url-pattern>/过滤的URL地址</url-pattern>
</filter-mapping>

5、URL 配置

1)精确匹配
/admin/index.jsp 或 /admin/addUserServlet
2)路径匹配
/admin/*
3)扩展名匹配
 *.jsp

注:/admin/*.jsp 不支持,即是路径匹配也是扩展名匹配,导致容器无法判断,报错。

6、生命周期

7、三个接口

  • Filter

  • FilterConfig

  • FilterChain

8、案例

十、Servlet 注解实现

====================================

最详细的步骤 (结合JDBC,实现用户登录,注册,删除,查询,修改)

一、创建数据表(sql数据库)

二、创建项目 (Eclipse)

1、配置工作空间的编码 (Project--Properties--Resource--Other)

2、JDK

3、Tomcat (Window菜单 - Preferences - Server - Runtime Environments)

4、创建Dynamic Web Project ...( File - New - Project... - Web - Dynamic Web Project)

三、创建前端页面HTML(webapp)

1、登录(login)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户管理系统 - 用户登录</title>
</head>
<body>
	<form action="login.do" method="post">
		帐号:<input type="text" name="username" value="admin888"/><br/>
		密码:<input type="password" name="password" value="123456"/><br/>
		<input type="submit" value="登录"/>
		<!-- todo:使用样式修改按钮,并使用JS实现页面跳转到注册页面 -->
		<button type="button" onClick="goToPage('reg.html')">用户注册</button>
	</form>
	
	
	<script type="text/javascript" src="js/index.js"></script>
	
	
</body>
</html>
创建 js (使用样式修改按钮,并使用JS实现页面跳转到注册页面)
/**
	JS实现页面跳转
 */
function goToPage(page) {
	location.href = page ;
}

/**
	提示用户是否真的删除
 */
function isDel( userId ) {
	
	// confirm():弹出具有“确定”和“取消”按钮的对话框
	// 点击“确定”返回True,反之返回False
	if(window.confirm("您真的要删除此用户码?")) {
		goToPage("del.do?userId=" + userId) ;
		alert("删除成功!")
	}
	
}

2、登录成功(login-success)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录成功</title>
</head>
<body>
	<h1>登录成功,欢迎Xxx先生/小姐!退出登录</h1>
	<hr/>
	
	<table border="1" align="center" width="80%">
		<tr>
			<th>帐号</th>
			<th>电话</th>
			<th>性别</th>
			<th>体重</th>
			<th>出生</th>
			<th>爱好</th>
			<th>操作</th>
		</tr>
		
		<tr align="center">
			<td>张三</td>
			<td>110</td>
			<td>男</td>
			<td>160</td>
			<td>1995-05-02</td>
			<td>吃,喝</td>
			<td><a href="show.html">查看</a> | 删除</td>
		</tr>
		
		<tr align="center">
			<td>李四</td>
			<td>120</td>
			<td>女</td>
			<td>60</td>
			<td>1998-05-02</td>
			<td>玩,乐</td>
			<td><a href="show.html">查看</a> | 删除</td>
		</tr>
		
		<tr align="center">
			<td>王五</td>
			<td>120</td>
			<td>男</td>
			<td>180</td>
			<td>1997-05-02</td>
			<td>吃,玩</td>
			<td><a href="show.html">查看</a> | 删除</td>
		</tr>
	</table>
</body>
</html>

3、登录失败(login-error)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录失败</title>
</head>
<body>
	<h1>错误的帐号或密码,登录失败!
		请重新<a href="index.html">登录</a>或
		<a href="reg.html">注册</a>
	</h1>
</body>
</html>

4、查看(show)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>查看用户</title>
</head>
<body>
	<h1>查看用户<span style="color:red;font-weight:bold">李四</span>明细</h1>
	<hr/>
	<form>
		帐号:<input type="text" value="李四"/><br/>
		电话:<input type="text" value="120"/><br/>
		性别:
			<input type="radio" name="sex" value="男"/>男
			<input type="radio" name="sex" value="女" checked/>女
		<br/>
		体重:<input type="text" value="60"/><br/>
		出生:<input type="text" value="1998-05-02"/><br/>
		爱好:
			<input type="checkbox" name="hobby" value="吃"/>吃
			<input type="checkbox" name="hobby" value="喝"/>喝
			<input type="checkbox" name="hobby" value="玩" checked/>玩
			<input type="checkbox" name="hobby" value="乐" checked/>乐
			<br/>
		<input type="submit" value="修改"/>
		<input type="button" value="返回"/><br/>
	</form>
</body>
</html>

5、注册(register)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户注册</title>
</head>
<body>
	<h1>用户注册</h1>
	<hr/>
	<form action="register.do" method="post">
		帐号:<input type="text" name="username"/><br/>
		密码:<input type="password" name="password"/><br/>
		电话:<input type="text" name="tel"/><br/>
		性别:
			<input type="radio" name="sex" value="男" id="man" checked/>
			<label for="man">男</label>
			
			<input type="radio" name="sex" value="女" id="woman"/>
			<label for="woman">女</label>
		<br/>
		体重:<input type="text" name="weight"/><br/>
		出生:<input type="text" name="birth"/><br/>
		爱好:
			<input type="checkbox" name="hobby" value="吃" id="eat"/>
			<label for="eat">吃</label>
			
			<input type="checkbox" name="hobby" value="喝" id="drink"/>
			<label for="drink">喝</label>
			
			<input type="checkbox" name="hobby" value="玩" id="play"/>
			<label for="play">玩</label>
			
			<input type="checkbox" name="hobby" value="乐" id="happy"/>
			<label for="happy">乐</label>
			<br/>
		<input type="submit" value="注册"/><br/>
	</form>
</body>
</html>

6、修改失败(update-error)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>修改失败</title>
</head>
<body>
	<h1>修改用户失败,<a href='welcome.do'>返回</a></h1>
</body>
</html>

四、编写后台JAVA代码 (src/main/java)

com|org.公司名称.组织名称.项目名称.模块名称.Xxxx.java

1、工具包(utils)(固定的,一定要记住)-(注意:要把连接驱动jar包(jtds-1.3.1.jar),添加到项目的lib目录 ==步骤:右击Deployment Descriptor:项目名 -- Generate Deployment Descriptor Stub)

连接数据库

package org.nf.s186.ums.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 连接数据库
 * 注意:要把连接驱动jar包(jtds-1.3.1.jar),添加到项目的lib目录
 * @author zhang
 *
 */
public class DBUtil {
	/**
	 * 连接驱动程序
	 */
	private  static final String DRIVER = "net.sourceforge.jtds.jdbc.Driver" ;
	/**
	 * 连接URL
	 */
	private  static final String URL = "jdbc:jtds:sqlserver://localhost:1433;DatabaseName=ums" ;
	/**
	 * 帐号
	 */
	private  static final String USER = "sa" ;
	/**
	 * 密码
	 */
	private  static final String PASS = "mm1306612" ;
	
	
	
	static {
		// 加载驱动程序
		try {
			Class.forName(DRIVER);
		} catch (ClassNotFoundException e) {
			System.out.println("加载驱动程序失败...");
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取连接对象 -- Java程序 与 数据库之间的桥梁
	 * @return
	 */
	public static Connection getConnection() {
		Connection conn = null ;
		try {
			conn = DriverManager.getConnection(URL, USER, PASS);
		} catch (SQLException e) {
			System.out.println("获取连接对象失败...");
			e.printStackTrace();
		}
		return conn ;
	}
	
	/**
	 * 关闭相关的 JDBC 对象
	 *  DriverManager:驱动管理对象,获取连接对象
	 *  		DriverManager.getConnection(URL, USER, PASS);
	 *  
	 * 	ResultSet:结果集对象
	 * 			用于接收查询数据时,返回的结果
	 * 
	 *  Statement:语句对象 用数据库(sql)的
	 *  		用于执行SQL语句(PreparedStatement、CallableStatement)
	 *  			增、删、改:executeUpdate()
	 *  			查询:executeQuery()
	 *  		
	 *  
	 *  Connection:连接对象
	 *  		建立JAVA程序与数据库之间的桥梁
	 * 
	 * @param rst 
	 * @param stmt 
	 * @param conn 
	 */
	public static void close(ResultSet rst,Statement stmt,Connection conn) {
		if(rst!=null) {
			try {
				rst.close() ;
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		
		if(stmt!=null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		if(conn!=null) {
			try {
				conn.close() ;
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	// executeUpdate()、executeQuery() - 略 
	public static void main(String[] args) {
		System.out.println(DBUtil.getConnection());
	}
}

日期时间处理工具类

package org.nf.s186.ums.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;

/**
 * 日期时间处理工具类
 * @author Administrator
 *
 */
public class DateUtil {
	
	/**
	 * 内置常用日期模式 -- 只包含日期
	 */
	public static final String DATA_PATTERN = "yyyy-MM-dd" ;
	
	/**
	 * 内置常用日期模式 -- 只包含日间
	 */
	public static final String TIME_PATTERN = "hh:mm:ss" ;
	
	/**
	 * 内置常用日期模式 -- 同时包含日期和时间
	 */
	public static final String DATATIME_PATTERN = "yyyy-MM-dd hh:mm:ss" ;
	
	
	/**
	 * 把"指定格式"的字符串类型的日期 转换为 java.util.Date类型的日期 
	 * 使用SimpleDateFormat进行转换
	 * yyyy-MM-dd hh:mm:ss
	 * @param strDate
	 * @return
	 */
	public static java.util.Date stringToDate(String strDate,String pattern) {
		// 实例化SimpleDateFormat对象的同时,指定时间格式
		SimpleDateFormat format = new SimpleDateFormat(pattern) ;
		java.util.Date date = null ;
		try {
			date = format.parse(strDate);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return date ;
	}
}


2.实体包(entity、domain)

package org.nf.s186.ums.entity;

import java.util.Date;

/**
 * 实体对象 - 用户对象 - 用于封装数据、传递数据
 * 
 * 一般有多个数据表,就有多少个实体对象 
 * 	1)表中的字段就是实体对象的属性 
 *  2)对象的属性一般要私有化,且生成相关的setter/getter方法
 * 	3)根据需要,可以定义重载构造方法,而默认的构造方法一般要显示写出来
 * 
 * 命名规范: 属性名首字母小写 驼峰标识 命名有意义
 * 
 * @author zhang
 *
 */
public class UserInfo {
    //字段
	private int id;
	private String username;
	private String password;
	private String tel;
	private String sex;
	private double weight;
	private Date birth;
	private String hobby;
	private Date regTime;
	
    //属性
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public double getWeight() {
		return weight;
	}
	public void setWeight(double weight) {
		this.weight = weight;
	}
	public Date getBirth() {
		return birth;
	}
	public void setBirth(Date birth) {
		this.birth = birth;
	}
	public String getHobby() {
		return hobby;
	}
	public void setHobby(String hobby) {
		this.hobby = hobby;
	}
	public Date getRegTime() {
		return regTime;
	}
	public void setRegTime(Date regTime) {
		this.regTime = regTime;
	}
	/**
	 * 默认(缺省)构造方法
	 * 
	 * 注意:当重载构造方法后,缺省构造方法就会被丢失
	 * 因此,一般我们会手动补回来
	 */
	public UserInfo() {}
	/**
	 * 重载构造方法 - 便于初始化对象 - 帐号、密码、手机号码
	 * @param username
	 * @param password
	 * @param tel
	 */
	public UserInfo(String username, String password, String tel) {
		this.username = username;
		this.password = password;
		this.tel = tel;
	}
	
	
}


3.数据访问对象包(dao)

1)DAO接口

package org.nf.s186.ums.dao;

import java.util.List;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 定义 用户信息表(用户对象) 的相关数据操作接口
 * 
 * 接口定义了相关的标准、规范,用于指定对象能做什么事情,
 * 		具体什么行为,但没有具体的实现。
 * 		具体的实现根据实际情况,定义相关的实现类实现(多态)。
 * 
 * 便于程序的扩展和维护
 * 	
 * 
 * DAO:数据访问对象(Data Access Object),
 * 		数据相关操作的对象,一般服务于业务对象,不包含相关的业务操作,只是单纯的实现数据操作(CRUD)
 * 		如果有相关业务就提取到业务对象实现;
 * 		如果没有相关业务代码或简单的业务可以直接在Servlet实现,而不需要业务对象
 * 
 * @author Administrator
 *
 */
public interface UserInfoDao {
	/**
	 * 根据帐号和密码查询用户,服务于登录业务
	 * @param username
	 * @param password
	 * @return
	 */
	public UserInfo queryUser(String username,String password) ;
	
	
	// 增、删、改、各种查询...
	/**
	 * 添加用户信息 
	 * @param userinfo 实体对象(用户的相关信息封装)
	 * @return 受影响行数
	 */
	public int insertUser(UserInfo userinfo) ;
	
	/**
	 * 根据用户编号删除数据
	 * @param id 用户编号
	 * @return 受影响行数
	 */
	public int deleteUser(int id) ;
	
	/**
	 * 修改用户
	 * @param userinfo 实体对象
	 * @return 受影响行数
	 */
	public int updateUser(UserInfo userinfo) ;
	
	/**
	 * 查询所有用户信息,除了当前登录用户,避免自己把自己删除了
	 * @param id
	 * @return
	 */
	public List<UserInfo> queryUserList(int id) ;
	
	
	
	/**
	 * 根据用户ID查询用户信息 - 服务于查看用户详情
	 * @param id
	 * @return
	 */
	public UserInfo queryUserById(int id) ;
	
	
}


2)DAO接口实现

package org.nf.s186.ums.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DBUtil;

/**
 * UserDao接口的实现类
 * 
 * 根据需要,可以定义多个DAO接口的实现类,从而解决不同需求的情况
 * 
 * 
 * @author Administrator
 *
 */
public class UserInfoDaoImpl implements UserInfoDao {

	@Override
	public UserInfo queryUser(String username, String password) {

		UserInfo user = null;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "select * from userinfo where username=? and password=?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();

		// 第三:获取语句对象
		PreparedStatement stmt = null;
		ResultSet rst = null;

		try {
			// 1.预编译SQL语句
			stmt = conn.prepareStatement(sql);
			// 2.填充数据
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			stmt.setString(1, username);
			stmt.setString(2, password);

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			rst = stmt.executeQuery();

			// 第五:处理SQL语句返回的结果
			if (rst.next()) {
				// 1.实例化对象
				user = new UserInfo();

				// 2.读取各个字段的数据
				// 语法如下:
				// 1)结果集对象.getXxx(字段索引)
				// 2)结果集对象.getXxx(字段列名)
				int userId = rst.getInt(1);
				String name = rst.getString(2);
				String tel = rst.getString(4);
				String sex = rst.getString(5);
				double weight = rst.getDouble(6);
				java.sql.Date birth = rst.getDate(7);
				String hobby = rst.getString(8);
				java.sql.Timestamp regTime = rst.getTimestamp(9);

				// 3.封装数据
				user.setId(userId);
				user.setUsername(name);
				user.setTel(tel);
				user.setSex(sex);
				user.setWeight(weight);
				user.setBirth(birth);
				user.setHobby(hobby);
				user.setRegTime(regTime);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(rst, stmt, conn);
		}

		return user;
	}

	@Override
	public int insertUser(UserInfo userinfo) {
		int row = 0;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "insert into userinfo(username,password,tel,sex,weight,birth,hobby) values (?,?,?,?,?,?,?)";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();
		PreparedStatement pstmt = null;

		try {
			// 第三:获取语句对象
			// 1.预编译SQL语句
			pstmt = conn.prepareStatement(sql);
			// 2.填充数据 - 把SQL语句补充完整
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			pstmt.setString(1, userinfo.getUsername());
			pstmt.setString(2, userinfo.getPassword());
			pstmt.setString(3, userinfo.getTel());
			pstmt.setString(4, userinfo.getSex());
			pstmt.setDouble(5, userinfo.getWeight());

			// 获取出生日期的毫秒数
			long longBirth = userinfo.getBirth().getTime();
			// 把java.util.Date转换为java.sql.Date
			java.sql.Date birth = new java.sql.Date(longBirth);

			pstmt.setDate(6, birth);
			pstmt.setString(7, userinfo.getHobby());

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			row = pstmt.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(null, pstmt, conn);
		}

		// 第五:处理SQL语句返回的结果
		return row;
	}

	@Override
	public int deleteUser(int id) {
		int row = 0;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "delete from userinfo where id=?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();
		PreparedStatement pstmt = null;

		try {
			// 第三:获取语句对象
			// 1.预编译SQL语句
			pstmt = conn.prepareStatement(sql);
			// 2.填充数据 - 把SQL语句补充完整
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			pstmt.setInt(1, id);
	

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			row = pstmt.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(null, pstmt, conn);
		}

		// 第五:处理SQL语句返回的结果
		return row;
	}

	@Override
	public int updateUser(UserInfo userinfo) {
		int row = 0;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "update userinfo set username=?,tel=?,sex=?,weight=?,birth=?,hobby=? where id=?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();
		PreparedStatement pstmt = null;

		try {
			// 第三:获取语句对象
			// 1.预编译SQL语句
			pstmt = conn.prepareStatement(sql);
			// 2.填充数据 - 把SQL语句补充完整
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			pstmt.setString(1, userinfo.getUsername());
			pstmt.setString(2, userinfo.getTel());
			pstmt.setString(3, userinfo.getSex());
			pstmt.setDouble(4, userinfo.getWeight());


			// 获取出生日期的毫秒数
			long longBirth = userinfo.getBirth().getTime();
			// 把java.util.Date转换为java.sql.Date
			java.sql.Date birth = new java.sql.Date(longBirth);

			pstmt.setDate(5, birth);
			pstmt.setString(6, userinfo.getHobby());
			pstmt.setInt(7, userinfo.getId());

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			row = pstmt.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(null, pstmt, conn);
		}

		// 第五:处理SQL语句返回的结果
		return row;
	}

	@Override
	public List<UserInfo> queryUserList(int id) {
		List<UserInfo> list = new ArrayList<>();

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "select * from userinfo where id != ?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();

		// 第三:获取语句对象
		PreparedStatement stmt = null;
		ResultSet rst = null;

		try {
			// 1.预编译SQL语句
			stmt = conn.prepareStatement(sql);
			// 2.填充数据
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			stmt.setInt(1, id);

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			rst = stmt.executeQuery();

			// 第五:处理SQL语句返回的结果
			while (rst.next()) {
				// 1.实例化对象
				UserInfo user = new UserInfo();

				// 2.读取各个字段的数据
				// 语法如下:
				// 1)结果集对象.getXxx(字段索引)
				// 2)结果集对象.getXxx(字段列名)
				int userId = rst.getInt(1);
				String name = rst.getString(2);
				String tel = rst.getString(4);
				String sex = rst.getString(5);
				double weight = rst.getDouble(6);
				java.sql.Date birth = rst.getDate(7);
				String hobby = rst.getString(8);
				java.sql.Timestamp regTime = rst.getTimestamp(9);

				// 3.封装数据
				user.setId(userId);
				user.setUsername(name);
				user.setTel(tel);
				user.setSex(sex);
				user.setWeight(weight);
				user.setBirth(birth);
				user.setHobby(hobby);
				user.setRegTime(regTime);

				// 4.把实体对象封装到List集合中
				list.add(user);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(rst, stmt, conn);
		}

		return list;
	}

	@Override
	public UserInfo queryUserById(int id) {
		UserInfo user = null;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "select * from userinfo where id=?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();

		// 第三:获取语句对象
		PreparedStatement stmt = null;
		ResultSet rst = null;

		try {
			// 1.预编译SQL语句
			stmt = conn.prepareStatement(sql);
			// 2.填充数据
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			stmt.setInt(1, id);


			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			rst = stmt.executeQuery();

			// 第五:处理SQL语句返回的结果
			if (rst.next()) {
				// 1.实例化对象
				user = new UserInfo();

				// 2.读取各个字段的数据
				// 语法如下:
				// 1)结果集对象.getXxx(字段索引)
				// 2)结果集对象.getXxx(字段列名)
				int userId = rst.getInt(1);
				String name = rst.getString(2);
				String tel = rst.getString(4);
				String sex = rst.getString(5);
				double weight = rst.getDouble(6);
				java.sql.Date birth = rst.getDate(7);
				String hobby = rst.getString(8);
				java.sql.Timestamp regTime = rst.getTimestamp(9);

				// 3.封装数据
				user.setId(userId);
				user.setUsername(name);
				user.setTel(tel);
				user.setSex(sex);
				user.setWeight(weight);
				user.setBirth(birth);
				user.setHobby(hobby);
				user.setRegTime(regTime);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(rst, stmt, conn);
		}

		return user;
	}

}


4.业务包(service)

1)Service接口

package org.nf.s186.ums.service;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 业务接口
 * 	如果业务单一或在确定的情况下,可以不需要定义接口
 * 	或者也可以根据实际情况,后期根据需求,重构代码再定义此接口
 * 
 * @author Administrator
 *
 */
public interface UserInfoService {
	/**
	 * 登录
	 * @param username
	 * @param password
	 * @return
	 */
	public UserInfo login(String username,String password) ;
	
	
	/**
	 * 注册
	 * @param user
	 * @return
	 */
	public int register(UserInfo user) ;
}


2)Service接口实现

package org.nf.s186.ums.service.impl;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;

public class UserInfoServiceImpl implements UserInfoService {

	@Override
	public UserInfo login(String username, String password) {
		// 第一:实例化DAO对象
		UserInfoDao userInfoDao = new UserInfoDaoImpl();

		// 第二:查询数据
		UserInfo userInfo = userInfoDao.queryUser(username, password);

		// 第三:返回结果
		return userInfo;
	}

	@Override
	public int register(UserInfo user) {
		UserInfoDao userInfoDao = new UserInfoDaoImpl();
		return userInfoDao.insertUser(user);
	}

}


5.Servlet包(servlet、controller、web)

1、登录
package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;
import org.nf.s186.ums.service.impl.UserInfoServiceImpl;

/**
 * 处理登录的服务器程序
 * @author Administrator
 *
 */
public class LoginServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		resp.setContentType("text/html;charset=utf-8");
		resp.setCharacterEncoding("utf-8") ;
		PrintWriter out = resp.getWriter() ;
		
		// 第一:获取用户输入的数据
		String username = req.getParameter("username");
		String password = req.getParameter("password");
		
		// 对数据进行合法性验证
		if(username==null || "".equals(username.trim())) {
			out.print("用户名不能为空,<a href='index.html'>返回</a>") ;
			out.flush();
			out.close();
			return ;
		}
		
		if(password==null || "".equals(password.trim())) {
			out.print("密码不能为空,<a href='index.html'>返回</a>") ;
			out.flush();
			out.close();
			return ;
		}
		
		// 第二:实例化业务对象
		UserInfoService userInfoService = new UserInfoServiceImpl() ;
		
		// 第三:处理
		UserInfo userInfo = userInfoService.login(username, password);
		
		// 第四:响应
		// 登录失败,默认跳转的页面
		String path = "error.html" ;
		
		// 登录成功
		if(userInfo!=null) {
			// 1.把登录帐号,存储在请求作用域中,便于数据传递 
			// 注意:在实际开发中,我们把帐号存储在会话作用域中
			// req.setAttribute("loginUser", userInfo);
			// req.getSession().setAttribute("loginUser", userInfo);
			
			HttpSession session = req.getSession() ;
			session.setAttribute("loginUser", userInfo);
			
			// 2.设置登录成功,跳转的页面
			path = "welcome.do" ;
		}
		
		// 1.页面跳转 -- 重定向
		resp.sendRedirect(path);
		
		// 2.页面跳转 -- 转发
		// req.getRequestDispatcher(path).forward(req, resp);
		
		
		
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.doPost(req, resp);
	}
}


2、登录成功
package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;

/**
 * 后面首页
 * 
 * @author Administrator
 *
 */
public class WelcomeServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		// 设置响应编码
		resp.setContentType("text/html;charset=utf-8");
		resp.setCharacterEncoding("utf-8") ;
		
		// 获取打印输出流对象
		PrintWriter out = resp.getWriter() ;
		
		// 获取请求作用域传递过来的数据
		// UserInfo userInfo = (UserInfo)req.getSession().getAttribute("loginUser");
		HttpSession session = req.getSession() ;
		UserInfo userInfo = (UserInfo)session.getAttribute("loginUser");
		
		
		// 判断在会话中是否存在登录的用户 -- 防止用法在没有登录的情况下,访问服务器资源
		if(userInfo==null) {
			out.print("对不起,你没有权限!请<a href='index.html'>登录</a>") ;
			out.flush();
			out.close();
			return ;
		}
		
		String msg = "欢迎" + userInfo.getUsername()  + ("男".equals(userInfo.getSex()) ? "先生" : "女士") ;
		
		out.print("<!DOCTYPE html>") ;
		out.print("<html>") ;
		out.print("<head>") ;
		out.print("<meta charset='UTF-8'>") ;
		out.print("<title>登录成功</title>") ;
		
		out.print("<script type='text/javascript' src='js/index.js'></script>") ;
		
		out.print("</head>") ;
		out.print("<body>") ;
		out.print("<h1>用户信息管理系统</h1>") ;
		out.print("<h3>" + msg + "</h3>") ;
		out.print("<h3><a href='logout.do'>退出登录</a></h3>") ;
		out.print("<hr/>") ;
		
		out.print("<table border='1' align='center' width='80%'>") ;
		out.print("<tr>") ;
		out.print("<th>帐号</th>") ;
		out.print("<th>电话</th>") ;
		out.print("<th>性别</th>") ;
		out.print("<th>体重</th>") ;
		out.print("<th>出生</th>") ;
		out.print("<th>爱好</th>") ;
		out.print("<th>操作</th>") ;
		out.print("</tr>") ;
		
		UserInfoDao dao = new UserInfoDaoImpl() ;
		List<UserInfo> list = dao.queryUserList(userInfo.getId()) ;
		
		// 如果集合没有数据,则显示“数据为空!”
		if(list==null || list.size()==0) {
			out.print("<tr align='center'>") ;
			out.print("<td colspan='7'>");
			out.print("<span style='color:red'>数据为空!</span>") ;
			out.print("</td>") ;
			out.print("</tr>");
		} else {
			// 如果集合有数据,则循环遍历出来 
			for(UserInfo u : list) {
				out.print("<tr align='center'>") ;
				out.print("<td>"+u.getUsername()+"</td>") ;
				out.print("<td>"+u.getTel()+"</td>") ;
				out.print("<td>"+u.getSex()+"</td>") ;
				out.print("<td>"+u.getWeight()+"</td>") ;
				out.print("<td>"+u.getBirth()+"</td>") ;
				out.print("<td>"+u.getHobby()+"</td>") ;
				// URL重写传参
				out.print("<td><a href='show.do?userId="+u.getId()+"'>查看</a> | <a href='#' onclick='isDel("+u.getId()+")'>删除</a></td>") ;
				out.print("</tr>") ;
			}
		}
		
		out.print("</table>") ;
		out.print("</body>") ;
		out.print("</html>") ;
		
		// 关闭对象
		out.flush();
		out.close();
	}
	
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.doPost(req, resp);
	}
}


3、退出登录
package org.nf.s186.ums.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * 实现退出登录(注销帐号)
 * @author Administrator
 *
 */
public class LogoutServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;


	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// req.getSession().invalidate();
		// 1.获取会话对象的实例
		HttpSession session = req.getSession() ;
		
		// 2.让会话失效 -- 会话对象存储的用户信息也就没有了
		session.invalidate(); 
		
		// 3.重定向到登录页面
		resp.sendRedirect("index.html");
	}
}


4、查看
package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;

/**
 * 根据用户编号,查看用户详情
 * @author zing
 *
 */
public class ShowUserServlet extends HttpServlet{

	private static final long serialVersionUID = 1L;

	@Override 
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		// 设置响应编码
		resp.setContentType("text/html;charset=utf-8");
		resp.setCharacterEncoding("utf-8") ;
		
		// 获取打印输出流对象
		PrintWriter out = resp.getWriter() ;
		
		
		HttpSession session = req.getSession() ;
		UserInfo userInfo = (UserInfo)session.getAttribute("loginUser");
		// 判断在会话中是否存在登录的用户 -- 防止用法在没有登录的情况下,访问服务器资源
		if(userInfo==null) {
			out.print("对不起,你没有权限!请<a href='index.html'>登录</a>") ;
			out.flush();
			out.close();
			return ;
		}
		
		
		
		// 获取请求参数 - 用户ID
		String userId = req.getParameter("userId") ;
		
		// 对获取数据进行合法性验证 -- 正则表达式 
		String reg = "\\d{1,}" ;
		
		boolean isOk = userId.matches(reg) ;
		if(!isOk) {
			out.print("<h1>非法操作,您传递的参数 " + userId + " 有误</h1>") ;
			out.append("<a href='welcome.do'>返回</a>") ;
			// 返回,程序不往下执行
			return ;
		} 
		
		
		// 必须保证 userId 这个字符串是一个合法的"数值"字符串,如:"123"
		int id = Integer.parseInt(userId) ;
		
		// 实例化DAO对象
		UserInfoDao userInfoDao = new UserInfoDaoImpl() ;
		
		// 根据用户ID查询用户的明细
		UserInfo u = userInfoDao.queryUserById(id);
		
		
		out.print("<!DOCTYPE html>") ;
		out.print("<html>") ;
		out.print("<head>") ;
		out.print("<meta charset='UTF-8'>") ;
		out.print("<title>查看用户</title>") ;
		out.print("</head>") ;
		out.print("<body>") ;
		out.print("<h1>查看用户<span style='color:red;font-weight:bold'>"+u.getUsername()+"</span>明细</h1>") ;
		out.print("<hr/>") ;
		out.print("<form action='user/update.do' method='post'>") ;
		out.print("帐号:<input type='text' name='username' value='"+u.getUsername()+"'/><br/>") ;
		
		// 注意:表单隐藏域 - “悄悄地”把数据传递给服务器
		out.print("<input type='hidden' name='userId' value='"+u.getId()+"'/>") ;
		out.print("电话:<input type='text' name='tel' value='"+u.getTel()+"'/><br/>") ;
		out.print("性别:") ;
		out.print("<input type='radio' name='sex' value='男' "+ ("男".equals(u.getSex())?"checked":"") +"/>男") ;
		out.print("<input type='radio' name='sex' value='女' "+ ("女".equals(u.getSex())?"checked":"") +"/>女") ;
		out.print("<br/>") ;
		out.print("体重:<input type='text' name='weight' value='"+u.getWeight()+"'/><br/>") ;
		out.print("出生:<input type='text' name='birth' value='"+u.getBirth()+"'/><br/>") ;
		out.print("爱好:") ;

		out.print("<input type='checkbox' name='hobby' value='吃' "+ (u.getHobby().contains("吃")?"checked":"") +"/>吃") ;
		out.print("<input type='checkbox' name='hobby' value='喝' "+ (u.getHobby().contains("喝")?"checked":"") +"/>喝") ;
		out.print("<input type='checkbox' name='hobby' value='玩' " + (u.getHobby().contains("玩")?"checked":"") + "/>玩") ;
		out.print("<input type='checkbox' name='hobby' value='乐' "+ (u.getHobby().contains("乐")?"checked":"") +"/>乐") ;
		out.print("<br/>") ;
		out.print("<input type='submit' value='修改'/>") ;
		out.print("<input type='button' value='返回'/><br/>") ;
		out.print("</form>") ;
		out.print("</body>") ;
		out.print("</html>") ;
		
		
		
		
		// 关闭对象
		out.flush();
		out.close();
	}
}


5、注册
package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.util.Arrays;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;
import org.nf.s186.ums.service.impl.UserInfoServiceImpl;
import org.nf.s186.ums.utils.DateUtil;

/**
 * 处理注册请求
 * @author Administrator
 *
 */
public class RegisterServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 第一:设置请求编码
		req.setCharacterEncoding("UTF-8");
		
	
		
		// 第二:获取客户端传递的数据
		String username = req.getParameter("username") ;
		String password = req.getParameter("password") ;
		String sex = req.getParameter("sex") ;
		String tel = req.getParameter("tel") ;
		String weight = req.getParameter("weight") ;
		String birth = req.getParameter("birth") ;
		String[] hobby = req.getParameterValues("hobby") ;
		
		// 第三:对传递的数据进行合法性验证(服务器验证),保证数据的合法性(安全) -- 正则表达式
		double doubleWeight = Double.parseDouble(weight);
		
		// 第四:加工处理数据(结合业务需求)
		// 1.实例化业务对象
		UserInfoService userService = new UserInfoServiceImpl() ;
		
		// 2.实例化实体对象,并初始化表单传递过来的数据
		UserInfo u = new UserInfo() ;
		
		// 3.初始化实体对象
		u.setUsername(username);
		u.setPassword(password);
		u.setSex(sex);
		u.setTel(tel);
		u.setWeight(doubleWeight);
		u.setBirth(DateUtil.stringToDate(birth, DateUtil.DATA_PATTERN));
		u.setHobby(Arrays.toString(hobby));
		
		// 4.业务处理 - 注册 
		int r = userService.register(u) ;
		
		// 第五:响应结果(打印输出或页面跳转[重定向、转发])
		String path = "index.html";
		if(r!=1) {
			path = "reg.html" ;
		} 
		resp.sendRedirect(path);
	}
}


6、修改
package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DateUtil;

/**
 * 修改用户信息
 * 
 * @author zing
 *
 */
public class UpdateUserServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 第一:设置请求编码
		req.setCharacterEncoding("UTF-8");
		
		// 设置响应编码
		resp.setContentType("text/html;charset=utf-8");
		resp.setCharacterEncoding("utf-8");
		// 获取打印输出流对象
		PrintWriter out = resp.getWriter();

		
		// 注意:每个一个后台程序都要编写以下代码,实现用户权限认证 -- 不利于程序维护 -- 解决:过滤器
		HttpSession session = req.getSession();
		UserInfo userInfo = (UserInfo) session.getAttribute("loginUser");
		// 判断在会话中是否存在登录的用户 -- 防止用法在没有登录的情况下,访问服务器资源
		if (userInfo == null) {
			out.print("对不起,你没有权限!请<a href='index.html'>登录</a>");
			out.flush();
			out.close();
			return;
		}

		// 第二:获取客户端传递的数据
		String username = req.getParameter("username");
		String userId = req.getParameter("userId");
		String sex = req.getParameter("sex");
		String tel = req.getParameter("tel");
		String weight = req.getParameter("weight");
		String birth = req.getParameter("birth");
		String[] hobby = req.getParameterValues("hobby");

		// 第三:对传递的数据进行合法性验证(服务器验证),保证数据的合法性(安全) -- 正则表达式
		double doubleWeight = Double.parseDouble(weight);
		int id = Integer.parseInt(userId);

		// 第四:加工处理数据(结合业务需求)
		// 1.实例化业务对象
		// UserInfoService userService = new UserInfoServiceImpl() ;
		UserInfoDao userInfoDao = new UserInfoDaoImpl();

		// 2.实例化实体对象,并初始化表单传递过来的数据
		UserInfo u = new UserInfo();

		// 3.初始化实体对象
		u.setId(id);
		u.setUsername(username);
		u.setSex(sex);
		u.setTel(tel);
		u.setWeight(doubleWeight);
		u.setBirth(DateUtil.stringToDate(birth, DateUtil.DATA_PATTERN));
		u.setHobby(Arrays.toString(hobby));

		// 4.业务处理 - 注册
		// int r = userService.register(u) ;
		int r = userInfoDao.updateUser(u);

		// 第五:响应结果(打印输出或页面跳转[重定向、转发])
		String path = "../welcome.do";

		if (r != 1) {
			path = "../update-error.html";
		}

		resp.sendRedirect(path);
	}
}


7、删除
package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;

/**
 * 删除用户
 * @author zhang
 *
 */
public class DeleteUserServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		resp.setContentType("text/html;charset=utf-8");
		resp.setCharacterEncoding("utf-8");
		
		PrintWriter out = resp.getWriter() ;
		
		
		HttpSession session = req.getSession() ;
		UserInfo userInfo = (UserInfo)session.getAttribute("loginUser");
		// 判断在会话中是否存在登录的用户 -- 防止用法在没有登录的情况下,访问服务器资源
		if(userInfo==null) {
			out.print("对不起,你没有权限!请<a href='index.html'>登录</a>") ;
			out.flush();
			out.close();
			return ;
		}
		
		
		// 第一:获取用户输入的数据
		String userId = req.getParameter("userId");
		
		// 对输入的数据进行合法性验证
		String reg = "\\d{1,}" ;
		boolean isOk = userId.matches(reg) ;
		
		if(!isOk) {
			// 注意:也可以通过页面跳转实现错误提示
			out.print("非法操作,您传递的参数["+userId+"]非法") ;
			out.print("<a href='welcome.do'>返回</a>") ;
			return ;
		}
		
		int id = Integer.parseInt(userId) ;
	
		// 第二:实例化业务对象
		// 第三:处理
		UserInfoDao userInfoDao = new UserInfoDaoImpl();
		int row = userInfoDao.deleteUser(id) ;

		// 第四:响应
		if(row != 1) {
			// 注意:也可以通过页面跳转实现错误提示
			out.print("对不起,删除用户失败!") ;
			out.print("<a href='welcome.do'>返回</a>") ;
			return ;
		}
	
		resp.sendRedirect("welcome.do") ;
	
	}
}


配置web.xml文件,对外提供一个访问URL

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
  <display-name>login-jdbc-demo</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  
  <!-- 登录  -->
  <servlet>
  	<servlet-name>LoginServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.LoginServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>LoginServlet</servlet-name>
  	<url-pattern>/login.do</url-pattern>
  </servlet-mapping>
  
  <!-- 退出登录  -->
  <servlet>
  	<servlet-name>LogoutServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.LogoutServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>LogoutServlet</servlet-name>
  	<url-pattern>/logout.do</url-pattern>
  </servlet-mapping>
  
  <!-- 注册  -->
  <servlet>
  	<servlet-name>RegisterServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.RegisterServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>RegisterServlet</servlet-name>
  	<url-pattern>/register.do</url-pattern>
  </servlet-mapping>
  
  
  <!-- 欢迎  -->
  <servlet>
  	<servlet-name>WelcomeServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.WelcomeServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>WelcomeServlet</servlet-name>
  	<url-pattern>/welcome.do</url-pattern>
  </servlet-mapping>
  
  <!-- 查看用户明细  -->
  <servlet>
  	<servlet-name>ShowUserServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.ShowUserServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>ShowUserServlet</servlet-name>
  	<url-pattern>/show.do</url-pattern>
  </servlet-mapping>
  
  <!-- 修改用户  -->
  <servlet>
  	<servlet-name>UpdateUserServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.UpdateUserServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>UpdateUserServlet</servlet-name>
  	<url-pattern>/user/update.do</url-pattern>
  </servlet-mapping>
  
   <!-- 修改用户  -->
  <servlet>
  	<servlet-name>DeleteUserServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.DeleteUserServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>DeleteUserServlet</servlet-name>
  	<url-pattern>/del.do</url-pattern>
  </servlet-mapping>
  
</web-app>

6.测试、运行(test)---只是检验可有可无

1、登录

package org.nf.s186.ums.test;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;

public class MainTest {

	public static void main(String[] args) {
		// 第一:定义帐号密码(模拟用户输入 )
		String username = "shangli" ;
		String password = "123456" ;
		
		// 第二:定义DAO对象,查询数据
		UserInfoDao userInfoDao = new UserInfoDaoImpl() ;
		
		// 第三:调用方法
		UserInfo user = userInfoDao.queryUser(username, password);
		
		// 第四:判断是否登录成功
		if(user==null) {
			System.out.println("登录失败");
		} else {
			System.out.println("恭喜"+user.getUsername()+",登录成功");
		}		
		
	}

}


2、注册

package org.nf.s186.ums.test;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DateUtil;

public class MainTest01 {

	public static void main(String[] args) {
		// 1.实例DAO对象
		UserInfoDao userInfoDao = new UserInfoDaoImpl() ;
		
		// 2.实例化实体对象
		UserInfo userInfo = new UserInfo() ;
		
		// 3.初始化实体对象
		userInfo.setUsername("Lily888");
		userInfo.setPassword("888888");
		userInfo.setHobby("吃,玩");
		userInfo.setSex("女");
		userInfo.setTel("111111111");
		userInfo.setWeight(50);
		userInfo.setBirth(DateUtil.stringToDate("1999-05-09", DateUtil.DATA_PATTERN));
		
		// 4.执行SQL语句
		int r = userInfoDao.insertUser(userInfo);
		
		// 5.处理结果
		if(r==1) {
			System.out.println("注册成功");
		} else {
			System.out.println("注册失败");
		}

	}

}


3、日期

package org.nf.s186.ums.test;

import org.nf.s186.ums.utils.DateUtil;

public class DateUtilTest {

	public static void main(String[] args) {
		String str = "2022-06-07" ;
		
		java.util.Date birth = DateUtil.stringToDate(str, DateUtil.DATA_PATTERN) ;
		
		System.out.println(birth);

	}

}


4、数据判断

package org.nf.s186.ums.test;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DateUtil;

public class HobbyTest {

	public static void main(String[] args) {
		String hobby = "吃,喝,玩" ;
		
		boolean bl1 = hobby.contains("吃") ;
		boolean bl2 = hobby.contains("喝") ;
		boolean bl3 = hobby.contains("玩") ;
		
		System.out.println(bl1);
		System.out.println(bl2);
		System.out.println(bl3);

	}

}


5、查询

package org.nf.s186.ums.test;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DateUtil;

public class QueryUserByIdTest {

	public static void main(String[] args) {
		// 1.实例DAO对象
		UserInfoDao userInfoDao = new UserInfoDaoImpl() ;
	
		UserInfo user = userInfoDao.queryUserById(80);
	
		if(user==null) {
			System.out.println("查无此人");
		} else {
			System.out.println(" :"+user.getUsername());
			System.out.println("性别:"+user.getSex());
			// ..
		}

	}

}


===========================

包名不能有大写字母

1、登录

顺序步骤:

1、工具包(添加jar包(jtds-1.3.1.jar)---2、实体对象---3、数据访问对象---4、数据访问对象实现类【每做完一项就要测试】---5、业务---6、业务实现类---7、在工具包创建MD5加密类---8、Servlet包(登录)---9、创建错误的提示信息包---10、错误消息jsp---11、登录JSP---12、创建css页面---13、验证码添加jar包(kaptcha-2.3.2.jar)---14、在Servlet包添加产生随机验证码类---15、配置web.xml---16、创建js页面(图片)---17、登录成功jsp---18、在Servlet包添加退出登录类---19、创建Filter包后台管理员登录认证类---20、创建md存SQL数据---21、运行

===============================================================

案例步骤:

每写完一个都要测试一下

只要是接口都是画大饼

web.xml的路径一定要是唯一的

最后添加 右击项目--folder--创建(放数据库数据)

创建数据库

创建项目

---检查项目的编码是否是 UTF-8(右击项目--Properties--Resource)

---- 要把连接驱动jar包(jtds-1.3.1.jar),添加到项目的lib目录

编写后台JAVA代码 (src/main/java)

包要命名规范 org/com.数据库名.模块名称....

不能有大写字母

1、工具包(utils)---存放项目相关工作类的包

===连接数据库类===

1、连接驱动程序

2、连接URL

3、帐号

4、密码

5、加载驱动程序

6、获取连接对象 -- Java程序 与 数据库之间的桥梁

7、关闭相关的 JDBC 对象

8、测试

2、实体包(entity)---存放实体类的包

===实体对象 - 用户对象 - 用于封装数据、传递数据===

1、字段

2、属性

3、缺省构造方法(默认可以不编写)

3、数据访问对象包(dao、.dao.impl)

---存放dao接口的包
===用户数据访问接口 - 标准 - 规范===

1、增

2、删

3、改

4、查 - 查询所有 - 返回多个数据

5、查 - 根据ID查询 - 返回唯一数据

6、查 - 服务于登录

7、查 - 查询所有 + 分页 - 返回多个数据

8、查 - 条件查询(精确、模糊) + 分页 - 返回多个数据
---存放dao接口实现类的包
===UserDao接口的实现类 - 接口的其中的一种实现(方案)===

第一:定义操作数据库的SQL语句

第二:获取连接对象 - 导包:ctrl + shift + o

第三:获取语句对象

第四:填充SQL语句

第五:执行SQL语句(更新操作、查询操作)

第六:处理执行结果
	
	1.获取当前行中,各字段的数据 - 结果集对象.getXxx(下标)
	
	2.创建实体对象
	
	3.初始化对象 - 把以上读取的各列数据,封装到实体对象中
	
第七:关闭对象	

4.业务包 (service、service.impl)

---存放service接口的包
===业务接口 - 标准 - 规范==

A、用户登录
---存放service接口实现类的包
===UserService接口的实现类 - 接口的其中的一种实现(方案)===

A1、实例化UserDao对象

A2、根据用户名称查询用户信息

A3、判断密码是否匹配

在工具包创建MD5加密类

 

5.Servlet包(servlet、controller、web)---存放Servlet程序的包

===处理用户登录类 ===

第一:获取用户提交的数据

第二:数据的合法性验证

第三:实例化业务对象或DAO对象,进行相关的处理

第四:响应结果

	1.登录失败

	2.登录成功

===处理用户退出登录类===

1、获取会话对象

2、让会话对象失效 -- session存储的用户信息也就没有了

3、页面跳转到登录页面

创建错误的提示信息包

1、字段

2、属性

3、缺省方法

4、重载方法

7、跟登录有关的页面(JSP)

登录 --- 创建css页面--- 创建js页面
一、<link>标签
在一个html文件中,link标签还包含许多其它属性,其中最常见的是使用link元素链接外部的CSS样式表,语法如下:

<link type="text/css"rel="stylesheet" href="style.css"></link>

link标签需要用一个反斜杠结束,这样才符合W3C标准,上述语法用html语言解释为:
	link type="定义当前文本内容以层叠样式表(CSS)来解析"

	rel="定义当前文档与被链接文档之间的关系,这里是调用外部文件,stylesheet即代表css样式表。"

	href="定义被链接文档的位置,这里链接所指向的是:同一目录下名为style.css的文件。"
===========================================================	
二、<script> 标签
1、<script> 标签的定义
	1)<script> 标签用于定义当前网页文档的脚本语言,比如:JavaScript(简称JS);

	2)<script> 标签引入脚本语言,可实现图像操作、表单验证以及更多其他动态交互作用;

	3)<script> 元素既可包含脚本语句,也可以通过 "src" 属性指向外部脚本文件;

	4)一个html文档中,可以包含多个<script> 标签。	

2、<script></script> 标签的用法
用script标签引入JavaScript脚本(简称JS)有内联方式和外联方式两种,分别详述如下:

1)内联方式
这种方式指的是在html文档中,将 JavaScript代码直接写在<script>和</scritp>标签之间。

<script type="text/javascript"> JS代码 </script>

type="text/javascript",在html5中是可选属性,可以省略不写,而在html4中,type是必选属性,不可省略!

2)外联方式
外联方式是在html文档中,通过<script> 标签的src属性引入一个外部的JS文件

<script type="text/javascript" src="外部js文件"></script>

使用了src属性引入外部JS文件,那么,<script> 元素内容就必须为空,即开始标签<script>和结束标签</scritp>之间不能有任何内容,即已经引入了外部JS文件,就不能再包括JS代码本身!

===========================================================
三、<form></form> 表单标签

<form action="目标地址"method="数据提交方式"></form>

四、<img/> 图像标签

<img src="图片地址" title="图片标题" onclick="点击事件')"/>

登录成功 --- 退出登录
创建退出登录的界面(JSP)

 

===异常===

1、对象名无效

检查连接的数据库名

2、

=================================================================

Ctrl+F 数据替换

$ --tuole

2、集合查询

顺序步骤:

1、工具包---2、添加jar包(jtds-1.3.1.jar)---3、实体对象---4、数据访问对象---5、数据访问对象实现类---6、测试---7、sevlet包(集合查询)---8、用户信息列表jsp---9、添加jar包()---

3、

==================================================================

步骤

1、登录

数据访问对象接口类

package org.nf.s186.ums.dao;

import java.util.List;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 定义 用户信息表(用户对象) 的相关数据操作接口
 * @author Administrator
 *
 */
public interface UserInfoDao {
	/**
	 * 根据帐号和密码查询用户,服务于登录业务
	 * @param username
	 * @param password
	 * @return
	 */
	public UserInfo queryUser(String username,String password) ;	

}


数据访问对象接口实现类

package org.nf.s186.ums.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DBUtil;

/**
 * UserDao接口的实现类
 * 
 * 根据需要,可以定义多个DAO接口的实现类,从而解决不同需求的情况
 * 
 * 
 * @author Administrator
 *
 */
public class UserInfoDaoImpl implements UserInfoDao {

	@Override
	public UserInfo queryUser(String username, String password) {

		UserInfo user = null;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "select * from userinfo where username=? and password=?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();

		// 第三:获取语句对象
		PreparedStatement stmt = null;
		ResultSet rst = null;

		try {
			// 1.预编译SQL语句
			stmt = conn.prepareStatement(sql);
			// 2.填充数据
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			stmt.setString(1, username);
			stmt.setString(2, password);

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			rst = stmt.executeQuery();

			// 第五:处理SQL语句返回的结果
			if (rst.next()) {
				// 1.实例化对象
				user = new UserInfo();

				// 2.读取各个字段的数据
				// 语法如下:
				// 1)结果集对象.getXxx(字段索引)
				// 2)结果集对象.getXxx(字段列名)
				int userId = rst.getInt(1);
				String name = rst.getString(2);
				String tel = rst.getString(4);
				String sex = rst.getString(5);
				double weight = rst.getDouble(6);
				java.sql.Date birth = rst.getDate(7);
				String hobby = rst.getString(8);
				java.sql.Timestamp regTime = rst.getTimestamp(9);

				// 3.封装数据
				user.setId(userId);
				user.setUsername(name);
				user.setTel(tel);
				user.setSex(sex);
				user.setWeight(weight);
				user.setBirth(birth);
				user.setHobby(hobby);
				user.setRegTime(regTime);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(rst, stmt, conn);
		}

		return user;
	}

}


业务接口类

package org.nf.s186.ums.service;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 业务接口
 * 	如果业务单一或在确定的情况下,可以不需要定义接口
 * 	或者也可以根据实际情况,后期根据需求,重构代码再定义此接口
 * 
 * @author Administrator
 *
 */
public interface UserInfoService {
	/**
	 * 登录
	 * @param username
	 * @param password
	 * @return
	 */
	public UserInfo login(String username,String password) ;
}


业务接口实现类

package org.nf.s186.ums.service.impl;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;

public class UserInfoServiceImpl implements UserInfoService {

	@Override
	public UserInfo login(String username, String password) {
		// 第一:实例化DAO对象
		UserInfoDao userInfoDao = new UserInfoDaoImpl();

		// 第二:查询数据
		UserInfo userInfo = userInfoDao.queryUser(username, password);

		// 第三:返回结果
		return userInfo;
	}

}


Servlet

package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;
import org.nf.s186.ums.service.impl.UserInfoServiceImpl;

/**
 * 处理登录的服务器程序
 * @author Administrator
 *
 */

public class LoginServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		resp.setContentType("text/html;charset=utf-8");
		resp.setCharacterEncoding("utf-8") ;
		PrintWriter out = resp.getWriter() ;
		
		// 第一:获取用户输入的数据
		String username = req.getParameter("username");
		String password = req.getParameter("password");
		
		// 对数据进行合法性验证
		if(username==null || "".equals(username.trim())) {
			out.print("用户名不能为空,<a href='index.html'>返回</a>") ;
			out.flush();
			out.close();
			return ;
		}
		
		if(password==null || "".equals(password.trim())) {
			out.print("密码不能为空,<a href='index.html'>返回</a>") ;
			out.flush();
			out.close();
			return ;
		}
		
		// 第二:实例化业务对象
		UserInfoService userInfoService = new UserInfoServiceImpl() ;
		
		// 第三:处理
		UserInfo userInfo = userInfoService.login(username, password);
		
		// 第四:响应结果
		// 1.登录失败
		if(user==null) {
			ErrorVO error = new ErrorVO("登录失败,错误的帐号或密码","login.jsp");
			req.setAttribute("error", error);
			req.getRequestDispatcher("../error.jsp").forward(req, resp);
			return ;
		}
		
		// 2.登录成功
		session.setAttribute("user", user);
		resp.sendRedirect("index.jsp");
}

错误提示类

package org.shop.vo;

/**
 * 错误对象
 * 
 * @author Administrator
 *
 */
public class ErrorVO {
	/**
	 * 错误的消息
	 */
	private String msg;

	/**
	 * 错误返回地址
	 */
	private String url;
	
	

	public ErrorVO() {
	}

	public ErrorVO(String msg, String url) {
		super();
		this.msg = msg;
		this.url = url;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

}


登录jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>管理员登录</title>
	<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/css/admin.css"></link>
	<script type="text/javascript" src="${pageContext.request.contextPath }/js/admin.js"></script>
</head>
<body>
	<h1>用户登录</h1>
	<form action="${pageContext.request.contextPath }/admin/login.do" method="post">
		帐号:<input type="text" name="username" value="admin"/><br/>
		密码:<input type="password" name="password" value="admin"/><br/>
		<input type="submit" value="登录"/>
	</form>
</body>
</html>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录失败</title>
</head>
<body>
	<h1>登录失败</h1>
</body>
</html>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录成功</title>
</head>
<body>
	<h1>登录成功</h1>
</body>
</html>

2、注册(添加)

数据访问对象接口类

package org.nf.s186.ums.dao;

import java.util.List;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 定义 用户信息表(用户对象) 的相关数据操作接口
 * @author Administrator
 *
 */
public interface UserInfoDao {

	/**
	 * 添加用户信息 
	 * @param userinfo 实体对象(用户的相关信息封装)
	 * @return 受影响行数
	 */

}


数据访问对象接口实现类

package org.nf.s186.ums.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DBUtil;

/**
 * UserDao接口的实现类
 * 
 * 根据需要,可以定义多个DAO接口的实现类,从而解决不同需求的情况
 * 
 * 
 * @author Administrator
 *
 */
public class UserInfoDaoImpl implements UserInfoDao {

	@Override
	public int insertUser(UserInfo userinfo) {
		int row = 0;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "insert into userinfo(username,password,tel,sex,weight,birth,hobby) values (?,?,?,?,?,?,?)";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();
		PreparedStatement pstmt = null;

		try {
			// 第三:获取语句对象
			// 1.预编译SQL语句
			pstmt = conn.prepareStatement(sql);
			// 2.填充数据 - 把SQL语句补充完整
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			pstmt.setString(1, userinfo.getUsername());
			pstmt.setString(2, userinfo.getPassword());
			pstmt.setString(3, userinfo.getTel());
			pstmt.setString(4, userinfo.getSex());
			pstmt.setDouble(5, userinfo.getWeight());

			// 获取出生日期的毫秒数
			long longBirth = userinfo.getBirth().getTime();
			// 把java.util.Date转换为java.sql.Date
			java.sql.Date birth = new java.sql.Date(longBirth);

			pstmt.setDate(6, birth);
			pstmt.setString(7, userinfo.getHobby());

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			row = pstmt.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(null, pstmt, conn);
		}

		// 第五:处理SQL语句返回的结果
		return row;
	}

}


业务接口类

package org.nf.s186.ums.service;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 业务接口
 * 
 * @author Administrator
 *
 */
public interface UserInfoService {

	/**
	 * 注册
	 * @param user
	 * @return
	 */
	public int register(UserInfo user) ;
}


业务接口实现类

package org.nf.s186.ums.service.impl;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;

public class UserInfoServiceImpl implements UserInfoService {
	@Override
	public int register(UserInfo user) {
		UserInfoDao userInfoDao = new UserInfoDaoImpl();
		return userInfoDao.insertUser(user);
	}

}


Servlet

package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.util.Arrays;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;
import org.nf.s186.ums.service.impl.UserInfoServiceImpl;
import org.nf.s186.ums.utils.DateUtil;

/**
 * 处理注册请求
 * @author Administrator
 *
 */
@WebServlet("/register.do")
public class RegisterServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 第一:设置请求编码
		req.setCharacterEncoding("UTF-8");
		
	
		
		// 第二:获取客户端传递的数据
		String username = req.getParameter("username") ;
		String password = req.getParameter("password") ;
		String sex = req.getParameter("sex") ;
		String tel = req.getParameter("tel") ;
		String weight = req.getParameter("weight") ;
		String birth = req.getParameter("birth") ;
		String[] hobby = req.getParameterValues("hobby") ;
		
		// 第三:对传递的数据进行合法性验证(服务器验证),保证数据的合法性(安全) -- 正则表达式
		double doubleWeight = Double.parseDouble(weight);
		
		// 第四:加工处理数据(结合业务需求)
		// 1.实例化业务对象
		UserInfoService userService = new UserInfoServiceImpl() ;
		
		// 2.实例化实体对象,并初始化表单传递过来的数据
		UserInfo u = new UserInfo() ;
		
		// 3.初始化实体对象
		u.setUsername(username);
		u.setPassword(password);
		u.setSex(sex);
		u.setTel(tel);
		u.setWeight(doubleWeight);
		u.setBirth(DateUtil.stringToDate(birth, DateUtil.DATA_PATTERN));
		u.setHobby(Arrays.toString(hobby));
		
		// 4.业务处理 - 注册 
		int r = userService.register(u) ;
		
		// 第五:响应结果(打印输出或页面跳转[重定向、转发])
		req.setAttribute("r", r);
		
		// 页面跳转到JSP中 - 转发
					         req.getRequestDispatcher("register.jsp").forward(req, resp);	
	}
}

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>注册成功</title>
</head>
<body>
	<h1>注册成功</h1>
</body>
</html>

 

3、修改

数据访问对象接口类

package org.nf.s186.ums.dao;

import java.util.List;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 定义 用户信息表(用户对象) 的相关数据操作接口
 * @author Administrator
 *
 */
public interface UserInfoDao {
	/**
	 * 修改用户
	 * @param userinfo 实体对象
	 * @return 受影响行数
	 */
	public int updateUser(UserInfo userinfo) ;
}


数据访问对象接口实现类

package org.nf.s186.ums.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DBUtil;

/**
 * UserDao接口的实现类
 * 
 * 根据需要,可以定义多个DAO接口的实现类,从而解决不同需求的情况
 * 
 * 
 * @author Administrator
 *
 */
public class UserInfoDaoImpl implements UserInfoDao {

	@Override
	public int updateUser(UserInfo userinfo) {
		int row = 0;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "update userinfo set username=?,tel=?,sex=?,weight=?,birth=?,hobby=? where id=?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();
		PreparedStatement pstmt = null;

		try {
			// 第三:获取语句对象
			// 1.预编译SQL语句
			pstmt = conn.prepareStatement(sql);
			// 2.填充数据 - 把SQL语句补充完整
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			pstmt.setString(1, userinfo.getUsername());
			pstmt.setString(2, userinfo.getTel());
			pstmt.setString(3, userinfo.getSex());
			pstmt.setDouble(4, userinfo.getWeight());


			// 获取出生日期的毫秒数
			long longBirth = userinfo.getBirth().getTime();
			// 把java.util.Date转换为java.sql.Date
			java.sql.Date birth = new java.sql.Date(longBirth);

			pstmt.setDate(5, birth);
			pstmt.setString(6, userinfo.getHobby());
			pstmt.setInt(7, userinfo.getId());

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			row = pstmt.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(null, pstmt, conn);
		}

		// 第五:处理SQL语句返回的结果
		return row;
	}

}


Servlet

package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DateUtil;

/**
 * 修改用户信息
 * 
 * @author zing
 *
 */
@WebServlet("/update.do")
public class UpdateUserServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 第一:设置请求编码
		req.setCharacterEncoding("UTF-8");
		
		// 设置响应编码
		resp.setContentType("text/html;charset=utf-8");
		resp.setCharacterEncoding("utf-8");
		// 获取打印输出流对象
		PrintWriter out = resp.getWriter();

		
		// 注意:每个一个后台程序都要编写以下代码,实现用户权限认证 -- 不利于程序维护 -- 解决:过滤器
		HttpSession session = req.getSession();
		UserInfo userInfo = (UserInfo) session.getAttribute("loginUser");
		// 判断在会话中是否存在登录的用户 -- 防止用法在没有登录的情况下,访问服务器资源
		if (userInfo == null) {
			out.print("对不起,你没有权限!请<a href='index.html'>登录</a>");
			out.flush();
			out.close();
			return;
		}

		// 第二:获取客户端传递的数据
		String username = req.getParameter("username");
		String userId = req.getParameter("userId");
		String sex = req.getParameter("sex");
		String tel = req.getParameter("tel");
		String weight = req.getParameter("weight");
		String birth = req.getParameter("birth");
		String[] hobby = req.getParameterValues("hobby");

		// 第三:对传递的数据进行合法性验证(服务器验证),保证数据的合法性(安全) -- 正则表达式
		double doubleWeight = Double.parseDouble(weight);
		int id = Integer.parseInt(userId);

		// 第四:加工处理数据(结合业务需求)
		// 1.实例化业务对象
		// UserInfoService userService = new UserInfoServiceImpl() ;
		UserInfoDao userInfoDao = new UserInfoDaoImpl();

		// 2.实例化实体对象,并初始化表单传递过来的数据
		UserInfo u = new UserInfo();

		// 3.初始化实体对象
		u.setId(id);
		u.setUsername(username);
		u.setSex(sex);
		u.setTel(tel);
		u.setWeight(doubleWeight);
		u.setBirth(DateUtil.stringToDate(birth, DateUtil.DATA_PATTERN));
		u.setHobby(Arrays.toString(hobby));

		// 4.业务处理
		int r = userInfoDao.updateUser(u);

		// 第五:响应结果(打印输出或页面跳转[重定向、转发])
		req.setAttribute("r", r);
		
		// 页面跳转到JSP中 - 转发
		req.getRequestDispatcher("update.jsp").forward(req, resp);

	}
}


修改jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>修改成功</title>
</head>
<body>
	<h1>修改成功</h1>
</body>
</html>

4、删除

数据访问对象接口类

package org.nf.s186.ums.dao;

import java.util.List;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 定义 用户信息表(用户对象) 的相关数据操作接口
 * @author Administrator
 *
 */
public interface UserInfoDao {

	/**
	 * 根据用户编号删除数据
	 * @param id 用户编号
	 * @return 受影响行数
	 */
    
	public int deleteUser(int id) ;

}


数据访问对象接口实现类

package org.nf.s186.ums.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DBUtil;

/**
 * UserDao接口的实现类
 * 
 * 根据需要,可以定义多个DAO接口的实现类,从而解决不同需求的情况
 * 
 * 
 * @author Administrator
 *
 */
public class UserInfoDaoImpl implements UserInfoDao {

	@Override
	public int deleteUser(int id) {
		int row = 0;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "delete from userinfo where id=?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();
		PreparedStatement pstmt = null;

		try {
			// 第三:获取语句对象
			// 1.预编译SQL语句
			pstmt = conn.prepareStatement(sql);
			// 2.填充数据 - 把SQL语句补充完整
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			pstmt.setInt(1, id);
	

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			row = pstmt.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(null, pstmt, conn);
		}

		// 第五:处理SQL语句返回的结果
		return row;
	}

}


Servlet

package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;

/**
 * 删除用户
 * @author zhang
 *
 */
public class DeleteUserServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		resp.setContentType("text/html;charset=utf-8");
		resp.setCharacterEncoding("utf-8");
		
		PrintWriter out = resp.getWriter() ;
		
		
		HttpSession session = req.getSession() ;
		UserInfo userInfo = (UserInfo)session.getAttribute("loginUser");
		// 判断在会话中是否存在登录的用户 -- 防止用法在没有登录的情况下,访问服务器资源
		if(userInfo==null) {
			out.print("对不起,你没有权限!请<a href='index.html'>登录</a>") ;
			out.flush();
			out.close();
			return ;
		}
		
		
		// 第一:获取用户输入的数据
		String userId = req.getParameter("userId");
		
		// 对输入的数据进行合法性验证
		String reg = "\\d{1,}" ;
		boolean isOk = userId.matches(reg) ;
		
		if(!isOk) {
			// 注意:也可以通过页面跳转实现错误提示
			out.print("非法操作,您传递的参数["+userId+"]非法") ;
			out.print("<a href='welcome.do'>返回</a>") ;
			return ;
		}
		
		int id = Integer.parseInt(userId) ;
	
		// 第二:实例化业务对象
		// 第三:处理
		UserInfoDao userInfoDao = new UserInfoDaoImpl();
		int row = userInfoDao.deleteUser(id) ;

		// 第四:响应
		req.setAttribute("row", row);
		
		// 页面跳转到JSP中 - 转发
		req.getRequestDispatcher("delete.jsp").forward(req, resp);
	
	}
}


删除jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>删除成功</title>
</head>
<body>
	<h1>删除成功</h1>
</body>
</html>

5、集合查询(查询所有)

数据访问对象接口类

package org.shop.dao;

import java.util.List;

import org.shop.entity.UserInfo;

/**
 * 用户数据访问接口 - 标准 - 规范
 * 包含了用户这个实体(数据表)的相关增、删、改、查的数据库操作方法
 * 
 * @author Administrator
 *
 */
public interface UserInfoDao {

	// 查 - 查询所有 - 返回多个数据
	public List<UserInfo> selectAllUser() ;
	
}

数据访问对象接口实现类

package org.shop.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.shop.dao.UserInfoDao;
import org.shop.entity.UserInfo;
import org.shop.util.DBUtil;

/**
 * UserInfoDao接口的实现类 - 接口的其中的一种实现(方案)
 * 
 * @author Administrator
 *
 */
public class UserInfoDaoImpl implements UserInfoDao {

	@Override
	public List<UserInfo> selectAllUser() {
		//创建集合对象
		List<UserInfo> list = new ArrayList<>() ;

		// 第一:定义操作数据库的SQL语句
		String sql = "select * from userinfo";

		// 第二:获取连接对象 - 导包:ctrl + shift + o
		Connection conn = DBUtil.getConnection();

		// 第三:获取语句对象
		PreparedStatement pstmt = null;
		ResultSet rst = null;
		try {
			pstmt = conn.prepareStatement(sql);

			// 第四:填充SQL语句

			// 第五:执行SQL语句(更新操作、查询操作)
			rst = pstmt.executeQuery();

			// 第六:处理执行结果
			while (rst.next()) {
				// 1.获取当前行中,各字段的数据 - 结果集对象.getXxx(下标)
				int id = rst.getInt(1);
				String username = rst.getString(2) ;
				// String password = rst.getString(3);
				String name = rst.getString(4);
				String image = rst.getString(5);
				String sex = rst.getString(6);
				String phone = rst.getString(7);
				String address = rst.getString(8);
				String zipCode = rst.getString(9);
				String email = rst.getString(10);
				Timestamp regTime = rst.getTimestamp(11);

				// 2.创建实体对象
				UserInfo user = new UserInfo();

				// 3.初始化对象 - 把以上读取的各列数据,封装到实体对象中
				user.setId(id);
				user.setUsername(username);
				// user.setPassword(password);
				user.setName(name);
				user.setImage(image);
				user.setSex(sex);
				user.setPhone(phone);
				user.setAddress(address);
				user.setZipCode(zipCode);
				user.setEmail(email);
				user.setRegTime(regTime);
				
				// 4.把当前行的数据(uer)添加到集合中
				list.add(user);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第七:关闭对象
			DBUtil.close(rst, pstmt, conn);
		}
		
		return list ;
	}

}


Servlet

package org.shop.controller.user;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.shop.dao.UserInfoDao;
import org.shop.dao.impl.UserInfoDaoImpl;
import org.shop.entity.UserInfo;

/**
 * 查询
 * @author Administrator
 * 
 */
@WebServlet("/admin/queryAllUserInfo.do")
public class QueryAllUserInfoServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 实例化Dao对象
		UserInfoDao userInfoDao = new UserInfoDaoImpl() ;
		
		// 查询所有的用户
		List<UserInfo> list = userInfoDao.selectAllUser();

		// 把数据存放在作用域对象中 - 请求作用域
		req.setAttribute("list", list);
		
		// 页面跳转到JSP中 - 转发
		req.getRequestDispatcher("listAllUserinfo.jsp").forward(req, resp);;

	}

}


查询jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户信息列表</title>
</head>
<body>
	<h1 align="center">用户信息列表</h1>
	
	<table border="1" align="center" width="80%">
		<tr>
			<th>编号</th>
			<th>帐号</th>
			<th>姓名</th>
			<th>性别</th>
			<th>电话</th>
			<th>邮箱</th>
			<th>注册时间</th>
			<th>操作</th>	
		</tr>
				
		<c:choose>
			<c:when test="${empty requestScope.list }">
				<tr align="center">
					<td colspan="8">数据为空</td>
				</tr>
			</c:when>
			
			<c:otherwise>
				<c:forEach items="${requestScope.list }" var="user">
					<tr align="center">
						<td>${user.id }</td>
						<td>${user.username }</td>
						<td>${user.name }</td>
						<td>${user.sex }</td>
						<td>${user.phone }</td>
						<td>${user.email }</td>
						<td>
							<fmt:formatDate value="${user.regTime }" pattern="yyyy-MM-dd hh:mm"/>
						</td>
						<td>删除 | 查看</td>	
					</tr>
				</c:forEach>
			</c:otherwise>
			
		</c:choose>
		
	</table>
		
	<h1 align="center">
		<a href="${pageContext.request.contextPath }/admin/index.jsp">
			返回
		</a>
	</h1>
</body>
</html>

6、根据用户ID查询用户信息

数据访问对象接口类

package org.nf.s186.ums.dao;

import java.util.List;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 定义 用户信息表(用户对象) 的相关数据操作接口
 * @author Administrator
 *
 */
public interface UserInfoDao {
	
	/**
	 * 根据用户ID查询用户信息 - 服务于查看用户详情
	 * @param id
	 * @return
	 */
	public UserInfo queryUserById(int id) ;

}


数据访问对象接口实现类

package org.nf.s186.ums.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DBUtil;

/**
 * UserDao接口的实现类
 * @author Administrator
 *
 */
public class UserInfoDaoImpl implements UserInfoDao {

	@Override
	public UserInfo queryUserById(int id) {
		UserInfo user = null;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "select * from userinfo where id=?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();

		// 第三:获取语句对象
		PreparedStatement stmt = null;
		ResultSet rst = null;

		try {
			// 1.预编译SQL语句
			stmt = conn.prepareStatement(sql);
			// 2.填充数据
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			stmt.setInt(1, id);


			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			rst = stmt.executeQuery();

			// 第五:处理SQL语句返回的结果
			if (rst.next()) {
				// 1.实例化对象
				user = new UserInfo();

				// 2.读取各个字段的数据
				// 语法如下:
				// 1)结果集对象.getXxx(字段索引)
				// 2)结果集对象.getXxx(字段列名)
				int userId = rst.getInt(1);
				String name = rst.getString(2);
				String tel = rst.getString(4);
				String sex = rst.getString(5);
				double weight = rst.getDouble(6);
				java.sql.Date birth = rst.getDate(7);
				String hobby = rst.getString(8);
				java.sql.Timestamp regTime = rst.getTimestamp(9);

				// 3.封装数据
				user.setId(userId);
				user.setUsername(name);
				user.setTel(tel);
				user.setSex(sex);
				user.setWeight(weight);
				user.setBirth(birth);
				user.setHobby(hobby);
				user.setRegTime(regTime);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(rst, stmt, conn);
		}

		return user;
	}

}


Servlet

package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;

/**
 * 根据用户编号,查看用户详情
 * @author zing
 *
 */
public class ShowUserServlet extends HttpServlet{

	private static final long serialVersionUID = 1L;

	@Override 
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		// 实例化DAO对象
		UserInfoDao userInfoDao = new UserInfoDaoImpl() ;
		
		// 根据用户ID查询用户的明细
		UserInfo u = userInfoDao.queryUserById(id);
        
        	// 把数据存放在作用域对象中 - 请求作用域
		req.setAttribute("u", u);
		
		// 页面跳转到JSP中 - 转发		req.getRequestDispatcher("showUserById.jsp").forward(req, resp);;


}


查询jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户信息列表</title>
</head>
<body>
	<h1 align="center">用户信息列表</h1>
	
	<table border="1" align="center" width="80%">
		<tr>
			<th>编号</th>
			<th>帐号</th>
			<th>姓名</th>
			<th>性别</th>
			<th>电话</th>
			<th>邮箱</th>
			<th>注册时间</th>
			<th>操作</th>	
		</tr>
		
		
		<c:choose>
			<c:when test="${empty requestScope.list }">
				<tr align="center">
					<td colspan="8">数据为空</td>
				</tr>
			</c:when>
			
			<c:otherwise>
				<c:forEach items="${requestScope.list }" var="user">
					<tr align="center">
						<td>${user.id }</td>
						<td>${user.username }</td>
						<td>${user.name }</td>
						<td>${user.sex }</td>
						<td>${user.phone }</td>
						<td>${user.email }</td>
						<td>
							<fmt:formatDate value="${user.regTime }" pattern="yyyy-MM-dd hh:mm"/>
						</td>
						<td>删除 | 查看</td>	
					</tr>
				</c:forEach>
			</c:otherwise>
			
		</c:choose>
		
	</table>
	
	
	<h1 align="center">
		<a href="${pageContext.request.contextPath }/admin/index.jsp">
			返回
		</a>
	</h1>

</body>
</html>

================================================一、开发步骤 (打印名字)

先创建前端页面HTML
第一:定义一个类,并继承HttpServlet
第二:重写父类的doXxx方法,Xxx表示客户端请求的方式,如post、get等
第三:在doXxx方法中,编写代码,实现相关的业务逻辑功能(需求)
	0.设置响应对象的编码
	1.获取打印输出流对象
	2.打印输出内容到浏览器(响应结果)
	3.关闭流对象
第四:配置web.xml文件,对外提供一个访问URL
	1.定义Servlet
	2.映射Servlet,对外提供访问URL
启动 http://localhost:8080/项目名/html名

二、模拟实现用户登录

如果用到按键先创建HTML界面
第一:定义一个类,并继承HttpServlet
第二:重写父类的doXxx方法,Xxx表示客户端请求的方式,如post、get等
第三:在doXxx方法中,编写代码,实现相关的业务逻辑功能(需求)
	0.设置响应对象的编码
	1.获取打印输出流对象
	2.获取用户登录的数据
	3.合法性判断
	4.打印输出内容到浏览器(响应结果)
	5.关闭流对象
第四:配置web.xml文件,对外提供一个访问URL
	1.定义Servlet
	2.映射Servlet,对外提供访问URL

启动 http://localhost:8080/项目名/html名

三、页面跳转

一、先在webapp创建HTML界面
   	登录
	登录失败
	登录成功

二、登录
在src/main/java右键创建类
	
	第一:在src/miam/java---class 定义一个类,并继承HttpServlet

	第二:重写父类的doXxx方法,Xxx表示客户端请求的方式,如post、get等

	第三:在doXxx方法中,编写代码,实现相关的业务逻辑功能(需求) - 登录功能
	注意:在Serlvet程序中,一般我们需要借助于“请求”、“响应”对象做相关的处理
		1、设置响应对象的编码方式
		2、设置请求对象的编码方式
		3、获取打印输出流对象
		4、获取用户登录的数据
		5、合法性判断
		6、响应结果 - 登录成功与失败分别跳转到相关的页面中	
			1.登录成功,使用转发实现页面跳转 -- API方法
				1)获取转发对象,并指定跳转的页面
				2)转发跳转
			或
				1)把数据设置在请求对象中,便于数据传递
				2)转发跳转
				
			2.登录失败,使用重定向实现页面跳转	
   	 	7、关闭流对象
三、成功登录
在src/main/java右键创建类
	
	第一:在src/miam/java---class 定义一个类,并继承HttpServlet

	第二:重写父类的doXxx方法,Xxx表示客户端请求的方式,如post、get等

	第三:在doXxx方法中,编写代码,实现相关的业务逻辑功能(需求)
		1、设置响应对象的编码方式
		2、获取打印输出流对象
		3、获取请求对象设置的数据
		4、打印输出内容到浏览器(响应结果)
		注意:以下操作非常繁琐,不便于维护,后面使用JSP替换
		5、关闭流
	第四:配置web.xml文件,对外提供一个访问URL
		1、定义Servlet 
		2、映射Servlet,对外提供访问URL
	
启动 http://localhost:8080/项目名/html名

四、结合JDBC,实现用户登录

一、创建数据表
	1.创建数据库
	2.切换到数据库
	3.创建数据表
	4.添加初始化数据
二、创建项目
	1.配置工作空间的编码
	2.配置JDK环境
	3.配置Tomcat
	4.创建Dynamic Web Project ...
三、创建前端页面(html)
四、编写后台JAVA代码
		com|org.公司名称.组织名称.项目名称.模块名称.Xxxx.java
		1.工具包(utils)
		org.nf.s186.ums.utils
			1)连接数据库 注意:要把连接驱动jar包,添加到项目的lib目录
			连接驱动程序
			连接URL
			连接帐号
			连接密码
			加载驱动程序
			获取连接对象 -- Java程序 与 数据库之间的桥梁
			关闭相关的 JDBC 对象
			main入口调用
		2.实体包(entity、domain)
		org.nf.s186.ums.entity
       	 	字段
        	属性
			无参构造函数	
			带参构造函数
		3.数据访问对象包(dao)
			1)DAO接口 
			org.nf.s186.ums.dao 
			实体名称Dao
				根据帐号和密码查询用户,服务于登录业务
			2)DAO接口实现
			org.nf.s186.ums.dao.impl
			实体名称DaoImpl
				定义用户信息为空
				第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
				第二:获取连接对象
				第三:获取语句对象
					1.预编译SQL语句
					2.填充数据
				第四:执行SQL语句	
					 1.增、删、改:int 变量 = 语句对象.executeUpdate()
					 2.查询:ResultSet 变量 = 语句对象.executeQuery()
				第五:处理SQL语句返回的结果
					1.实例化对象
					2.读取各个字段的数据
						1)结果集对象.getXxx(字段索引)
						2)结果集对象.getXxx(字段列名)
					3.封装数据
				第六:关闭对象
		4.业务包(service)

			1)Service接口 

			org.nf.s186.ums.service

			实体名称Service	
				登录
				
 			2)Service接口实现

			org.nf.s186.ums.service.impl

			实体名称ServiceImpl	
				第一:实例化DAO对象 
				第二:查询数据
				第三:返回结果
		5.Servlet包(servlet、controller、web)		
		浏览器(操作界面)  ----    Servlet(桥梁)  -----  后台JAVA代码

		org.nf.s186.ums.servlet		
			处理登录的服务器程序
				第一:获取用户输入的数据
				第二:实例化业务对象
				第三:处理
				第四:响应
					1.登录失败,默认跳转的页面
					2.登录成功
						1)把登录帐号,存储在请求作用域中,便于数据传递 
						2)设置登录成功,跳转的页面
					 3.页面跳转 -- 重定向 或
                     页面跳转 -- 转发

五、结合JDBC,实现用户登录,注册,删除,查询,修改

1、结合JDBC,实现用户登录

一、创建数据表(sql数据库)
二、创建项目  (Eclipse)
	1、配置工作空间的编码 (Project--Properties--Resource--Other)
	2、配置JDK环境
	3、Tomcat (Window菜单 - Preferences - Server - Runtime Environments)
	 4、创建Dynamic Web Project ...( File - New - Project... - Web - Dynamic Web Project)

三、创建前端页面HTML(webapp)
	 1、登录(login)
	 2、登录成功(login-success)
	 3、登录失败(login-error)
四、编写后台JAVA代码  (src/main/java)
com|org.公司名称.组织名称.项目名称.模块名称.Xxxx.java
	 1、工具包(utils)(固定的,一定要记住)-(注意:要把连接驱动jar包(jtds-1.3.1.jar),添加到项目的lib目录     ==步骤:右击Deployment Descriptor:项目名 -- Generate Deployment Descriptor Stub)
	2、实体包(entity、domain)
	3、数据访问对象包(dao)
		1)DAO接口 
		2)DAO接口实现
	4、业务包(service)
		 1)Service接口 
		 2)Service接口实现
	5、Servlet包(servlet、controller、web)		
		 1)登录
		 2)登录成功
五、测试、运行(test)---只是检验可有可无
		 1、登录
六、配置web.xml文件,对外提供一个访问URL

2、结合JDBC,实现用户注册

一、创建数据表(sql数据库)
二、创建项目  (Eclipse)
	1、配置工作空间的编码 (Project--Properties--Resource--Other)
	2、配置JDK环境
	3、Tomcat (Window菜单 - Preferences - Server - Runtime Environments)
	 4、创建Dynamic Web Project ...( File - New - Project... - Web - Dynamic Web Project)

三、创建前端页面HTML(webapp)
	 1、登录(login)-- 跳转到注册页面	 
	 2、登录成功(login-success)
	 3、登录失败(login-error)
	 4、注册(register)--通过登录前端页面跳转
		创建JS实现页面跳转(在webapp目录创建)
		
四、编写后台JAVA代码  (src/main/java)

com|org.公司名称.组织名称.项目名称.模块名称.Xxxx.java
	 1、工具包(utils)(固定的,一定要记住)-(注意:要把连接驱动jar包(jtds-1.3.1.jar),添加到项目的lib目录     ==步骤:右击Deployment Descriptor:项目名 -- Generate Deployment Descriptor Stub)
	2、实体包(entity、domain)
	3、数据访问对象包(dao)
		1)DAO接口 
		2)DAO接口实现
	4、业务包(service)
		 1)Service接口 
		 2)Service接口实现
	5、Servlet包(servlet、controller、web)		
		 1)登录
		 2)登录成功
		 3)注册
五、测试、运行(test)---只是检验可有可无
		 1、登录
		 2、登录成功
六、配置web.xml文件,对外提供一个访问URL

3、结合JDBC,实现用户查询

一、创建数据表(sql数据库)
二、创建项目  (Eclipse)
	1、配置工作空间的编码 (Project--Properties--Resource--Other)
	2、配置JDK环境
	3、Tomcat (Window菜单 - Preferences - Server - Runtime Environments)
	 4、创建Dynamic Web Project ...( File - New - Project... - Web - Dynamic Web Project)

三、创建前端页面HTML(webapp)
	 1、登录(login)-- 跳转到注册页面	 
	 2、登录成功(login-success)
	 3、登录失败(login-error)
	 4、注册(register)--通过登录前端页面跳转
		创建JS实现页面跳转(在webapp目录创建)
		
四、编写后台JAVA代码  (src/main/java)

com|org.公司名称.组织名称.项目名称.模块名称.Xxxx.java
	 1、工具包(utils)(固定的,一定要记住)-(注意:要把连接驱动jar包(jtds-1.3.1.jar),添加到项目的lib目录     ==步骤:右击Deployment Descriptor:项目名 -- Generate Deployment Descriptor Stub)
	2、实体包(entity、domain)
	3、数据访问对象包(dao)
		1)DAO接口 
		2)DAO接口实现
	4、业务包(service)
		 1)Service接口 
		 2)Service接口实现
	5、Servlet包(servlet、controller、web)		
		 1)登录
		 2)登录成功
		 3)注册
五、测试、运行(test)---只是检验可有可无
		 1、登录
		 2、登录成功
六、配置web.xml文件,对外提供一个访问URL

 

步骤 登录 注册 修改 删除

 

一、创建前端页面HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户注册</title>
</head>
<body>
	<h1>用户注册</h1>
	<hr/>
	<form action="register.do" method="post">
		帐号:<input type="text" name="username"/><br/>
		密码:<input type="password" name="password"/><br/>
		电话:<input type="text" name="tel"/><br/>
		性别:
			<input type="radio" name="sex" value="男" id="man" checked/>
			<label for="man">男</label>
			
			<input type="radio" name="sex" value="女" id="woman"/>
			<label for="woman">女</label>
		<br/>
		体重:<input type="text" name="weight"/><br/>
		出生:<input type="text" name="birth"/><br/>
		爱好:
			<input type="checkbox" name="hobby" value="吃" id="eat"/>
			<label for="eat">吃</label>
			
			<input type="checkbox" name="hobby" value="喝" id="drink"/>
			<label for="drink">喝</label>
			
			<input type="checkbox" name="hobby" value="玩" id="play"/>
			<label for="play">玩</label>
			
			<input type="checkbox" name="hobby" value="乐" id="happy"/>
			<label for="happy">乐</label>
			<br/>
		<input type="submit" value="注册"/><br/>
	</form>
</body>
</html>

二、通过登录前端页面跳转

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户管理系统 - 用户登录</title>
</head>
<body>
	<form action="login.do" method="post">
		帐号:<input type="text" name="username"/><br/>
		密码:<input type="password" name="password"/><br/>
		<input type="submit" value="登录"/>
		<!-- todo:使用样式修改按钮,并使用JS实现页面跳转到注册页面 -->
		<button type="button" onClick="goToPage('reg.html')">用户注册</button>
	</form>
	
	
	<script type="text/javascript" src="js/index.js"></script>
	
	
</body>
</html>

 

三、创建JS实现页面跳转(在webapp目录创建)

/**
	JS实现页面跳转
 */
function goToPage(page) {
	location.href = page ;
}

四、工具包(utils)

package org.nf.s186.ums.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 连接数据库
 * 注意:要把连接驱动jar包,添加到项目的lib目录
 * 
 * @author zhang
 *
 */
public class DBUtil {
	/**
	 * 连接驱动程序
	 */
	private  static final String DRIVER = "net.sourceforge.jtds.jdbc.Driver" ;
	/**
	 * 连接URL
	 */
	private  static final String URL = "jdbc:jtds:sqlserver://localhost:1433;DatabaseName=ums" ;
	/**
	 * 帐号
	 */
	private  static final String USER = "sa" ;
	/**
	 * 密码
	 */
	private  static final String PASS = "mm1306612" ;
	
	
	
	static {
		/*
		 * 加载驱动程序
		 */
		try {
			Class.forName(DRIVER);
		} catch (ClassNotFoundException e) {
			System.out.println("加载驱动程序失败...");
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取连接对象 -- Java程序 与 数据库之间的桥梁
	 * @return
	 */
	public static Connection getConnection() {
		Connection conn = null ;
		try {
			conn = DriverManager.getConnection(URL, USER, PASS);
		} catch (SQLException e) {
			System.out.println("获取连接对象失败...");
			e.printStackTrace();
		}
		return conn ;
	}
	
	/**
	 * 关闭相关的 JDBC 对象
	 *  DriverManager:驱动管理对象,获取连接对象
	 *  		DriverManager.getConnection(URL, USER, PASS);
	 *  
	 * 	ResultSet:结果集对象
	 * 			用于接收查询数据时,返回的结果
	 * 
	 *  Statement:语句对象
	 *  		用于执行SQL语句(PreparedStatement、CallableStatement)
	 *  			增、删、改:executeUpdate()
	 *  			查询:executeQuery()
	 *  		
	 *  
	 *  Connection:连接对象
	 *  		建立JAVA程序与数据库之间的桥梁
	 * 
	 * @param rst 
	 * @param stmt 父类对象可以接收子类对象 - 多态
	 * @param conn 
	 */
	public static void close(ResultSet rst,Statement stmt,Connection conn) {
		if(rst!=null) {
			try {
				rst.close() ;
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		
		if(stmt!=null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		if(conn!=null) {
			try {
				conn.close() ;
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
	// executeUpdate()、executeQuery() - 略 
	public static void main(String[] args) {
		System.out.println(DBUtil.getConnection());
	}
	
}


 

五、实体包(entity 、domain)

package org.nf.s186.ums.entity;

import java.util.Date;

/**
 * 实体对象 - 用户对象 - 用于封装数据、传递数据
 * 
 * 一般有多个数据表,就有多少个实体对象 
 * 	1)表中的字段就是实体对象的属性 
 *  2)对象的属性一般要私有化,且生成相关的setter/getter方法
 * 	3)根据需要,可以定义重载构造方法,而默认的构造方法一般要显示写出来
 * 
 * 命名规范: 属性名首字母小写 驼峰标识 命名有意义
 * 
 * @author zhang
 *
 */
public class UserInfo {
	private int id;
	private String username;
	private String password;
	private String tel;
	private String sex;
	private double weight;
	private Date birth;
	private String hobby;
	private Date regTime;
	
	/**
	 * 默认(缺省)构造方法
	 * 
	 * 注意:当重载构造方法后,缺省构造方法就会被丢失
	 * 因此,一般我们会手动补回来
	 */
	public UserInfo() {}
	/**
	 * 重载构造方法 - 便于初始化对象 - 帐号、密码、手机号码
	 * @param username
	 * @param password
	 * @param tel
	 */
	public UserInfo(String username, String password, String tel) {
		this.username = username;
		this.password = password;
		this.tel = tel;
	}
	
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public double getWeight() {
		return weight;
	}
	public void setWeight(double weight) {
		this.weight = weight;
	}
	public Date getBirth() {
		return birth;
	}
	public void setBirth(Date birth) {
		this.birth = birth;
	}
	public String getHobby() {
		return hobby;
	}
	public void setHobby(String hobby) {
		this.hobby = hobby;
	}
	public Date getRegTime() {
		return regTime;
	}
	public void setRegTime(Date regTime) {
		this.regTime = regTime;
	}

	
	
	
}


 

六、数据访问对象包(dao)

1)DAO接口

package org.nf.s186.ums.dao;

import java.util.List;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 定义 用户信息表(用户对象) 的相关数据操作接口
 * 
 * 接口定义了相关的标准、规范,用于指定对象能做什么事情,
 * 		具体什么行为,但没有具体的实现。
 * 		具体的实现根据实际情况,定义相关的实现类实现(多态)。
 * 
 * 便于程序的扩展和维护
 * 	
 * 
 * DAO:数据访问对象(Data Access Object),
 * 		数据相关操作的对象,一般服务于业务对象,不包含相关的业务操作,只是单纯的实现数据操作(CRUD)
 * 		如果有相关业务就提取到业务对象实现;
 * 		如果没有相关业务代码或简单的业务可以直接在Servlet实现,而不需要业务对象
 * 
 * @author Administrator
 *
 */
public interface UserInfoDao {
	/**
	 * 根据帐号和密码查询用户,服务于登录业务
	 * @param username
	 * @param password
	 * @return
	 */
	public UserInfo queryUser(String username,String password) ;
	
	
	// 增、删、改、各种查询...
	/**
	 * 添加用户信息 
	 * @param userinfo 实体对象(用户的相关信息封装)
	 * @return 受影响行数
	 */
	public int insertUser(UserInfo userinfo) ;
	
	/**
	 * 根据用户编号删除数据
	 * @param id 用户编号
	 * @return 受影响行数
	 */
	public int deleteUser(int id) ;
	
	/**
	 * 修改用户
	 * @param userinfo 实体对象
	 * @return 受影响行数
	 */
	public int updateUser(UserInfo userinfo) ;
	
	/**
	 * 查询所有用户信息,除了当前登录用户,避免自己把自己删除了
	 * @param id
	 * @return
	 */
	public List<UserInfo> queryUserList(int id) ;

}

2)DAO接口实现

package org.nf.s186.ums.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DBUtil;

/**
 * UserDao接口的实现类
 * 
 * 根据需要,可以定义多个DAO接口的实现类,从而解决不同需求的情况
 * 
 * 
 * @author Administrator
 *
 */
public class UserInfoDaoImpl implements UserInfoDao {

	@Override
	public UserInfo queryUser(String username, String password) {

		UserInfo user = null;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "select * from userinfo where username=? and password=?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();

		// 第三:获取语句对象
		PreparedStatement stmt = null;
		ResultSet rst = null;

		try {
			// 1.预编译SQL语句
			stmt = conn.prepareStatement(sql);
			// 2.填充数据
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			stmt.setString(1, username);
			stmt.setString(2, password);

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			rst = stmt.executeQuery();

			// 第五:处理SQL语句返回的结果
			if (rst.next()) {
				// 1.实例化对象
				user = new UserInfo();

				// 2.读取各个字段的数据
				// 语法如下:
				// 1)结果集对象.getXxx(字段索引)
				// 2)结果集对象.getXxx(字段列名)
				int userId = rst.getInt(1);
				String name = rst.getString(2);
				String sex = rst.getString("sex");

				// 3.封装数据
				user.setId(userId);
				user.setUsername(name);
				user.setSex(sex);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(rst, stmt, conn);
		}

		return user;
	}

	@Override
	public int insertUser(UserInfo userinfo) {
		
        //声明变量
        int row = 0;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "insert into userinfo(username,password,tel,sex,weight,birth,hobby) values (?,?,?,?,?,?,?)";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();
		PreparedStatement pstmt = null;

		try {
			// 第三:获取语句对象
			// 1.预编译SQL语句
			pstmt = conn.prepareStatement(sql);
			// 2.填充数据 - 把SQL语句补充完整
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			pstmt.setString(1, userinfo.getUsername());
			pstmt.setString(2, userinfo.getPassword());
			pstmt.setString(3, userinfo.getTel());
			pstmt.setString(4, userinfo.getSex());
			pstmt.setDouble(5, userinfo.getWeight());

			// 获取出生日期的毫秒数
			long longBirth = userinfo.getBirth().getTime();
			// 把java.util.Date转换为java.sql.Date
			java.sql.Date birth = new java.sql.Date(longBirth);

			pstmt.setDate(6, birth);
			pstmt.setString(7, userinfo.getHobby());

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			row = pstmt.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(null, pstmt, conn);
		}

		// 第五:处理SQL语句返回的结果
		return row;
	}

	@Override
	public int deleteUser(int id) {
		int row = 0;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位

		// 第二:获取连接对象

		// 第三:获取语句对象

		// 1.预编译SQL语句
		// 2.填充数据
		// 语法:语句对象.setXxx(占位符索引,数据) ;
		// Xxx表示属性/字段的具体数据类型

		// 第四:执行SQL语句
		// 语法如下:
		// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
		// 2)查询:ResultSet 变量 = 语句对象.executeQuery()

		// 第五:处理SQL语句返回的结果
		// 第六:关闭对象

		return row;
	}

	@Override
	public int updateUser(UserInfo userinfo) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public List<UserInfo> queryUserList(int id) {
		List<UserInfo> list = new ArrayList<>();

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "select * from userinfo where id != ?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();

		// 第三:获取语句对象
		PreparedStatement stmt = null;
		ResultSet rst = null;

		try {
			// 1.预编译SQL语句
			stmt = conn.prepareStatement(sql);
			// 2.填充数据
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			stmt.setInt(1, id);


			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			rst = stmt.executeQuery();

			// 第五:处理SQL语句返回的结果
			while (rst.next()) {
				// 1.实例化对象
				UserInfo user = new UserInfo();

				// 2.读取各个字段的数据
				// 语法如下:
				// 1)结果集对象.getXxx(字段索引)
				// 2)结果集对象.getXxx(字段列名)
				int userId = rst.getInt(1);
				String name = rst.getString(2);
				String tel = rst.getString(4);
				String sex = rst.getString(5);
				double weight = rst.getDouble(6);
				java.sql.Date birth = rst.getDate(7);
				String hobby = rst.getString(8);
				java.sql.Timestamp regTime = rst.getTimestamp(9);
				

				// 3.封装数据
				user.setId(userId);
				user.setUsername(name);
				user.setTel(tel);
				user.setSex(sex);
				user.setWeight(weight);
				user.setBirth(birth);
				user.setHobby(hobby);
				user.setRegTime(regTime);
				
				// 4.把实体对象封装到List集合中
				list.add(user) ;
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(rst, stmt, conn);
		}

		return list;
	}

}


七、业务包(service)

1)Service接口

package org.nf.s186.ums.service;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 业务接口
 * 	如果业务单一或在确定的情况下,可以不需要定义接口
 * 	或者也可以根据实际情况,后期根据需求,重构代码再定义此接口
 * 
 * @author Administrator
 *
 */
public interface UserInfoService {
	/**
	 * 登录
	 * @param username
	 * @param password
	 * @return
	 */
	public UserInfo login(String username,String password) ;
	
	
	/**
	 * 注册
	 * @param user
	 * @return
	 */
	public int register(UserInfo user) ;
}

2)Service接口实现

package org.nf.s186.ums.service.impl;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;

public class UserInfoServiceImpl implements UserInfoService {
	//查询
	@Override
	public UserInfo login(String username, String password) {
		// 第一:实例化DAO对象
		UserInfoDao userInfoDao = new UserInfoDaoImpl();

		// 第二:查询数据
		UserInfo userInfo = userInfoDao.queryUser(username, password);

		// 第三:返回结果
		return userInfo;
	}

	//注册
	@Override
	public int register(UserInfo user) {
		UserInfoDao userInfoDao = new UserInfoDaoImpl();
		return userInfoDao.insertUser(user);
	}

}

八、在servlet包创建java

package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.util.Arrays;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;
import org.nf.s186.ums.service.impl.UserInfoServiceImpl;
import org.nf.s186.ums.utils.DateUtil;

/**
 * 处理注册请求
 * @author Administrator
 *
 */
public class RegisterServlet extends HttpServlet{
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 第一:设置请求编码
		req.setCharacterEncoding("UTF-8");
		
		// 第二:获取客户端传递的数据
		String username = req.getParameter("username") ;
		String password = req.getParameter("password") ;
		String sex = req.getParameter("sex") ;
		String tel = req.getParameter("tel") ;
		String weight = req.getParameter("weight") ;
		String birth = req.getParameter("birth") ;
		String[] hobby = req.getParameterValues("hobby") ;
		
		// 第三:对传递的数据进行合法性验证(服务器验证),保证数据的合法性(安全) -- 正则表达式
		double doubleWeight = Double.parseDouble(weight);
		
		// 第四:加工处理数据(结合业务需求)
		// 1.实例化业务对象
		UserInfoService userService = new UserInfoServiceImpl() ;
		
		// 2.实例化实体对象,并初始化表单传递过来的数据
		UserInfo u = new UserInfo() ;
		
		// 3.初始化实体对象
		u.setUsername(username);
		u.setPassword(password);
		u.setSex(sex);
		u.setTel(tel);
		u.setWeight(doubleWeight);
		u.setBirth(DateUtil.stringToDate(birth, DateUtil.DATA_PATTERN));
		u.setHobby(Arrays.toString(hobby));
		
		// 4.业务处理 - 注册 
		int r = userService.register(u) ;
		
		// 第五:响应结果(打印输出或页面跳转[重定向、转发])
		String path = "index.html";
		if(r!=1) {
			path = "reg.html" ;
		} 
		resp.sendRedirect(path);
	}
}


九、配置web.xml文件,对外提供一个访问URL

  <!-- 注册  -->
  <servlet>
  	<servlet-name>RegisterServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.RegisterServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>RegisterServlet</servlet-name>
  	<url-pattern>/register.do</url-pattern>
  </servlet-mapping>

十、测试包(test)

package org.nf.s186.ums.test;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DateUtil;

public class MainTest01 {

	public static void main(String[] args) {
		// 1.实例DAO对象
		UserInfoDao userInfoDao = new UserInfoDaoImpl() ;
		
		// 2.实例化实体对象
		UserInfo userInfo = new UserInfo() ;
		
		// 3.初始化实体对象
		userInfo.setUsername("Lily888");
		userInfo.setPassword("888888");
		userInfo.setHobby("吃,玩");
		userInfo.setSex("女");
		userInfo.setTel("111111111");
		userInfo.setWeight(50);
		userInfo.setBirth(DateUtil.stringToDate("1999-05-09", DateUtil.DATA_PATTERN));
		
		// 4.执行SQL语句
		int r = userInfoDao.insertUser(userInfo);
		
		// 5.处理结果
		if(r==1) {
			System.out.println("注册成功");
		} else {
			System.out.println("注册失败");
		}

	}

}

 

最详细的步骤 (结合JDBC,实现用户登录,注册,删除,查询,修改)

一、创建数据表(sql数据库)

二、创建项目 (Eclipse)

1、配置工作空间的编码 (Project--Properties--Resource--Other)

2、JDK

3、Tomcat (Window菜单 - Preferences - Server - Runtime Environments)

4、创建Dynamic Web Project ...( File - New - Project... - Web - Dynamic Web Project)

三、创建前端页面HTML(webapp)

1、登录(login)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户管理系统 - 用户登录</title>
</head>
<body>
	<form action="login.do" method="post">
		帐号:<input type="text" name="username" value="admin888"/><br/>
		密码:<input type="password" name="password" value="123456"/><br/>
		<input type="submit" value="登录"/>
		<!-- todo:使用样式修改按钮,并使用JS实现页面跳转到注册页面 -->
		<button type="button" onClick="goToPage('reg.html')">用户注册</button>
	</form>
	
	
	<script type="text/javascript" src="js/index.js"></script>
	
	
</body>
</html>

创建 js (使用样式修改按钮,并使用JS实现页面跳转到注册页面)
/**
	JS实现页面跳转
 */
function goToPage(page) {
	location.href = page ;
}

/**
	提示用户是否真的删除
 */
function isDel( userId ) {
	
	// confirm():弹出具有“确定”和“取消”按钮的对话框
	// 点击“确定”返回True,反之返回False
	if(window.confirm("您真的要删除此用户码?")) {
		goToPage("del.do?userId=" + userId) ;
		alert("删除成功!")
	}
	
}

2、登录成功(login-success)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录成功</title>
</head>
<body>
	<h1>登录成功,欢迎Xxx先生/小姐!退出登录</h1>
	<hr/>
	
	<table border="1" align="center" width="80%">
		<tr>
			<th>帐号</th>
			<th>电话</th>
			<th>性别</th>
			<th>体重</th>
			<th>出生</th>
			<th>爱好</th>
			<th>操作</th>
		</tr>
		
		<tr align="center">
			<td>张三</td>
			<td>110</td>
			<td>男</td>
			<td>160</td>
			<td>1995-05-02</td>
			<td>吃,喝</td>
			<td><a href="show.html">查看</a> | 删除</td>
		</tr>
		
		<tr align="center">
			<td>李四</td>
			<td>120</td>
			<td>女</td>
			<td>60</td>
			<td>1998-05-02</td>
			<td>玩,乐</td>
			<td><a href="show.html">查看</a> | 删除</td>
		</tr>
		
		<tr align="center">
			<td>王五</td>
			<td>120</td>
			<td>男</td>
			<td>180</td>
			<td>1997-05-02</td>
			<td>吃,玩</td>
			<td><a href="show.html">查看</a> | 删除</td>
		</tr>
	</table>
</body>
</html>

3、登录失败(login-error)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录失败</title>
</head>
<body>
	<h1>错误的帐号或密码,登录失败!
		请重新<a href="index.html">登录</a>或
		<a href="reg.html">注册</a>
	</h1>
</body>
</html>

4、查看(show)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>查看用户</title>
</head>
<body>
	<h1>查看用户<span style="color:red;font-weight:bold">李四</span>明细</h1>
	<hr/>
	<form>
		帐号:<input type="text" value="李四"/><br/>
		电话:<input type="text" value="120"/><br/>
		性别:
			<input type="radio" name="sex" value="男"/>男
			<input type="radio" name="sex" value="女" checked/>女
		<br/>
		体重:<input type="text" value="60"/><br/>
		出生:<input type="text" value="1998-05-02"/><br/>
		爱好:
			<input type="checkbox" name="hobby" value="吃"/>吃
			<input type="checkbox" name="hobby" value="喝"/>喝
			<input type="checkbox" name="hobby" value="玩" checked/>玩
			<input type="checkbox" name="hobby" value="乐" checked/>乐
			<br/>
		<input type="submit" value="修改"/>
		<input type="button" value="返回"/><br/>
	</form>
</body>
</html>

5、注册(register)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户注册</title>
</head>
<body>
	<h1>用户注册</h1>
	<hr/>
	<form action="register.do" method="post">
		帐号:<input type="text" name="username"/><br/>
		密码:<input type="password" name="password"/><br/>
		电话:<input type="text" name="tel"/><br/>
		性别:
			<input type="radio" name="sex" value="男" id="man" checked/>
			<label for="man">男</label>
			
			<input type="radio" name="sex" value="女" id="woman"/>
			<label for="woman">女</label>
		<br/>
		体重:<input type="text" name="weight"/><br/>
		出生:<input type="text" name="birth"/><br/>
		爱好:
			<input type="checkbox" name="hobby" value="吃" id="eat"/>
			<label for="eat">吃</label>
			
			<input type="checkbox" name="hobby" value="喝" id="drink"/>
			<label for="drink">喝</label>
			
			<input type="checkbox" name="hobby" value="玩" id="play"/>
			<label for="play">玩</label>
			
			<input type="checkbox" name="hobby" value="乐" id="happy"/>
			<label for="happy">乐</label>
			<br/>
		<input type="submit" value="注册"/><br/>
	</form>
</body>
</html>

6、修改失败(update-error)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>修改失败</title>
</head>
<body>
	<h1>修改用户失败,<a href='welcome.do'>返回</a></h1>
</body>
</html>

四、编写后台JAVA代码 (src/main/java)

com|org.公司名称.组织名称.项目名称.模块名称.Xxxx.java

1、工具包(utils)(固定的,一定要记住)-(注意:要把连接驱动jar包(jtds-1.3.1.jar),添加到项目的lib目录 ==步骤:右击Deployment Descriptor:项目名 -- Generate Deployment Descriptor Stub)

连接数据库类

package org.nf.s186.ums.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 连接数据库
 * 注意:要把连接驱动jar包(jtds-1.3.1.jar),添加到项目的lib目录
 * @author zhang
 *
 */
public class DBUtil {
	/**
	 * 连接驱动程序
	 */
	private  static final String DRIVER = "net.sourceforge.jtds.jdbc.Driver" ;
	/**
	 * 连接URL
	 */
	private  static final String URL = "jdbc:jtds:sqlserver://localhost:1433;DatabaseName=ums" ;
	/**
	 * 帐号
	 */
	private  static final String USER = "sa" ;
	/**
	 * 密码
	 */
	private  static final String PASS = "mm1306612" ;
	
	
	
	static {
		// 加载驱动程序
		try {
			Class.forName(DRIVER);
		} catch (ClassNotFoundException e) {
			System.out.println("加载驱动程序失败...");
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取连接对象 -- Java程序 与 数据库之间的桥梁
	 * @return
	 */
	public static Connection getConnection() {
		Connection conn = null ;
		try {
			conn = DriverManager.getConnection(URL, USER, PASS);
		} catch (SQLException e) {
			System.out.println("获取连接对象失败...");
			e.printStackTrace();
		}
		return conn ;
	}
	
	/**
	 * 关闭相关的 JDBC 对象
	 *  DriverManager:驱动管理对象,获取连接对象
	 *  		DriverManager.getConnection(URL, USER, PASS);
	 *  
	 * 	ResultSet:结果集对象
	 * 			用于接收查询数据时,返回的结果
	 * 
	 *  Statement:语句对象 用数据库(sql)的
	 *  		用于执行SQL语句(PreparedStatement、CallableStatement)
	 *  			增、删、改:executeUpdate()
	 *  			查询:executeQuery()
	 *  		
	 *  
	 *  Connection:连接对象
	 *  		建立JAVA程序与数据库之间的桥梁
	 * 
	 * @param rst 
	 * @param stmt 
	 * @param conn 
	 */
	public static void close(ResultSet rst,Statement stmt,Connection conn) {
		if(rst!=null) {
			try {
				rst.close() ;
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		
		if(stmt!=null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		if(conn!=null) {
			try {
				conn.close() ;
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
    //main入口 输出调用
	// executeUpdate()、executeQuery() - 略 
	public static void main(String[] args) {
		System.out.println(DBUtil.getConnection());
	}
}

日期时间处理工具类

package org.nf.s186.ums.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;

/**
 * 日期时间处理工具类
 * @author Administrator
 *
 */
public class DateUtil {
	
	/**
	 * 内置常用日期模式 -- 只包含日期
	 */
	public static final String DATA_PATTERN = "yyyy-MM-dd" ;
	
	/**
	 * 内置常用日期模式 -- 只包含日间
	 */
	public static final String TIME_PATTERN = "hh:mm:ss" ;
	
	/**
	 * 内置常用日期模式 -- 同时包含日期和时间
	 */
	public static final String DATATIME_PATTERN = "yyyy-MM-dd hh:mm:ss" ;
	
	
	/**
	 * 把"指定格式"的字符串类型的日期 转换为 java.util.Date类型的日期 
	 * 使用SimpleDateFormat进行转换
	 * yyyy-MM-dd hh:mm:ss
	 * @param strDate
	 * @return
	 */
	public static java.util.Date stringToDate(String strDate,String pattern) {
		// 实例化SimpleDateFormat对象的同时,指定时间格式
		SimpleDateFormat format = new SimpleDateFormat(pattern) ;
        //声明
		java.util.Date date = null ;
		try {
            //转换
			date = format.parse(strDate);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return date ;
	}
}


2.实体包(entity、domain)

package org.nf.s186.ums.entity;

import java.util.Date;

/**
 * 实体对象 - 用户对象 - 用于封装数据、传递数据
 * 
 * 一般有多个数据表,就有多少个实体对象 
 * 	1)表中的字段就是实体对象的属性 
 *  2)对象的属性一般要私有化,且生成相关的setter/getter方法
 * 	3)根据需要,可以定义重载构造方法,而默认的构造方法一般要显示写出来
 * 
 * 命名规范: 属性名首字母小写 驼峰标识 命名有意义
 * 
 * @author zhang
 *
 */
public class UserInfo {
    //字段
	private int id;
	private String username;
	private String password;
	private String tel;
	private String sex;
	private double weight;
	private Date birth;
	private String hobby;
	private Date regTime;
	
    //属性
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public double getWeight() {
		return weight;
	}
	public void setWeight(double weight) {
		this.weight = weight;
	}
	public Date getBirth() {
		return birth;
	}
	public void setBirth(Date birth) {
		this.birth = birth;
	}
	public String getHobby() {
		return hobby;
	}
	public void setHobby(String hobby) {
		this.hobby = hobby;
	}
	public Date getRegTime() {
		return regTime;
	}
	public void setRegTime(Date regTime) {
		this.regTime = regTime;
	}
	/**
	 * 默认(缺省)构造方法
	 * 
	 * 注意:当重载构造方法后,缺省构造方法就会被丢失
	 * 因此,一般我们会手动补回来
	 */
	public UserInfo() {}
	/**
	 * 重载构造方法 - 便于初始化对象 - 帐号、密码、手机号码
	 * @param username
	 * @param password
	 * @param tel
	 */
	public UserInfo(String username, String password, String tel) {
		this.username = username;
		this.password = password;
		this.tel = tel;
	}
	
	
}


3.数据访问对象包(dao)

1)DAO接口

package org.nf.s186.ums.dao;

import java.util.List;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 定义 用户信息表(用户对象) 的相关数据操作接口
 * 
 * 接口定义了相关的标准、规范,用于指定对象能做什么事情,
 * 		具体什么行为,但没有具体的实现。
 * 		具体的实现根据实际情况,定义相关的实现类实现(多态)。
 * 
 * 便于程序的扩展和维护
 * 	
 * 
 * DAO:数据访问对象(Data Access Object),
 * 		数据相关操作的对象,一般服务于业务对象,不包含相关的业务操作,只是单纯的实现数据操作(CRUD)
 * 		如果有相关业务就提取到业务对象实现;
 * 		如果没有相关业务代码或简单的业务可以直接在Servlet实现,而不需要业务对象
 * 
 * @author Administrator
 *
 */
public interface UserInfoDao {
	/**
	 * 根据帐号和密码查询用户,服务于登录业务
	 * @param username
	 * @param password
	 * @return
	 */
	public UserInfo queryUser(String username,String password) ;
	
	
	// 增、删、改、各种查询...
	/**
	 * 添加用户信息 
	 * @param userinfo 实体对象(用户的相关信息封装)
	 * @return 受影响行数
	 */
	public int insertUser(UserInfo userinfo) ;
	
	/**
	 * 根据用户编号删除数据
	 * @param id 用户编号
	 * @return 受影响行数
	 */
	public int deleteUser(int id) ;
	
	/**
	 * 修改用户
	 * @param userinfo 实体对象
	 * @return 受影响行数
	 */
	public int updateUser(UserInfo userinfo) ;
	
	/**
	 * 查询所有用户信息,除了当前登录用户,避免自己把自己删除了
	 * @param id
	 * @return
	 */
	public List<UserInfo> queryUserList(int id) ;
	
	
	
	/**
	 * 根据用户ID查询用户信息 - 服务于查看用户详情
	 * @param id
	 * @return
	 */
	public UserInfo queryUserById(int id) ;
	
	
}


2)DAO接口实现

package org.nf.s186.ums.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DBUtil;

/**
 * UserDao接口的实现类
 * 
 * 根据需要,可以定义多个DAO接口的实现类,从而解决不同需求的情况
 * 
 * 
 * @author Administrator
 *
 */
public class UserInfoDaoImpl implements UserInfoDao {

    //重写根据帐号和密码查询用户,服务于登录业务的方法
	@Override
	public UserInfo queryUser(String username, String password) {
		//声明
		UserInfo user = null;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "select * from userinfo where username=? and password=?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();

		// 第三:获取语句对象
		PreparedStatement stmt = null;
		ResultSet rst = null;

		try {
			// 1.预编译SQL语句
			stmt = conn.prepareStatement(sql);
			// 2.填充数据
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			stmt.setString(1, username);
			stmt.setString(2, password);

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			rst = stmt.executeQuery();

			// 第五:处理SQL语句返回的结果
			if (rst.next()) {
				// 1.实例化对象
				user = new UserInfo();

				// 2.读取各个字段的数据
				// 语法如下:
				// 1)结果集对象.getXxx(字段索引)
				// 2)结果集对象.getXxx(字段列名)
				int userId = rst.getInt(1);
				String name = rst.getString(2);
				String tel = rst.getString(4);
				String sex = rst.getString(5);
				double weight = rst.getDouble(6);
				java.sql.Date birth = rst.getDate(7);
				String hobby = rst.getString(8);
				java.sql.Timestamp regTime = rst.getTimestamp(9);

				// 3.封装数据
				user.setId(userId);
				user.setUsername(name);
				user.setTel(tel);
				user.setSex(sex);
				user.setWeight(weight);
				user.setBirth(birth);
				user.setHobby(hobby);
				user.setRegTime(regTime);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(rst, stmt, conn);
		}

		return user;
	}

    //重写添加用户信息的方法
	@Override
	public int insertUser(UserInfo userinfo) {
        //定义变量
		int row = 0;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "insert into userinfo(username,password,tel,sex,weight,birth,hobby) values (?,?,?,?,?,?,?)";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();
		PreparedStatement pstmt = null;

		try {
			// 第三:获取语句对象
			// 1.预编译SQL语句
			pstmt = conn.prepareStatement(sql);
			// 2.填充数据 - 把SQL语句补充完整
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			pstmt.setString(1, userinfo.getUsername());
			pstmt.setString(2, userinfo.getPassword());
			pstmt.setString(3, userinfo.getTel());
			pstmt.setString(4, userinfo.getSex());
			pstmt.setDouble(5, userinfo.getWeight());

			// 获取出生日期的毫秒数
			long longBirth = userinfo.getBirth().getTime();
			// 把java.util.Date转换为java.sql.Date
			java.sql.Date birth = new java.sql.Date(longBirth);

			pstmt.setDate(6, birth);
			pstmt.setString(7, userinfo.getHobby());

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			row = pstmt.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(null, pstmt, conn);
		}

		// 第五:处理SQL语句返回的结果
		return row;
	}

	@Override
	public int deleteUser(int id) {
		int row = 0;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "delete from userinfo where id=?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();
		PreparedStatement pstmt = null;

		try {
			// 第三:获取语句对象
			// 1.预编译SQL语句
			pstmt = conn.prepareStatement(sql);
			// 2.填充数据 - 把SQL语句补充完整
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			pstmt.setInt(1, id);
	

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			row = pstmt.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(null, pstmt, conn);
		}

		// 第五:处理SQL语句返回的结果
		return row;
	}

	@Override
	public int updateUser(UserInfo userinfo) {
		int row = 0;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "update userinfo set username=?,tel=?,sex=?,weight=?,birth=?,hobby=? where id=?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();
		PreparedStatement pstmt = null;

		try {
			// 第三:获取语句对象
			// 1.预编译SQL语句
			pstmt = conn.prepareStatement(sql);
			// 2.填充数据 - 把SQL语句补充完整
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			pstmt.setString(1, userinfo.getUsername());
			pstmt.setString(2, userinfo.getTel());
			pstmt.setString(3, userinfo.getSex());
			pstmt.setDouble(4, userinfo.getWeight());


			// 获取出生日期的毫秒数
			long longBirth = userinfo.getBirth().getTime();
			// 把java.util.Date转换为java.sql.Date
			java.sql.Date birth = new java.sql.Date(longBirth);

			pstmt.setDate(5, birth);
			pstmt.setString(6, userinfo.getHobby());
			pstmt.setInt(7, userinfo.getId());

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			row = pstmt.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(null, pstmt, conn);
		}

		// 第五:处理SQL语句返回的结果
		return row;
	}

	@Override
	public List<UserInfo> queryUserList(int id) {
		List<UserInfo> list = new ArrayList<>();

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "select * from userinfo where id != ?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();

		// 第三:获取语句对象
		PreparedStatement stmt = null;
		ResultSet rst = null;

		try {
			// 1.预编译SQL语句
			stmt = conn.prepareStatement(sql);
			// 2.填充数据
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			stmt.setInt(1, id);

			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			rst = stmt.executeQuery();

			// 第五:处理SQL语句返回的结果
			while (rst.next()) {
				// 1.实例化对象
				UserInfo user = new UserInfo();

				// 2.读取各个字段的数据
				// 语法如下:
				// 1)结果集对象.getXxx(字段索引)
				// 2)结果集对象.getXxx(字段列名)
				int userId = rst.getInt(1);
				String name = rst.getString(2);
				String tel = rst.getString(4);
				String sex = rst.getString(5);
				double weight = rst.getDouble(6);
				java.sql.Date birth = rst.getDate(7);
				String hobby = rst.getString(8);
				java.sql.Timestamp regTime = rst.getTimestamp(9);

				// 3.封装数据
				user.setId(userId);
				user.setUsername(name);
				user.setTel(tel);
				user.setSex(sex);
				user.setWeight(weight);
				user.setBirth(birth);
				user.setHobby(hobby);
				user.setRegTime(regTime);

				// 4.把实体对象封装到List集合中
				list.add(user);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(rst, stmt, conn);
		}

		return list;
	}

	@Override
	public UserInfo queryUserById(int id) {
		UserInfo user = null;

		// 第一:定义操作数据库的SQL语句,具体数据使用 ? 占位
		String sql = "select * from userinfo where id=?";

		// 第二:获取连接对象
		Connection conn = DBUtil.getConnection();

		// 第三:获取语句对象
		PreparedStatement stmt = null;
		ResultSet rst = null;

		try {
			// 1.预编译SQL语句
			stmt = conn.prepareStatement(sql);
			// 2.填充数据
			// 语法:语句对象.setXxx(占位符索引,数据) ;
			// Xxx表示属性/字段的具体数据类型
			stmt.setInt(1, id);


			// 第四:执行SQL语句
			// 语法如下:
			// 1)增、删、改:int 变量 = 语句对象.executeUpdate()
			// 2)查询:ResultSet 变量 = 语句对象.executeQuery()
			rst = stmt.executeQuery();

			// 第五:处理SQL语句返回的结果
			if (rst.next()) {
				// 1.实例化对象
				user = new UserInfo();

				// 2.读取各个字段的数据
				// 语法如下:
				// 1)结果集对象.getXxx(字段索引)
				// 2)结果集对象.getXxx(字段列名)
				int userId = rst.getInt(1);
				String name = rst.getString(2);
				String tel = rst.getString(4);
				String sex = rst.getString(5);
				double weight = rst.getDouble(6);
				java.sql.Date birth = rst.getDate(7);
				String hobby = rst.getString(8);
				java.sql.Timestamp regTime = rst.getTimestamp(9);

				// 3.封装数据
				user.setId(userId);
				user.setUsername(name);
				user.setTel(tel);
				user.setSex(sex);
				user.setWeight(weight);
				user.setBirth(birth);
				user.setHobby(hobby);
				user.setRegTime(regTime);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 第六:关闭对象
			DBUtil.close(rst, stmt, conn);
		}

		return user;
	}

}


4.业务包(service)

1)Service接口

package org.nf.s186.ums.service;

import org.nf.s186.ums.entity.UserInfo;

/**
 * 业务接口
 * 	如果业务单一或在确定的情况下,可以不需要定义接口
 * 	或者也可以根据实际情况,后期根据需求,重构代码再定义此接口
 * 
 * @author Administrator
 *
 */
public interface UserInfoService {
	/**
	 * 登录
	 * @param username
	 * @param password
	 * @return
	 */
	public UserInfo login(String username,String password) ;
	
	
	/**
	 * 注册
	 * @param user
	 * @return
	 */
	public int register(UserInfo user) ;
}


2)Service接口实现

package org.nf.s186.ums.service.impl;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;

public class UserInfoServiceImpl implements UserInfoService {

	@Override
	public UserInfo login(String username, String password) {
		// 第一:实例化DAO对象
		UserInfoDao userInfoDao = new UserInfoDaoImpl();

		// 第二:查询数据
		UserInfo userInfo = userInfoDao.queryUser(username, password);

		// 第三:返回结果
		return userInfo;
	}

	@Override
	public int register(UserInfo user) {
		UserInfoDao userInfoDao = new UserInfoDaoImpl();
		return userInfoDao.insertUser(user);
	}

}


5.Servlet包(servlet、controller、web)

1、登录
package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;
import org.nf.s186.ums.service.impl.UserInfoServiceImpl;

/**
 * 处理登录的服务器程序
 * @author Administrator
 *
 */
public class LoginServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		resp.setContentType("text/html;charset=utf-8");
		resp.setCharacterEncoding("utf-8") ;
		PrintWriter out = resp.getWriter() ;
		
		// 第一:获取用户输入的数据
		String username = req.getParameter("username");
		String password = req.getParameter("password");
		
		// 对数据进行合法性验证
		if(username==null || "".equals(username.trim())) {
			out.print("用户名不能为空,<a href='index.html'>返回</a>") ;
			out.flush();
			out.close();
			return ;
		}
		
		if(password==null || "".equals(password.trim())) {
			out.print("密码不能为空,<a href='index.html'>返回</a>") ;
			out.flush();
			out.close();
			return ;
		}
		
		// 第二:实例化业务对象
		UserInfoService userInfoService = new UserInfoServiceImpl() ;
		
		// 第三:处理
		UserInfo userInfo = userInfoService.login(username, password);
		
		// 第四:响应
		// 登录失败,默认跳转的页面
		String path = "error.html" ;
		
		// 登录成功
		if(userInfo!=null) {
			// 1.把登录帐号,存储在请求作用域中,便于数据传递 
			// 注意:在实际开发中,我们把帐号存储在会话作用域中
			// req.setAttribute("loginUser", userInfo);
			// req.getSession().setAttribute("loginUser", userInfo);
			
			HttpSession session = req.getSession() ;
			session.setAttribute("loginUser", userInfo);
			
			// 2.设置登录成功,跳转的页面
			path = "welcome.do" ;
		}
		
		// 1.页面跳转 -- 重定向
		resp.sendRedirect(path);
		
		// 2.页面跳转 -- 转发
		// req.getRequestDispatcher(path).forward(req, resp);
		
		
		
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.doPost(req, resp);
	}
}


2、登录成功
package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;

/**
 * 后面首页
 * 
 * @author Administrator
 *
 */
public class WelcomeServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		// 设置响应编码
		resp.setContentType("text/html;charset=utf-8");
		resp.setCharacterEncoding("utf-8") ;
		
		// 获取打印输出流对象
		PrintWriter out = resp.getWriter() ;
		
		// 获取请求作用域传递过来的数据
		// UserInfo userInfo = (UserInfo)req.getSession().getAttribute("loginUser");
		HttpSession session = req.getSession() ;
		UserInfo userInfo = (UserInfo)session.getAttribute("loginUser");
		
		
		// 判断在会话中是否存在登录的用户 -- 防止用法在没有登录的情况下,访问服务器资源
		if(userInfo==null) {
			out.print("对不起,你没有权限!请<a href='index.html'>登录</a>") ;
			out.flush();
			out.close();
			return ;
		}
		
		String msg = "欢迎" + userInfo.getUsername()  + ("男".equals(userInfo.getSex()) ? "先生" : "女士") ;
		
		out.print("<!DOCTYPE html>") ;
		out.print("<html>") ;
		out.print("<head>") ;
		out.print("<meta charset='UTF-8'>") ;
		out.print("<title>登录成功</title>") ;
		
		out.print("<script type='text/javascript' src='js/index.js'></script>") ;
		
		out.print("</head>") ;
		out.print("<body>") ;
		out.print("<h1>用户信息管理系统</h1>") ;
		out.print("<h3>" + msg + "</h3>") ;
		out.print("<h3><a href='logout.do'>退出登录</a></h3>") ;
		out.print("<hr/>") ;
		
		out.print("<table border='1' align='center' width='80%'>") ;
		out.print("<tr>") ;
		out.print("<th>帐号</th>") ;
		out.print("<th>电话</th>") ;
		out.print("<th>性别</th>") ;
		out.print("<th>体重</th>") ;
		out.print("<th>出生</th>") ;
		out.print("<th>爱好</th>") ;
		out.print("<th>操作</th>") ;
		out.print("</tr>") ;
		
		UserInfoDao dao = new UserInfoDaoImpl() ;
		List<UserInfo> list = dao.queryUserList(userInfo.getId()) ;
		
		// 如果集合没有数据,则显示“数据为空!”
		if(list==null || list.size()==0) {
			out.print("<tr align='center'>") ;
			out.print("<td colspan='7'>");
			out.print("<span style='color:red'>数据为空!</span>") ;
			out.print("</td>") ;
			out.print("</tr>");
		} else {
			// 如果集合有数据,则循环遍历出来 
			for(UserInfo u : list) {
				out.print("<tr align='center'>") ;
				out.print("<td>"+u.getUsername()+"</td>") ;
				out.print("<td>"+u.getTel()+"</td>") ;
				out.print("<td>"+u.getSex()+"</td>") ;
				out.print("<td>"+u.getWeight()+"</td>") ;
				out.print("<td>"+u.getBirth()+"</td>") ;
				out.print("<td>"+u.getHobby()+"</td>") ;
				// URL重写传参
				out.print("<td><a href='show.do?userId="+u.getId()+"'>查看</a> | <a href='#' onclick='isDel("+u.getId()+")'>删除</a></td>") ;
				out.print("</tr>") ;
			}
		}
		
		out.print("</table>") ;
		out.print("</body>") ;
		out.print("</html>") ;
		
		// 关闭对象
		out.flush();
		out.close();
	}
	
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.doPost(req, resp);
	}
}


3、退出登录
package org.nf.s186.ums.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * 实现退出登录(注销帐号)
 * @author Administrator
 *
 */
public class LogoutServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;


	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// req.getSession().invalidate();
		// 1.获取会话对象的实例
		HttpSession session = req.getSession() ;
		
		// 2.让会话失效 -- 会话对象存储的用户信息也就没有了
		session.invalidate(); 
		
		// 3.重定向到登录页面
		resp.sendRedirect("index.html");
	}
}


4、查看
package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;

/**
 * 根据用户编号,查看用户详情
 * @author zing
 *
 */
public class ShowUserServlet extends HttpServlet{

	private static final long serialVersionUID = 1L;

	@Override 
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		// 设置响应编码
		resp.setContentType("text/html;charset=utf-8");
		resp.setCharacterEncoding("utf-8") ;
		
		// 获取打印输出流对象
		PrintWriter out = resp.getWriter() ;
		
		
		HttpSession session = req.getSession() ;
		UserInfo userInfo = (UserInfo)session.getAttribute("loginUser");
		// 判断在会话中是否存在登录的用户 -- 防止用法在没有登录的情况下,访问服务器资源
		if(userInfo==null) {
			out.print("对不起,你没有权限!请<a href='index.html'>登录</a>") ;
			out.flush();
			out.close();
			return ;
		}
		
		
		
		// 获取请求参数 - 用户ID
		String userId = req.getParameter("userId") ;
		
		// 对获取数据进行合法性验证 -- 正则表达式 
		String reg = "\\d{1,}" ;
		
		boolean isOk = userId.matches(reg) ;
		if(!isOk) {
			out.print("<h1>非法操作,您传递的参数 " + userId + " 有误</h1>") ;
			out.append("<a href='welcome.do'>返回</a>") ;
			// 返回,程序不往下执行
			return ;
		} 
		
		
		// 必须保证 userId 这个字符串是一个合法的"数值"字符串,如:"123"
		int id = Integer.parseInt(userId) ;
		
		// 实例化DAO对象
		UserInfoDao userInfoDao = new UserInfoDaoImpl() ;
		
		// 根据用户ID查询用户的明细
		UserInfo u = userInfoDao.queryUserById(id);
		
		
		out.print("<!DOCTYPE html>") ;
		out.print("<html>") ;
		out.print("<head>") ;
		out.print("<meta charset='UTF-8'>") ;
		out.print("<title>查看用户</title>") ;
		out.print("</head>") ;
		out.print("<body>") ;
		out.print("<h1>查看用户<span style='color:red;font-weight:bold'>"+u.getUsername()+"</span>明细</h1>") ;
		out.print("<hr/>") ;
		out.print("<form action='user/update.do' method='post'>") ;
		out.print("帐号:<input type='text' name='username' value='"+u.getUsername()+"'/><br/>") ;
		
		// 注意:表单隐藏域 - “悄悄地”把数据传递给服务器
		out.print("<input type='hidden' name='userId' value='"+u.getId()+"'/>") ;
		out.print("电话:<input type='text' name='tel' value='"+u.getTel()+"'/><br/>") ;
		out.print("性别:") ;
		out.print("<input type='radio' name='sex' value='男' "+ ("男".equals(u.getSex())?"checked":"") +"/>男") ;
		out.print("<input type='radio' name='sex' value='女' "+ ("女".equals(u.getSex())?"checked":"") +"/>女") ;
		out.print("<br/>") ;
		out.print("体重:<input type='text' name='weight' value='"+u.getWeight()+"'/><br/>") ;
		out.print("出生:<input type='text' name='birth' value='"+u.getBirth()+"'/><br/>") ;
		out.print("爱好:") ;

		out.print("<input type='checkbox' name='hobby' value='吃' "+ (u.getHobby().contains("吃")?"checked":"") +"/>吃") ;
		out.print("<input type='checkbox' name='hobby' value='喝' "+ (u.getHobby().contains("喝")?"checked":"") +"/>喝") ;
		out.print("<input type='checkbox' name='hobby' value='玩' " + (u.getHobby().contains("玩")?"checked":"") + "/>玩") ;
		out.print("<input type='checkbox' name='hobby' value='乐' "+ (u.getHobby().contains("乐")?"checked":"") +"/>乐") ;
		out.print("<br/>") ;
		out.print("<input type='submit' value='修改'/>") ;
		out.print("<input type='button' value='返回'/><br/>") ;
		out.print("</form>") ;
		out.print("</body>") ;
		out.print("</html>") ;
		
		
		
		
		// 关闭对象
		out.flush();
		out.close();
	}
}


5、注册
package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.util.Arrays;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.service.UserInfoService;
import org.nf.s186.ums.service.impl.UserInfoServiceImpl;
import org.nf.s186.ums.utils.DateUtil;

/**
 * 处理注册请求
 * @author Administrator
 *
 */
public class RegisterServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 第一:设置请求编码
		req.setCharacterEncoding("UTF-8");
		
	
		
		// 第二:获取客户端传递的数据
		String username = req.getParameter("username") ;
		String password = req.getParameter("password") ;
		String sex = req.getParameter("sex") ;
		String tel = req.getParameter("tel") ;
		String weight = req.getParameter("weight") ;
		String birth = req.getParameter("birth") ;
		String[] hobby = req.getParameterValues("hobby") ;
		
		// 第三:对传递的数据进行合法性验证(服务器验证),保证数据的合法性(安全) -- 正则表达式
		double doubleWeight = Double.parseDouble(weight);
		
		// 第四:加工处理数据(结合业务需求)
		// 1.实例化业务对象
		UserInfoService userService = new UserInfoServiceImpl() ;
		
		// 2.实例化实体对象,并初始化表单传递过来的数据
		UserInfo u = new UserInfo() ;
		
		// 3.初始化实体对象
		u.setUsername(username);
		u.setPassword(password);
		u.setSex(sex);
		u.setTel(tel);
		u.setWeight(doubleWeight);
		u.setBirth(DateUtil.stringToDate(birth, DateUtil.DATA_PATTERN));
		u.setHobby(Arrays.toString(hobby));
		
		// 4.业务处理 - 注册 
		int r = userService.register(u) ;
		
		// 第五:响应结果(打印输出或页面跳转[重定向、转发])
		String path = "index.html";
		if(r!=1) {
			path = "reg.html" ;
		} 
		resp.sendRedirect(path);
	}
}


6、修改
package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DateUtil;

/**
 * 修改用户信息
 * 
 * @author zing
 *
 */
public class UpdateUserServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 第一:设置请求编码
		req.setCharacterEncoding("UTF-8");
		
		// 设置响应编码
		resp.setContentType("text/html;charset=utf-8");
		resp.setCharacterEncoding("utf-8");
		// 获取打印输出流对象
		PrintWriter out = resp.getWriter();

		
		// 注意:每个一个后台程序都要编写以下代码,实现用户权限认证 -- 不利于程序维护 -- 解决:过滤器
		HttpSession session = req.getSession();
		UserInfo userInfo = (UserInfo) session.getAttribute("loginUser");
		// 判断在会话中是否存在登录的用户 -- 防止用法在没有登录的情况下,访问服务器资源
		if (userInfo == null) {
			out.print("对不起,你没有权限!请<a href='index.html'>登录</a>");
			out.flush();
			out.close();
			return;
		}

		// 第二:获取客户端传递的数据
		String username = req.getParameter("username");
		String userId = req.getParameter("userId");
		String sex = req.getParameter("sex");
		String tel = req.getParameter("tel");
		String weight = req.getParameter("weight");
		String birth = req.getParameter("birth");
		String[] hobby = req.getParameterValues("hobby");

		// 第三:对传递的数据进行合法性验证(服务器验证),保证数据的合法性(安全) -- 正则表达式
		double doubleWeight = Double.parseDouble(weight);
		int id = Integer.parseInt(userId);

		// 第四:加工处理数据(结合业务需求)
		// 1.实例化业务对象
		// UserInfoService userService = new UserInfoServiceImpl() ;
		UserInfoDao userInfoDao = new UserInfoDaoImpl();

		// 2.实例化实体对象,并初始化表单传递过来的数据
		UserInfo u = new UserInfo();

		// 3.初始化实体对象
		u.setId(id);
		u.setUsername(username);
		u.setSex(sex);
		u.setTel(tel);
		u.setWeight(doubleWeight);
		u.setBirth(DateUtil.stringToDate(birth, DateUtil.DATA_PATTERN));
		u.setHobby(Arrays.toString(hobby));

		// 4.业务处理 - 注册
		// int r = userService.register(u) ;
		int r = userInfoDao.updateUser(u);

		// 第五:响应结果(打印输出或页面跳转[重定向、转发])
		String path = "../welcome.do";

		if (r != 1) {
			path = "../update-error.html";
		}

		resp.sendRedirect(path);
	}
}


7、删除
package org.nf.s186.ums.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;

/**
 * 删除用户
 * @author zhang
 *
 */
public class DeleteUserServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		resp.setContentType("text/html;charset=utf-8");
		resp.setCharacterEncoding("utf-8");
		
		PrintWriter out = resp.getWriter() ;
		
		
		HttpSession session = req.getSession() ;
		UserInfo userInfo = (UserInfo)session.getAttribute("loginUser");
		// 判断在会话中是否存在登录的用户 -- 防止用法在没有登录的情况下,访问服务器资源
		if(userInfo==null) {
			out.print("对不起,你没有权限!请<a href='index.html'>登录</a>") ;
			out.flush();
			out.close();
			return ;
		}
		
		
		// 第一:获取用户输入的数据
		String userId = req.getParameter("userId");
		
		// 对输入的数据进行合法性验证
		String reg = "\\d{1,}" ;
		boolean isOk = userId.matches(reg) ;
		
		if(!isOk) {
			// 注意:也可以通过页面跳转实现错误提示
			out.print("非法操作,您传递的参数["+userId+"]非法") ;
			out.print("<a href='welcome.do'>返回</a>") ;
			return ;
		}
		
		int id = Integer.parseInt(userId) ;
	
		// 第二:实例化业务对象
		// 第三:处理
		UserInfoDao userInfoDao = new UserInfoDaoImpl();
		int row = userInfoDao.deleteUser(id) ;

		// 第四:响应
		if(row != 1) {
			// 注意:也可以通过页面跳转实现错误提示
			out.print("对不起,删除用户失败!") ;
			out.print("<a href='welcome.do'>返回</a>") ;
			return ;
		}
	
		resp.sendRedirect("welcome.do") ;
	
	}
}


配置web.xml文件,对外提供一个访问URL

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
  <display-name>login-jdbc-demo</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  
  <!-- 登录  -->
  <servlet>
  	<servlet-name>LoginServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.LoginServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>LoginServlet</servlet-name>
  	<url-pattern>/login.do</url-pattern>
  </servlet-mapping>
  
  <!-- 退出登录  -->
  <servlet>
  	<servlet-name>LogoutServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.LogoutServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>LogoutServlet</servlet-name>
  	<url-pattern>/logout.do</url-pattern>
  </servlet-mapping>
  
  <!-- 注册  -->
  <servlet>
  	<servlet-name>RegisterServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.RegisterServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>RegisterServlet</servlet-name>
  	<url-pattern>/register.do</url-pattern>
  </servlet-mapping>
  
  
  <!-- 欢迎  -->
  <servlet>
  	<servlet-name>WelcomeServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.WelcomeServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>WelcomeServlet</servlet-name>
  	<url-pattern>/welcome.do</url-pattern>
  </servlet-mapping>
  
  <!-- 查看用户明细  -->
  <servlet>
  	<servlet-name>ShowUserServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.ShowUserServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>ShowUserServlet</servlet-name>
  	<url-pattern>/show.do</url-pattern>
  </servlet-mapping>
  
  <!-- 修改用户  -->
  <servlet>
  	<servlet-name>UpdateUserServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.UpdateUserServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>UpdateUserServlet</servlet-name>
  	<url-pattern>/user/update.do</url-pattern>
  </servlet-mapping>
  
   <!-- 修改用户  -->
  <servlet>
  	<servlet-name>DeleteUserServlet</servlet-name>
  	<servlet-class>org.nf.s186.ums.servlet.DeleteUserServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>DeleteUserServlet</servlet-name>
  	<url-pattern>/del.do</url-pattern>
  </servlet-mapping>
  
</web-app>

6.测试、运行(test)---只是检验可有可无

1、登录

package org.nf.s186.ums.test;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;

public class MainTest {

	public static void main(String[] args) {
		// 第一:定义帐号密码(模拟用户输入 )
		String username = "shangli" ;
		String password = "123456" ;
		
		// 第二:定义DAO对象,查询数据
		UserInfoDao userInfoDao = new UserInfoDaoImpl() ;
		
		// 第三:调用方法
		UserInfo user = userInfoDao.queryUser(username, password);
		
		// 第四:判断是否登录成功
		if(user==null) {
			System.out.println("登录失败");
		} else {
			System.out.println("恭喜"+user.getUsername()+",登录成功");
		}		
		
	}

}


2、注册

package org.nf.s186.ums.test;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DateUtil;

public class MainTest01 {

	public static void main(String[] args) {
		// 1.实例DAO对象
		UserInfoDao userInfoDao = new UserInfoDaoImpl() ;
		
		// 2.实例化实体对象
		UserInfo userInfo = new UserInfo() ;
		
		// 3.初始化实体对象
		userInfo.setUsername("Lily888");
		userInfo.setPassword("888888");
		userInfo.setHobby("吃,玩");
		userInfo.setSex("女");
		userInfo.setTel("111111111");
		userInfo.setWeight(50);
		userInfo.setBirth(DateUtil.stringToDate("1999-05-09", DateUtil.DATA_PATTERN));
		
		// 4.执行SQL语句
		int r = userInfoDao.insertUser(userInfo);
		
		// 5.处理结果
		if(r==1) {
			System.out.println("注册成功");
		} else {
			System.out.println("注册失败");
		}

	}

}


3、日期

package org.nf.s186.ums.test;

import org.nf.s186.ums.utils.DateUtil;

public class DateUtilTest {

	public static void main(String[] args) {
		String str = "2022-06-07" ;
		
		java.util.Date birth = DateUtil.stringToDate(str, DateUtil.DATA_PATTERN) ;
		
		System.out.println(birth);

	}

}


4、数据判断

package org.nf.s186.ums.test;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DateUtil;

public class HobbyTest {

	public static void main(String[] args) {
		String hobby = "吃,喝,玩" ;
		
		boolean bl1 = hobby.contains("吃") ;
		boolean bl2 = hobby.contains("喝") ;
		boolean bl3 = hobby.contains("玩") ;
		
		System.out.println(bl1);
		System.out.println(bl2);
		System.out.println(bl3);

	}

}


5、查询

package org.nf.s186.ums.test;

import org.nf.s186.ums.dao.UserInfoDao;
import org.nf.s186.ums.dao.impl.UserInfoDaoImpl;
import org.nf.s186.ums.entity.UserInfo;
import org.nf.s186.ums.utils.DateUtil;

public class QueryUserByIdTest {

	public static void main(String[] args) {
		// 1.实例DAO对象
		UserInfoDao userInfoDao = new UserInfoDaoImpl() ;
	
		UserInfo user = userInfoDao.queryUserById(80);
	
		if(user==null) {
			System.out.println("查无此人");
		} else {
			System.out.println(" :"+user.getUsername());
			System.out.println("性别:"+user.getSex());
			// ..
		}

	}

}


==常见异常==

1、登录失败

可能原因 - 传过来的值为空 没有这个数据

解决方法:逐步查找问题所在,找到自己认为可能错的地方 --追踪代码步骤 双击最左边的数字 -- 点击小虫子

检查是否有编码,没有则不能用中文登录

2、500错误

3、405报错

4、数据库表连接错误

--------------登录-------------

https://blog.csdn.net/weixin_43883625/article/details/94909075

--------------注册-------------

==========监听器========

一、创建前端页面HTML

二、创建Listener包

1、定义监听器 - 监听上下文对象生命周期的相关操作(创建 + 销毁)

2、定义监听器 - 监听上下文对象属性的相关操作(设置属性 + 替换属性 + 移除属性)

三、创建Servlet包

  • 定义Servlet,实现把数据设置在上下文对象中

四、配置web.xml文件,对外提供一个访问URL

====================================================================

 

一、创建前端页面HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>上下文对象属性操作监听器</title>
</head>
<body>
	<h1>上下文对象属性操作监听</h1>
	
	<h3><a href="setData.do">设置属性</a></h3>
	<h3>替换属性</h3>
	<h3>移除属性</h3>
</body>
</html>

二、创建Listener包

1、定义监听器 - 监听上下文对象生命周期的相关操作(创建 + 销毁)


2、定义监听器 - 监听上下文对象属性的相关操作(设置属性 + 替换属性 + 移除属性)


三、创建Servlet包

  • 定义Servlet,实现把数据设置在上下文对象中


四、配置web.xml文件,对外提供一个访问URL


JSP

一、案例步骤:

1、创建实体对象 (在src/main/java 创建实体对象包 和 类)

  • 字段

  • 属性

  • 无参构造函数

  • 有参构造函数

package org.ch06.entity;

public class User {

	private String name;
	private int age;
	private String sex;

	public User() {
	}

	public User(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

}


 

2、创建jsp (在webapp创建测试包 和 jsp)

  • 在JSP页面中,导入Java包

  • 在小脚本中创建List集合,用于存储多个用户

  • 在小脚本中实例化对象

  • 在小脚本中添加多个用户到List集合中

  • 创建表格

  • 在小脚本中遍历表格信息

  • 把所有实体对象的信息添加到表格中

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!--在JSP页面中,导入Java包-->    
<%@ page import="java.util.*" %>
<%@ page import="org.ch06.entity.User" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户列表</title>
</head>
<body>

	<%
		// 在小脚本中创建List集合,用于存储多个用户
		List<User> list = new ArrayList<User>() ;
	
		//实例化对象
		User u1 = new User("张三",18,"男") ;
		User u2 = new User("李四",19,"女") ;
		User u3 = new User("王五",20,"男") ;
    
		// 在小脚本中添加多个用户到List集合中
		list.add(u1) ;
		list.add(u2) ;
		list.add(u3) ;
	
	%>
	<!--创建表格-->
	<h1 align="center">用户列表</h1>
	<table border="1" width="60%" align="center">
		<tr>
			<th>姓名</th>
			<th>年龄</th>
			<th>性别</th>
		</tr>
		
        
		<%//在小脚本中遍历表格信息
			for(User u : list) {
		%>
        		<!--把所有实体对象的信息添加到表格中-->
				<tr align="center">
					<td><% out.print(u.getName()); %></td>
					<td><%= u.getAge() %></td>
					<td><%= u.getSex() %></td>
				</tr>
		<%
			}
		%>	
	</table>
</body>
</html>

二、输出日期

  • 在JSP页面中,导入Java包

  • 在小脚本中实例化Date对象

  • 打印输出

<!-- JSP指令(三个) -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 在JSP页面中,导入Java包 -->
<%@ page import="java.util.Date"%><!-- 日期 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>第一个JSP页面</title>
<!-- 
	在JSP中,与HTML一样,也可以定义相关的CSS和JS
	JSP把HTML从Servlet中脱离出来,能更好的实现页面设计 
	但是,从以下代码发现,在JSP中嵌入Java代码 -- 解决:使用EL + JSTL 
	- 实现了在JSP中再也看不到一行Java代码,但同样也能实现数据的动态更新
 -->
</head>
<body>
	<h1>第一个JSP页面</h1>
	<h3>从结构来看,JSP是一个特殊的HTML页面</h3>
	<h3>Hello,World</h3>
	
	<!-- 
		在JSP页面中,可以编写JAVA代码,并使用相关的JDK类库
		小脚本,在JSP中编写的Java代码必须写在小脚本中 
	-->
	<%
		// 实例化Date对象
		Date now = new Date() ;
	
		// 打印输出
		// 注意:在JSP中,不需要实例化,而能够直接使用的对象,我们称之为内置对象(九个)
		out.print(now) ;
	%>
	
</body>
</html>

三、页面固定

  • 创建jsp 头部

  • 创建jsp 脚部

  • 创建jsp 第一个页面

    1. 在小脚本中导入所需要的页面 (所有页面都可用)

===================================================================

创建jsp 头部

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>head</title>
</head>
<body>
	<h1 style="color:red">head...</h1>
</body>
</html>

 

创建jsp 脚部

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>foot</title>
</head>
<body>
	<h1>foot...</h1>
</body>
</html>

 

创建jsp 第一个页面

  • 在小脚本中导入所需要的页面 (所有页面都可用)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>第一个页面</title>
</head>
<body>
	<%@ include file="head.jsp" %>
	<h1>好好学习...</h1>
	<%@ include file="foot.jsp" %>
</body>
</html>

 

四、两种方式输出表达式

1、为小脚本中的内容添加样

2、小脚本输出

3、 在小脚本中计算两个数

4、EL表达式输出

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>输出表达式</title>
</head>
<body>

	<!-- 为小脚本中的内容添加样式 -->
	<h3 style="color:red"><%= "好好学习,天天向上" %></h3>
	
	
	<h3>数值:<%= 3.14 %></h3>
	
	<hr/>
	
	<%
		// 小脚本输出 
		out.print("<h3>你好</h3>") ;
	%>
	
	
	<!-- 在小脚本中计算两个数 -->
	<h3>两数之和为:<%= 100 + 200 %></h3>
	
	
	<!-- EL表达式输出 -->
	<h3>${"我好" }</h3>
	
	<h3>${100+200}</h3>
		
</body>
</html>

五、声明的使用

1、在JSP小脚本中,定义方法

2、在JSP小脚本中,定义类

3、在小脚本中计算两个数的和

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>声明的使用</title>
</head>
<body>
	<%!
		// 在JSP小脚本中,定义方法
		public int sum(int a,int b) {
			return a + b ;
		}
	
		// 在JSP小脚本中,定义类
		class User {
			private String name ;
			private int age ;
		}
	%>
	<!-- 在小脚本中计算两个数的和 -->
	两数之和为:<%=sum(100,200) %>
</body>
</html>

六、一个网页包含其他网页

1、创建第一个jsp网页

2、创建第一个jsp网页

  • 在小脚本中定义一个网页、

  • 使用include指令连接网页

七、动作指令实现转发

1、创建第一个jsp页面

  • 在小脚本中创建内置对象

  • 在小脚本中输出内容

2、创建第二个jsp页面

  • 在小脚本中设置请求编码

  • 在转发到welcome.jsp中的同时,传递参数

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>欢迎,您转发到我这里来了!</h1>
	<%
		// request.setCharacterEncoding("utf-8") ;
	
		// 在JSP中,不需要创建而直接使用的对象,称之为内置对象
		
		//在小脚本中创建内置对象
		String username = request.getParameter("username") ;
		String sex = request.getParameter("sex") ;
	%>
	
	<!-- 在小脚本中输出内容 -->
	帐号:<%=username%><br/>
	性别:<%=sex %>
	
	
</body>
</html>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>动作指令实现转发</title>
</head>
<body>
	<% 
		// 如果转发并传参为中文时,必须在“转发源文件”中设置请求编码,
		// 而“转发目标文件”不需要设置。
		
		//在小脚本中设置请求编码
		request.setCharacterEncoding("UTF-8"); 
	%>
	<!-- 作用:用户访问test01.jsp时,页面转发(页面跳转)到welcome.jsp中 -->
	
	<!-- 在转发到welcome.jsp中的同时,传递参数 -->
	<jsp:forward page="welcome.jsp">
		<jsp:param value="男" name="sex"></jsp:param>
		<jsp:param value="张三" name="username"></jsp:param>
	</jsp:forward>

</body>
</html>

 

八、动作指令实现对象操作

1、创建实体对象类

  • 字段

  • 属性

  • 无参构造函数

  • 带参构造函数

2、创建jsp页面

  • 实例化对象

  • 初始化对象

  • 获取对象的属性值

package org.ch06.entity;

public class User {

	private String name;
	private int age;
	private String sex;

	public User() {
	}

	public User(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

}


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<% %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>动作指令实现对象操作</title>
</head>
<body>
	<!-- 第一:实例化对象 -->
	<%
		// User u = new User() ;
		// u.setSex("男") ;
		// out.println(u.getSex()) ;
	%>
	
	<!-- 实例化对象 -->
	<jsp:useBean id="u" class="org.ch06.entity.User"></jsp:useBean>
	
	<!-- 初始化对象 -->
	<jsp:setProperty property="sex" name="u" value="男"/>
	<jsp:setProperty property="age" name="u" value="18"/>
	
	<!-- 获取对象的属性值 -->
	性别:<jsp:getProperty property="sex" name="u"/><br/>
	年龄:<jsp:getProperty property="age" name="u"/>
	
	
</body>
</html>

九、内置对象 -- response

1、获取请求参数的值

1)创建一个jsp页面

  • 在小脚本中获取参数值

  • 在小脚本中输出内容

2)创建一个jsp页面

  • 在小脚本中页面跳转 -- 重定向

  • 或页面跳转 -- 转发 转发传递数据

    • 与重定向一样,通过URL重写

    • 或把数据设置在请求作用域中

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>获取请求参数的值</title>
</head>
<body>
	<h1>1.欢迎光临 -- 您页面跳转过来了!</h1>
	<h3>获取请求参数的值</h3>
	<%
		// 在小脚本中获取参数值
		String uname = request.getParameter("username") ;
		String uage = request.getParameter("age") ;
	%>
	<!-- 在小脚本中输出内容 -->
	帐号:<%=uname %><br/>
	年龄:<%=uage %>
	
	
	
</body>
</html>

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>内置对象 -- response</title>
</head>
<body>
	<%
		// 页面跳转 -- 重定向 -- 重定向通过URL重写传递数据(获取请求参数的值)
		//response.sendRedirect("welcome1.jsp?username=zs&age=18") ;
	
		// 页面跳转 -- 转发 
		// 转发传递数据 -- 方法一:与重定向一样,通过URL重写(获取请求参数的值)
		//request.getRequestDispatcher("welcome1.jsp?username=zs&age=18").forward(request, response) ;
		
		// 转发传递数据 -- 方法二:把数据设置在请求作用域中(获取请求参数的值或获取请求作用域的值)
		//request.setAttribute("username", "ls") ;
		//request.setAttribute("age", 19) ;
		//request.getRequestDispatcher("welcome2.jsp").forward(request, response) ;
		//response.sendRedirect("welcome2.jsp") ;
	%>
</body>
</html>

 

2、获取请求作用域的值-1

1)创建一个jsp页面

  • 在小脚本中获取请求作用域的数据

  • 在小脚本中输出内容

2)创建一个jsp页面

  • 在小脚本中页面跳转 -- 转发 转发传递数据

    • 把数据设置在请求作用域中

<%@page import="org.apache.catalina.connector.Response"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>获取请求作用域的值</title>
</head>
<body>
	<h1>2.欢迎光临 -- 您页面跳转过来了!</h1>
	<h3>获取请求作用域的值</h3>
	<%
		// 在小脚本中获取请求作用域的数据
		String uname = (String)request.getAttribute("username") ;
		int uage = (Integer)request.getAttribute("age") ;
	%>
	<!-- 在小脚本中输出内容 -->
	帐号:<%=uname %><br/>
	年龄:<%=uage %>	
	
</body>
</html>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>内置对象 -- response</title>
</head>
<body>
	<%
//页面跳转 -- 转发 
// 转发传递数据 -- 方法二:把数据设置在请求作用域中(获取请求参数的值或获取请求作用域的值)
		//request.setAttribute("username", "ls") ;
		//request.setAttribute("age", 19) ;
		//request.getRequestDispatcher("welcome2.jsp").forward(request, response) ;
		//response.sendRedirect("welcome2.jsp") ;
	%>
</body>
</html>

3、获取请求作用域的值-2

1)创建一个jsp页面 (任意)

2)创建一个jsp页面 (5秒后,页面刷新跳转到指定页面)

<%@page import="org.apache.catalina.connector.Response"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>获取请求作用域的值</title>
</head>
<body>
	<h1>3.欢迎光临 -- 您5秒后,页面跳转过来了!</h1>
		
</body>
</html>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>内置对象 -- response</title>
</head>
<body>
	<%
		// 5秒后,页面刷新跳转到指定页面
		response.setHeader("refresh", "5;URL=welcome3.jsp") ;		
	%>
</body>
</html>

十、定义JSP页面,实现表单处理

1、创建一个jsp页面

  • 在小脚本中

    设置请求编码

    获取表单提交的数据

  • 在小脚本中输出

  • 在小脚本中有序列表遍历输出

2、创建一个jsp页面

爱好表单地址连接

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>定义JSP页面,实现表单处理(Servlet)</title>
</head>
<body>
<!-- 在小脚本中 -->
<%//设置请求编码
	request.setCharacterEncoding("utf-8") ;

	// 第一:获取表单提交的数据
	String uname = request.getParameter("username") ;
	String[] hobbys = request.getParameterValues("hobby") ;
	
	// 第二:合法性验证(正则)
	// 第三:实例化对象,封装数据
	// 第四:创建业务对象 或 DAO对象
	// 第五:响应
%>

<!-- 在小脚本中输出 -->
帐号:<%=uname %><br/>
<!-- 在小脚本中有序列表遍历输出 -->
爱好:
	<ul>
		<%
			for(String h : hobbys) {
		%>
			<li><%=h %></li>
		<%
			}
		%>
	</ul>


</body>
</html>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- 
		action属性指定为一个“服务器程序”来对此表单进行操作
		而这个服务器程序就是我们学习过的Servlet程序,在开发中,一般这么做
		当然,我们也可以指定为一个JSP页面,JSP本质上也是一个Servlet
	
	 -->
	<form action="form-do.jsp" method="post"> 
		帐号:<input type="text" name="username"/><br/>
		爱好:
			<input type="checkbox" name="hobby" value="吃"/>吃
			<input type="checkbox" name="hobby" value="喝"/>喝
			<input type="checkbox" name="hobby" value="玩"/>玩
			<input type="checkbox" name="hobby" value="乐"/>乐
		<br/>
		<input type="submit" value="提交"/>
	</form>
</body>
</html>



=======================================================================

JavaBean与EL

一、创建一个java类

1、属性 - 描述对象的特征 - 封装数据 - 成员变量

1)字段

2)默认(缺省)构造方法

3)重载构造方法

4)setter/getter方法(属性)

2、行为 - 描述对象的功能 - 封装业务 - 成员方法

编写代码,实现方法的具体功能

二、创建测试类

1、实例化对象 - 默认构造方法 - 对象的属性没有具体的数据,需要调用setter方法初始化(或 实例化对象 - 重载构造方法 - 在实例化对象的同时,初始化对象)

2、初始化对象

3、访问属性或调用方法实现相关的操作

4、调用方法 如果方法有返回值,一般使用一个与返回值类型相同的变量接收,根据需做进一步的处理

5、输出

三、创建Servlet包 -- 定义一个Servlet程序,用于展示某个用户信息

1、代替web.xml

2、默认常量

3、实例化对象

4、初始化对象

5、调用方法实现相关的操作

6、把处理的结果存放到作用域对象中

  • 把具体的数值存放到作用对象中

  • 把对象存入到作用对象中

7、页面跳转,从Serlvet转发到JSP

四、创建一个jsp页面

读取Servlet传递过来的数据,用EL表达式

  • 具体的数值

  • 对象数据

五、根据自己所需编写web.xml


 

一、创建一个java类

1、属性 - 描述对象的特征 - 封装数据 - 成员变量

1)字段

2)默认(缺省)构造方法

3)重载构造方法

4)setter/getter方法(属性)

2、行为 - 描述对象的功能 - 封装业务 - 成员方法

编写代码,实现方法的具体功能

package org.ch07;

/**
 * 第一:定义类
 * @author Administrator
 *
 */
public class Student {
    // 1.属性 - 描述对象的特征 - 封装数据 - 成员变量
    // 访问修饰符 数据类型 变量名称 ;
	private String name ;
	private int age ;
	
	//2. 默认(缺省)构造方法
	public Student() {}
	
    //3. 重载构造方法 - 当重载构造方法后,默认构造方法将丢失
	// 在实际开发中,一般把默认构造方法显式的定义回来
    public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}
    
    //4. setter/getter方法(属性)
    public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
    
    
	// 2.行为 - 描述对象的功能 - 封装业务 - 成员方法
    
	
	
	//访问修饰符 数据类型 方法名([数据类型 形参名称1,...,数据类型 形参名称2]) {
        // 编写代码,实现方法的具体功能
    //    [return 处理结果 ;]
    //}
	public int sum(int num1,int num2) {
		// 编写代码,实现方法的具体功能
		int jieGuo = num1 + num2 ;
	    return jieGuo ;
	}
}


 

二、创建测试类

1、实例化对象 - 默认构造方法 - 对象的属性没有具体的数据,需要调用setter方法初始化(或 实例化对象 - 重载构造方法 - 在实例化对象的同时,初始化对象)

2、初始化对象

3、访问属性或调用方法实现相关的操作

4、调用方法 如果方法有返回值,一般使用一个与返回值类型相同的变量接收,根据需做进一步的处理

5、输出

package org.ch07;

public class MainTest {

	public static void main(String[] args) {
		// 第二:实例化对象 - 默认构造方法 - 对象的属性没有具体的数据,
		// 需要调用setter方法初始化
		Student zs = new Student() ;
		
		// 第三:初始化对象
		zs.setName("张三");
		zs.setAge(19);
		
		// 实例化对象 - 重载构造方法 - 在实例化对象的同时,初始化对象
		// Student ls = new Student("李四", 18);
		
		// 第四:访问属性或调用方法实现相关的操作
		System.out.println(zs.getName());
		System.out.println(zs.getAge());
		
		// 注意:传递参数时,根据参数的个数,顺序,类型进行传递
		// 调用方法 如果方法有返回值,一般使用一个与返回值类型相同的变量接收,根据需做进一步的处理
		int he = zs.sum(100, 200) ;
		
		//输出
		System.out.println("和为:"+he);
		
		
	}

}


 

三、创建Servlet包 -- 定义一个Servlet程序,用于展示某个用户信息

1、代替web.xml

2、默认常量

3、实例化对象

4、初始化对象

5、调用方法实现相关的操作

6、把处理的结果存放到作用域对象中

  • 把具体的数值存放到作用对象中

  • 把对象存入到作用对象中

7、页面跳转,从Serlvet转发到JSP

package org.ch07.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.ch07.Student;

/**
 * 定义一个Servlet程序,用于展示某个用户信息
 * 
 * @author Administrator
 *
 */

//代替web.xml
@WebServlet("/show.do")
public class ShowUserServlet extends HttpServlet {
	//默认常量
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		// 第一:实例化对象
		Student zs = new Student() ;
		
		// 第二:初始化对象
		zs.setName("张三");
		zs.setAge(18);
		
		// 第三:调用方法实现相关的操作
		int he = zs.sum(100, 200);
		
		// 第四:把处理的结果存放到作用域对象中
		// 1.把具体的数值存放到作用对象中
		req.setAttribute("sum", he);
		
		// 2.把对象存入到作用对象中
		req.setAttribute("user", zs);
		
		// 第五:页面跳转,从Serlvet转发到JSP
		req.getRequestDispatcher("showUser.jsp").forward(req, resp);
		
	
		
	}

}


 

四、创建一个jsp页面

读取Servlet传递过来的数据,用EL表达式

  • 具体的数值

  • 对象数据

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>在JSP页面中,读到Servlet传递过来的数据</title>
</head>
<body>
	<h1>读取Servlet传递过来的数据</h1>
	<h3>1.具体的数值:${sum }</h3>
	
	<h3>2.对象数据</h3>
	<h3>帐号:${ user.name }</h3>
	<h3>年龄:${ user["age"] }</h3>
</body>
</html>

五、根据自己所需编写web.xml

	<jsp-config>
		<jsp-property-group>
			<url-pattern>*.jsp</url-pattern>
			<el-ignored>false</el-ignored>
		</jsp-property-group>
	</jsp-config>

JSTL

1、创建实体对象

  • 字段

  • 属性

  • 无参构造函数

  • 带参构造函数

2、创建servlet包

查看所有的用户

  • web.xml

  • 默认

  • 定义集合

  • 初始化数据

  • 把集合数据设置在相关的作用域对象中

  • 转发

3、创建jsp页面

  • 创建表格

    多条件

====================================

一、创建数据库(sql数据库)

二、创建项目(Eclipse)

三、创建前端页面HTML(webapp)

四、编写后台JAVA代码 (src/main/java)

com|org.公司名称.组织名称.项目名称.模块名称.Xxxx.java

==========A==============================================

一、创建数据库(sql数据库)

1.创建数据库

2.切换到数据库

3.创建数据表

4.添加初始化数据

二、创建项目(Eclipse)

1、配置工作空间的编码 (Project--Properties--Resource--Other)

2、配置JDK

 3、配置Tomcat (Window菜单 - Preferences - Server - Runtime Environments)

4、创建Dynamic Web Project ...( File - New - Project... - Web - Dynamic Web Project)

三、创建前端页面HTML(webapp)

1、登录(login)--创建 js (使用样式修改按钮,并使用JS实现页面跳转到注册页面)

2、登录成功(login-success)

3、登录失败(login-error)

4、查看(show)

5、注册(register)

6、修改失败(update-error)

四、编写后台JAVA代码 (src/main/java)

com|org.公司名称.组织名称.项目名称.模块名称.Xxxx.java

1、工具包(utils)(固定的,一定要记住)-(注意:要把连接驱动jar包(jtds-1.3.1.jar),添加到项目的lib目录     ==步骤:右击Deployment Descriptor:项目名 -- Generate Deployment Descriptor Stub)

2.实体包(entity、domain)

3.数据访问对象包(dao)

4.业务包(service)

5.Servlet包(servlet、controller、web)

6、配置web.xml文件,对外提供一个访问URL

7、测试、运行(test)---只是检验可有可无

=============B======================

1、登录(login)--创建 js (使用样式修改按钮,并使用JS实现页面跳转到注册页面)

1、标题

2、表单--帐号 密码 按钮(登录、注册)(注册按钮 -- 使用样式修改按钮,并使用JS实现页面跳转到注册页面)

创建 js (使用样式修改按钮,并使用JS实现页面跳转到注册页面)

1、JS实现页面跳转

2、提示用户是否真的删除

2、登录成功(login-success)

1、标题

2、表单

3、登录失败(login-error)

1、标题

2、使用超链接跳转到其他页面

===========================

案例步骤:

只要是接口都是画大饼

web.xml的路径一定要是唯一的

最后添加 右击项目--folder--创建(放数据库数据)

创建数据库

创建项目

---检查项目的编码是否是 UTF-8(右击项目--Properties--Resource)

---- 要把连接驱动jar包(jtds-1.3.1.jar),添加到项目的lib目录

编写后台JAVA代码 (src/main/java)

包要命名规范 org/com.数据库名.模块名称....

1、工具包(utils)---存放项目相关工作类的包

===连接数据库类===

1、连接驱动程序

2、连接URL

3、帐号

4、密码

5、加载驱动程序

6、获取连接对象 -- Java程序 与 数据库之间的桥梁

7、关闭相关的 JDBC 对象

8、测试

2、实体包(entity)---存放实体类的包

===实体对象 - 用户对象 - 用于封装数据、传递数据===

1、字段

2、属性

3、缺省构造方法(默认可以不编写)

3、数据访问对象包(dao、.dao.impl)

---存放dao接口的包

===用户数据访问接口 - 标准 - 规范===

1、增

2、删

3、改

4、查 - 查询所有 - 返回多个数据

5、查 - 根据ID查询 - 返回唯一数据

6、查 - 服务于登录

7、查 - 查询所有 + 分页 - 返回多个数据

8、查 - 条件查询(精确、模糊) + 分页 - 返回多个数据

---存放dao接口实现类的包

===UserDao接口的实现类 - 接口的其中的一种实现(方案)===

第一:定义操作数据库的SQL语句

第二:获取连接对象 - 导包:ctrl + shift + o

第三:获取语句对象

第四:填充SQL语句

第五:执行SQL语句(更新操作、查询操作)

第六:处理执行结果
	
	1.获取当前行中,各字段的数据 - 结果集对象.getXxx(下标)
	
	2.创建实体对象
	
	3.初始化对象 - 把以上读取的各列数据,封装到实体对象中
	
第七:关闭对象	


4.业务包 (service、service.impl)

---存放service接口的包

===业务接口 - 标准 - 规范==

A、用户登录

---存放service接口实现类的包

===UserService接口的实现类 - 接口的其中的一种实现(方案)===

A1、实例化UserDao对象

A2、根据用户名称查询用户信息

A3、判断密码是否匹配

在工具包创建MD5加密类

 

5.Servlet包(servlet、controller、web)---存放Servlet程序的包

===处理用户登录类 ===

第一:获取用户提交的数据

第二:数据的合法性验证

第三:实例化业务对象或DAO对象,进行相关的处理

第四:响应结果

	1.登录失败

	2.登录成功

===处理用户退出登录类===

1、获取会话对象

2、让会话对象失效 -- session存储的用户信息也就没有了

3、页面跳转到登录页面

创建错误的提示信息包

1、字段

2、属性

3、缺省方法

4、重载方法

7、跟登录有关的页面(JSP)

登录 --- 创建css页面--- 创建js页面

一、<link>标签
在一个html文件中,link标签还包含许多其它属性,其中最常见的是使用link元素链接外部的CSS样式表,语法如下:

<link type="text/css"rel="stylesheet" href="style.css"></link>

link标签需要用一个反斜杠结束,这样才符合W3C标准,上述语法用html语言解释为:
	link type="定义当前文本内容以层叠样式表(CSS)来解析"

	rel="定义当前文档与被链接文档之间的关系,这里是调用外部文件,stylesheet即代表css样式表。"

	href="定义被链接文档的位置,这里链接所指向的是:同一目录下名为style.css的文件。"
===========================================================	
二、<script> 标签
1、<script> 标签的定义
	1)<script> 标签用于定义当前网页文档的脚本语言,比如:JavaScript(简称JS);

	2)<script> 标签引入脚本语言,可实现图像操作、表单验证以及更多其他动态交互作用;

	3)<script> 元素既可包含脚本语句,也可以通过 "src" 属性指向外部脚本文件;

	4)一个html文档中,可以包含多个<script> 标签。	

2、<script></script> 标签的用法
用script标签引入JavaScript脚本(简称JS)有内联方式和外联方式两种,分别详述如下:

1)内联方式
这种方式指的是在html文档中,将 JavaScript代码直接写在<script>和</scritp>标签之间。

<script type="text/javascript"> JS代码 </script>

type="text/javascript",在html5中是可选属性,可以省略不写,而在html4中,type是必选属性,不可省略!

2)外联方式
外联方式是在html文档中,通过<script> 标签的src属性引入一个外部的JS文件

<script type="text/javascript" src="外部js文件"></script>

使用了src属性引入外部JS文件,那么,<script> 元素内容就必须为空,即开始标签<script>和结束标签</scritp>之间不能有任何内容,即已经引入了外部JS文件,就不能再包括JS代码本身!

===========================================================
三、<form></form> 表单标签

<form action="目标地址"method="数据提交方式"></form>

四、<img/> 图像标签

<img src="图片地址" title="图片标题" onclick="点击事件')"/>

登录成功 --- 退出登录

=====================

创建退出登录的界面(JSP)

=====================

===异常===

1、对象名无效

检查连接的数据库名

2、

==颜色头==

red 红色
silver 银
sand 沙子色
gunmetal 青铜色
stone浅橄榄灰色 
D/melange 米灰色
cream米黄色
coffee咖啡色 
wine酒红色 
gold金
yellow 黄色
black黑色
olive橄榄色 
pink粉红色
anti gold 古铜色
natural 自然色
peach 桃色
daffod 水仙黄
coral 珊瑚色
gilt 青铜色
pewter蓝灰色 
turq 湖水蓝
bronze 红古铜色
fuchsia 粉玫色
pistac 淡黄绿色
rainbow 彩虹色
shocking red 憬红色
pink 粉红色 
salmon pink 橙红色 
baby pink 浅粉红色 
shocking pink 鲜粉红色 
brown 褐色, 茶色 
beige 灰褐色 
chocolate 红褐色, 赭石色 
sandy beige 浅褐色 
camel 驼色 
amber 琥珀色 
khaki 卡其色 
maroon 褐红色 
green 绿色 
moss green 苔绿色 
emerald green 鲜绿色 
olive green 橄榄绿 
blue 蓝色 
turquoise blue 土耳其玉色 
cobalt blue 钴蓝色, 艳蓝色 
navy blue 藏青色, 深蓝色, 天蓝色 
aquamarine blue 蓝绿色 
scarlet 绯红, 猩红 
mauve 紫红 
wine red 葡萄酒红 
purple, violet 紫色 
lavender 淡紫色 
lilac 浅紫色 
antique violet 古紫色 
pansy 紫罗兰色 
white 白色 
off-white 灰白色 
ivory 象牙色 
snowy white 雪白色 
oyster white 乳白色 
gray 灰色 
charcoal gray 炭灰色 
smoky gray 烟灰色 
misty gray 雾灰色 
BABY BLUE 浅蓝 
TIGERLILY 橘红 
STORM 雾灰 
WINTER SKY 天蓝 
VAPOR BLUE 烟灰 
OYSTER GREY 米灰 
JESTER RED 大红 
CANDY PINK 粉红 
JAFFA ORANGE 橘黄 
pale taupe 浅灰褐色 
cracker khaki 杏色 
tulip yellow 黄色 
thirsty blue 浅蓝色 
green mint 浅绿 
banana cream 香蕉黄 
Acid blue 湖色 
Amber 琥珀色 
Amethyst 紫水晶色 
Antique 古紫色 
Apple green 苹果绿 
Apricot 杏黄 
Aqua green 水绿色 
Aquamarine blue 蓝绿色 
Auburn 赤褐色 
Azure green 碧绿色 
Bay 枣色 
Baby blue 浅蓝色 
Baby pink 浅粉红色 
Beige 灰棕色 
Benzo blue 靛蓝色 
Black 黑色 
Blue 蓝色 
Blue green 竹青色 
Blue grey 蓝灰色 
Bluish white 青白色 
Bluish yellow 青黄色 
Brick red 青莲色 
Bronze black 射光黑色 
Bronze blue 射光绀蓝 
Bronze violet 射光紫蓝 
Brown 棕色 
Buff 浅黄色 
Calamine blue 淡蓝色 
Caramel 酱色 
Cardinal 深红色 
Carmine 紫红色 
Carnation 肉色 
Celeste 天青色 
Chalky 白垩 
Charcoal grey 炭灰色 
Cherry 樱桃红 
Chestnut 栗褐色 
Citrine 柠檬黄 
Cobalt blue 钴蓝色 
Cochineal 胭脂红 
Coco 黄棕色 
Contrast colot r色 
Copper red 铜色 
Coral 珊瑚色 
Cream 米色 
Crystal cream 奶油白 
Dark green 深绿色 
Dark grey 深灰色 
Delicate color 娇色 
Deep green 墨绿色 
Deep yellow 深黄色 
Dun 焦茶色 
Emerald green 鲜绿色 
Florid 鲜红 
French rose 法国红 
Garnet 暗红 
Geranium 原色红 
Gold 金 
Golden yellow 金黄色 
Green 绿色 
Grey 灰 
Hazel 赤褐色 
Hepatic 猪肝色 
Hyacinth 紫蓝色 
Indigo 靛青色 
Ivory 象牙黄 
Jade green 翠绿色 
Lavender 藕色 
Lias 淡紫色 
Light grey 淡灰色 
Lyons blue 蓝紫色 
Mandarin blue 深蓝 
Marine green 海水绿 
Maroon 枣红;茶色 
Medium blue 中蓝色 
Medium yellow 中黄色 
Milk white 乳白色 
Ming blue 藏青色 
Moss green 苔绿色 
Navy blue 海水蓝 
Nimbus grey 雨云灰色 
Ocher 赭色 
Off white 灰白 
Olive 橄榄色 
Olive green 草绿色;橄榄绿 
Opaque 不透明 
Orange 橘黄色 
Oriental ted 大红 
Peach 桃红色 
Peacock blue 孔雀蓝 
Pea green 豆绿色 
Pied 杂色 
Pink 粉红色 
Pitch black 深黑色 
Protective color 保护色 
Prussian blue 普鲁士蓝 
Purple 紫色 
Purple bronze 紫铜色 
Reddish 淡红 
Reddish yellow 浓黄 
Rich color 浓色 
Rose 玫瑰红 
Royal blue 宝蓝色 
Rust brown 鼻烟色 
Sallow 苍黄 
Salmon 橙红 
Sandy 淡茶色 
Sap green 暗绿色 
Scarlet 绯色 
Sepia 棕黑色 
Shade 颜色深浅 
Shocking pink 鲜粉红 
Silver 银色 
Sky blue 天蓝 
Slate grey 鼠灰色 
Smoky grey 雾灰色 
Snow white 雪白 
Soft color 嫩色 
Sorrel 红棕色 
Tan 浅棕色 
Tapestry red 咖啡色 
Tawny 黄褐色 
Translucent 半透明 
Transparent 透明 
Turquoise 蓝绿色 
Turquoise blue 土耳其玉色 
Ultramarine 青蓝色 
Ultramarine blue 群青 
Umber 浓茶色 
Verdigris color 铜绿色 
Vermilion 桔红;朱砂红 
Violet 紫罗兰色 
White 白色 
Wine red 葡萄红 
Yellow 黄色 
York yellow 蛋黄色 
amber 琥珀色 
antique violet 古紫色 
antiquewhite 古董白 
aqua 浅绿色 
aquamarine 碧绿色 
azure 天蓝色 
baby pink 浅粉红色 
beige 米色 
bisque 橘黄色 
black 黑色 
blanchedalmond 白杏色 
blue 蓝色 
blueviolet 紫罗兰色 
brown 棕色 
burlywood 实木色 
cadetblue 军蓝色 
camel 驼色 
charcoal gray 炭灰色 
chartreuse 黄绿色 
chocolate 巧克力色 
cobalt blue 艳蓝色 
coral 珊瑚色 
cornflowerblue 菊蓝色 
cornsilk 米绸色 
crimson 暗深红色 
cyan 青色 
magenta 洋红色 
maroon 栗色 
mauve 紫红 
mediumaquamarine 间绿色 
mediumblue 间蓝色 
mediumorchid 间紫色 
mediumpurple 间紫色 
mediumseagreen 间海蓝色 
mediumslateblue 间暗蓝色 
mediumspringgreen 间春绿色 
mediumturquoise 间绿宝石色 
mediumvioletred 间紫罗兰色 
midnightblue 中灰蓝色 
mintcream 薄荷色 
misty gray 雾灰色 
mistyrose 浅玫瑰色 
moccasin 鹿皮色 
moss green 苔绿色 
navajowhite 纳瓦白 
navy 藏青 
off-white 灰白 
oldlace 老花色 
olive 橄榄色 
olivedrab 深绿褐色 
orange 橙色 
orangered 橙红色 
orchid 淡紫色 
oyster white 乳白色 
palegoldenrod 苍麒麟色 
palegreen 苍绿色 
paleturquoise 苍绿色 
palevioletred 苍紫罗蓝色 
pansy 紫罗兰色 
papayawhip 番木色 
peachpuff 桃色 
peru 秘鲁色 
pink 粉红 
plum 杨李色 
powderblue 粉蓝色 
purple 紫色  
rosybrown 褐玫瑰红 
royalblue 宝蓝色 
rubine 宝石红 
saddlebrown 重褐色 
salmon 鲜肉色 
salmon pink 橙红色 
sandy beige 浅褐色 
sandybrown 沙褐色 
sapphire 宝石蓝 
scarlet 猩红色 
seagreen 海绿色 
seashell 海贝色 
shocking pink 鲜粉红色 
sienna 赭色 
silver 银白色 
skyblue 天蓝色 
slateblue 石蓝色 
slategray 灰石色 
smoky gray 烟灰色 
snow 雪白色 
springgreen 春绿色 
steelblue 钢蓝色 
stone 石色 
tan 茶色 
teal 水鸭色 
thistle 蓟色 
tomato 番茄色 
turquoise 青绿色 
turquoise blue 翠蓝色 
violet 紫色 
wheat 浅黄色 
white 白色 
whitesmoke 烟白色 
winered 葡萄酒红 
yellow 黄色 
yellowgreen 黄绿色 
darkblue 暗蓝色 
darkcyan 暗青色 
darkgoldenrod 暗金黄色 
darkgray 暗灰色 
darkgreen 暗绿色 
darkkhaki 暗卡其色 
darkmagenta 暗洋红色 
darkolivegreen 暗橄榄绿色 
darkorange 暗桔色 
darkorchid 暗紫色 
darkred 暗红色 
darksalmon 暗肉色 
darkseagreen 暗海蓝色 
darkslateblue 暗灰蓝色 
darkslategray 墨绿色 
darkturquoise 暗宝石绿 
lightyellow 浅黄色 
lilac 浅紫色 
lime 酸橙色 
limegreen 橙绿色 
linen 亚麻色 
darkviolet 暗紫色 
deeppink 深粉色 
deepskyblue 深天蓝色 
dimgray 暗灰色 
dodgerblue 闪蓝色 
emerald green 艳绿色 
firebrick 火砖色 
floralwhite 花白色 
forestgreen 森林绿 
fuchsia 紫红色 
gainsboro 淡灰色 
ghostwhite 幽灵白 
gold 金黄色 
goldenrod 金麒麟色 
gray 灰色 
green 绿色 
greenyellow 黄绿色 
honeydew 蜜色 
hotpink 艳粉色 
indianred 印第安红 
indigo 靛蓝色 
ivory 象牙色 
khaki 卡其色 
lavender 淡紫色 
lavenderblush 淡紫红 
lawngreen 草绿色 
lemonchiffon 柠檬绸色 
lightblue 浅蓝色 
lightcoral 浅珊瑚色 
lightcyan 浅青色 
lightgoldenrodyellow 浅金黄色 
lightgreen 浅绿色 
lightgrey 浅灰色 
lightpink 浅粉色 
lightsalmon 浅肉色 
lightseagreen 浅海蓝色 
lightskyblue 浅天蓝色 
lightslategray 浅蓝灰色 
lightsteelblue 浅钢蓝色

==颜色底==

地点:报告厅二

暨大学号:2022413004041

座位号:25

专业名称:软件工程

层次:高起本

考试日期: 7月4日 星期一‘】

大学英语(1) 8:30-9:20

大学英语(2) 9:25-10:15

计算机应用 10:20-11:10

应用文写作 11:15-12:05

大学英语(3) 14:30-15:20

大学英语(4) 15:25-16:15

posted @ 2024-02-29 08:11  一只菜喵程序媛  阅读(40)  评论(0编辑  收藏  举报