JavaWeb_11_原生Web应用开发
尝试开发第一个web应用吧!
点击跳转原生Web应用开发视频
留恋相似处,令我们停滞不前;接纳相异处,带我们改变未来。
超链接
配置tomcat启动参数-Dfile.encoding=UTF-8后,IDEA(Eclipse 类似)控制台乱码
intelij idea java.lang.ClassNotFoundException
P28 JDBC复习
什么是JDBC:Java连接数据库!
需要jar包的支持:
- java.sql
- mysql-connector-java-8.0.28.jar… 连接驱动(必须导入)
实验环境搭建
- sql
CREATE TABLE users(
id INT PRIMARY KEY,
`name` VARCHAR(40),
`password` VARCHAR(40),
email VARCHAR(60),
birthday DATE
);
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'牛魔瘦了','123456','nm@qq.com','2016-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'八戒','123456','bj@qq.com','2016-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'悟空','123456','wk@qq.com','2016-01-01');
SELECT * FROM users;
- 导入数据库依赖
<!--mysql的驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
- IDEA中连接数据库
JDBC 固定步骤:
- 加载驱动
- 连接数据库,代表数据库
- 向数据库发送SQL的对象Statement,prepareStatement:CRUD
- 编写SQL(根据业务,不同的SQL)
- 执行SQL
- 关闭连接
package com.niumo.test;
import java.sql.*;
public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "nm123456";
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url,username,password);
//3.向数据库发送SQL的对象Statement,prepareStatement:CRUD
Statement statement = connection.createStatement();
//4.编写SQL
String sql = "select * from users";
//5.执行查询SQL,返回一个ResultSet:结果集
ResultSet rs = statement.executeQuery(sql);
while(rs.next()){
System.out.println("id"+rs.getObject("id"));
System.out.println("name"+rs.getObject("name"));
System.out.println("password"+rs.getObject("password"));
System.out.println("email"+rs.getObject("email"));
System.out.println("birthday"+rs.getObject("birthday"));
System.out.println("===================================");
}
//6.关闭连接,释放资源(一定要做)先开后关
rs.close();
statement.close();
connection.close();
}
}
预编译SQL
package com.niumo.test;
import java.sql.*;
public class TestJdbc2 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "nm123456";
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url,username,password);
//3.编写SQL
String sql = "insert into users (id, name, password, email, birthday) values (?,?,?,?,?);";
//4.预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,4);//给第一个占位符? 的值赋值为1;
preparedStatement.setString(2,"牛魔瘦了2");//给第二个占位符? 的值赋值为牛魔瘦了2;
preparedStatement.setString(3,"123456");//给第四个占位符? 的值赋值为123456;
preparedStatement.setString(4,"123456@qq.com");//给第五个占位符? 的值赋值为123456@qq.com;
preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));//给第一个占位符? 的值赋值为1;
//5.执行SQL
int i = preparedStatement.executeUpdate();
if(i>0){
System.out.println("插入成功!");
}
//6.关闭连接,释放资源(一定要做)先开后关
preparedStatement.close();
connection.close();
}
}
P29 JDBC事务
要么都成功,要么都失败!
ACID原则:保证数据的安全。
开启事务
事务提交 commit()
事务回滚 rollback()
关闭事务
转账:
A:1000
B:1000
A(900) --100--> B(1100)
Junit单元测试
依赖
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
简单使用
@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行!
@Test
public void test(){
System.out.println("Hello");
}
失败的时候是红色:
搭建一个环境
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(40),
money FLOAT
);
INSERT INTO account(`name`,money) VALUES('A',1000);
INSERT INTO account(`name`,money) VALUES('B',1000);
INSERT INTO account(`name`,money) VALUES('C',1000);
package com.niumo.test;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class TestJdbc3 {
@Test
public void test(){
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "nm123456";
Connection connection = null;
try{
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.连接数据库,代表数据库
connection = DriverManager.getConnection(url,username,password);
//3.通知数据库开启事务,false 开启
connection.setAutoCommit(false);
String sql1 = "update account set money = money-100 where name = 'A';";
connection.prepareStatement(sql1).executeUpdate();
//制造错误
// int i= 1/0;
String sql2 = "update account set money = money+100 where name = 'B';";
connection.prepareStatement(sql2).executeUpdate();
connection.commit(); //以上两条SQL都执行成功了,就提交事务!
System.out.println("success");
} catch (Exception e) {
//如果出现异常,就通知数据库回滚事务
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
P30 smbms项目搭建
架构图
数据库
CREATE DATABASE `smbms`;
USE `smbms`;
DROP TABLE IF EXISTS `smbms_address`;
CREATE TABLE `smbms_address`(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`contact` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '联系人姓名',
`addressDesc` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '收货地址明细',
`postCode` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '邮编',
`tel` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '联系人电话',
`createBy` BIGINT(20) DEFAULT NULL COMMENT '创建者',
`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',
`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '修改者',
`modifyDate` DATETIME DEFAULT NULL COMMENT '修改时间',
`userId` BIGINT(20) DEFAULT NULL COMMENT '用户ID',
PRIMARY KEY (`id`)
)ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
DROP TABLE IF EXISTS `smbms_bill`;
CREATE TABLE `smbms_bill`(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`billCode` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '账单编码',
`productName` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '商品名称',
`productDesc` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '商品描述',
`productUnit` VARCHAR(10) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '商品单位',
`productCount` DECIMAL(20,2) DEFAULT NULL COMMENT '商品数量',
`totalPrice` DECIMAL(20,2) DEFAULT NULL COMMENT '商品总额',
`isPayment` INT(10) DEFAULT NULL COMMENT '是否支付(1:未支付 2:已支付)',
`createBy` BIGINT(20) DEFAULT NULL COMMENT '创建者(userId)',
`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',
`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '更新者(userId)',
`modifyDate` DATETIME DEFAULT NULL COMMENT '更新时间',
`providerID` BIGINT(20) DEFAULT NULL COMMENT '供应商ID',
PRIMARY KEY (`id`)
)ENGINE=INNODB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
DROP TABLE IF EXISTS `smbms_provider`;
CREATE TABLE `smbms_provider`(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`proCode` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商编码',
`proName` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商名称',
`proDesc` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商详细描述',
`proContact` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商联系人',
`proPhone` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '联系电话',
`proAddress` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '地址',
`proFax` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '传真',
`createBy` BIGINT(20) DEFAULT NULL COMMENT '创建者(userId)',
`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',
`modifyDate` DATETIME DEFAULT NULL COMMENT '更新时间',
`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '更新者(userId)',
PRIMARY KEY (`id`)
)ENGINE=INNODB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
DROP TABLE IF EXISTS `smbms_role`;
CREATE TABLE `smbms_role`(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`roleCode` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '角色编码',
`roleName` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '角色名称',
`createBy` BIGINT(20) DEFAULT NULL COMMENT '创建者',
`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',
`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '修改者',
`modifyDate` DATETIME DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
)ENGINE=INNODB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO smbms_role(id, roleCode, roleName, createBy, creationDate)
VALUES(1,"SMBMS_ADMIN","系统管理员",1,"2022-03-10 00:00:00"),
(2,"SMBMS_MANAGER","经理",1,"2022-03-10 00:00:00"),
(3,"SMBMS_EMPLOYEE","普通员工",1,"2022-03-10 00:00:00");
DROP TABLE IS EXISTS `smbms_user`;
CREATE TABLE `smbms_user`(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`userCode` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户编码',
`userName` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户名称',
`userPassword` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户密码',
`gender` INT(10) DEFAULT NULL COMMENT '性别(1:女、2:男)',
`birthday` DATE DEFAULT NULL COMMENT '出生日期',
`phone` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '手机',
`address` VARCHAR(30) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '地址',
`userRole` BIGINT(20) DEFAULT NULL COMMENT '用户角色(取字角色表-角色id)',
`createBy` BIGINT(20) DEFAULT NULL COMMENT '创建者(userId)',
`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',
`modifyDate` DATETIME DEFAULT NULL COMMENT '更新时间',
`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '更新者(userId)',
PRIMARY KEY (`id`)
)ENGINE=INNODB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
TRUNCATE TABLE `smbms_user`;
INSERT INTO `smbms_user` (`userCode`,`userName`,`userPassword`,`gender`,`birthday`,`phone`,`address`,`userRole`)
VALUES('admin','管理员','123456',2,'1989-03-08','18583688888','成都',1),
('niumo','牛魔瘦了','123456',2,'1989-03-08','18583688888','北京',1),
('bajie','八戒','123456',2,'1989-03-08','18583688888','河南',1),
('wukong','悟空','123456',2,'1989-03-08','18583688888','重庆',2),
('zs','张三','123456',2,'1989-03-08','18583688888','新疆',2),
('ls','李四','123456',2,'1989-03-08','18583688888','哈尔滨',2),
('ww','王五','123456',2,'1989-03-08','18583688888','河北',2),
('zl','赵六','123456',2,'1989-03-08','18583688888','湖北',2),
('tq','田七','123456',2,'1989-03-08','18583688888','湖南',2),
('mq','梦琪','123456',1,'1989-03-08','18583688888','苏州',2),
('ylk','云凌可','123456',1,'1989-03-08','18583688888','杭州',2),
('ymm','余梦茂','123456',1,'1989-03-08','18583688888','上海',3),
('wzy','文子隐','123456',1,'1989-03-08','18583688888','齐齐哈尔',3),
('lsw','黎舒旺','123456',1,'1989-03-08','18583688888','呼和浩特',3),
('yy','亦玉','123456',1,'1989-03-08','18583688888','西藏',3),
('sx','书雪','123456',1,'1989-03-08','18583688888','拉萨',3),
('bt','冰彤','123456',1,'1989-03-08','18583688888','香格里拉',3),
('dz','代真','123456',2,'1989-03-08','18583688888','大理',3),
('yueyao','乐瑶','123456',2,'1989-03-08','18583688888','南阳',3),
('yyc','云羿谆','123456',2,'1989-03-08','18583688888','西昌',3);
项目如何搭建?
考虑使用不使用Maven?依赖,Jar
项目搭建准备工作
-
搭建一个maven web项目
-
配置Tomcat
-
测试项目是否能够跑起来
-
导入项目中会遇到的jar包;
servlet,jsp,mysql驱动,jstl,standard …
-
创建项目包结构
-
编写实体类;
ORM映射:表-类映射
package com.niumo.pojo; import java.util.Date; public class User { private Integer id; // id private String userCode; // 用户编码 private String userName; // 用户姓名 private String userPassword; // 用户密码 private Integer gender; // 性别 private Date birthday; // 出生日期 private String phone; // 电话 private String address; // 地址 private Integer userRole; // 用户角色 private Integer createBy; // 创建者 private Date creationDate; // 创建时间 private Integer modifyBy; // 更新者 private Date modifyDate; // 更新时间 private Integer age; // 年龄 private String userRoleName; // 用户角色名称 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserCode() { return userCode; } public void setUserCode(String userCode) { this.userCode = userCode; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserPassword() { return userPassword; } public void setUserPassword(String userPassword) { this.userPassword = userPassword; } public Integer getGender() { return gender; } public void setGender(Integer gender) { this.gender = gender; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Integer getUserRole() { return userRole; } public void setUserRole(Integer userRole) { this.userRole = userRole; } public Integer getCreateBy() { return createBy; } public void setCreateBy(Integer createBy) { this.createBy = createBy; } public Date getCreationDate() { return creationDate; } public void setCreationDate(Date creationDate) { this.creationDate = creationDate; } public Integer getModifyBy() { return modifyBy; } public void setModifyBy(Integer modifyBy) { this.modifyBy = modifyBy; } public Date getModifyDate() { return modifyDate; } public void setModifyDate(Date modifyDate) { this.modifyDate = modifyDate; } public Integer getAge() { Date date = new Date(); Integer age = date.getYear()-birthday.getYear(); return age; } public void setAge(Integer age) { this.age = age; } public String getUserRoleName() { return userRoleName; } public void setUserRoleName(String userRoleName) { this.userRoleName = userRoleName; } }
package com.niumo.pojo; import java.util.Date; public class Role { private Integer id; // id private String roleCode; // 角色编码 private String roleName; // 角色名称 private Integer createBy; // 创建者 private Date creationDate; // 创建时间 private Integer modifyBy; // 更新者 private Date modifyDate; // 更新时间 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getRoleCode() { return roleCode; } public void setRoleCode(String roleCode) { this.roleCode = roleCode; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public Integer getCreateBy() { return createBy; } public void setCreateBy(Integer createBy) { this.createBy = createBy; } public Date getCreationDate() { return creationDate; } public void setCreationDate(Date creationDate) { this.creationDate = creationDate; } public Integer getModifyBy() { return modifyBy; } public void setModifyBy(Integer modifyBy) { this.modifyBy = modifyBy; } public Date getModifyDate() { return modifyDate; } public void setModifyDate(Date modifyDate) { this.modifyDate = modifyDate; } }
package com.niumo.pojo; import java.util.Date; public class Provider { private Integer id; // id private String proCode; // 供应商编码 private String proName; // 供应商名称 private String proDesc; // 供应商描述 private String proContact; // 供应商联系人 private String proPhone; // 供应商电话 private String proAddress; // 供应商地址 private String proFax; // 供应商传真 private Integer createBy; // 创建者 private Date creationDate; // 创建时间 private Integer modifyBy; // 更新者 private Date modifyDate; // 更新时间 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getProCode() { return proCode; } public void setProCode(String proCode) { this.proCode = proCode; } public String getProName() { return proName; } public void setProName(String proName) { this.proName = proName; } public String getProDesc() { return proDesc; } public void setProDesc(String proDesc) { this.proDesc = proDesc; } public String getProContact() { return proContact; } public void setProContact(String proContact) { this.proContact = proContact; } public String getProPhone() { return proPhone; } public void setProPhone(String proPhone) { this.proPhone = proPhone; } public String getProAddress() { return proAddress; } public void setProAddress(String proAddress) { this.proAddress = proAddress; } public String getProFax() { return proFax; } public void setProFax(String proFax) { this.proFax = proFax; } public Integer getCreateBy() { return createBy; } public void setCreateBy(Integer createBy) { this.createBy = createBy; } public Date getCreationDate() { return creationDate; } public void setCreationDate(Date creationDate) { this.creationDate = creationDate; } public Integer getModifyBy() { return modifyBy; } public void setModifyBy(Integer modifyBy) { this.modifyBy = modifyBy; } public Date getModifyDate() { return modifyDate; } public void setModifyDate(Date modifyDate) { this.modifyDate = modifyDate; } }
package com.niumo.pojo; import java.math.BigDecimal; import java.util.Date; public class Bill { private Integer id; // id private String billCode; // 账单编号 private String productName; // 商品名称 private String productDesc; // 商品描述 private String productUnit; //商品单位 private BigDecimal productCount; //商品数量 private BigDecimal totalPrice; // 总金额 private Integer isPayment; // 是否支付 private Integer providerId; // 供应商ID private Integer createBy; // 创建者 private Date creationDate; // 创建时间 private Integer modifyBy; // 更新者 private Date modifyDate; // 更新时间 private String providerName; // 供应商名称 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getBillCode() { return billCode; } public void setBillCode(String billCode) { this.billCode = billCode; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getProductDesc() { return productDesc; } public void setProductDesc(String productDesc) { this.productDesc = productDesc; } public String getProductUnit() { return productUnit; } public void setProductUnit(String productUnit) { this.productUnit = productUnit; } public BigDecimal getProductCount() { return productCount; } public void setProductCount(BigDecimal productCount) { this.productCount = productCount; } public BigDecimal getTotalPrice() { return totalPrice; } public void setTotalPrice(BigDecimal totalPrice) { this.totalPrice = totalPrice; } public Integer getIsPayment() { return isPayment; } public void setIsPayment(Integer isPayment) { this.isPayment = isPayment; } public Integer getProviderId() { return providerId; } public void setProviderId(Integer providerId) { this.providerId = providerId; } public Integer getCreateBy() { return createBy; } public void setCreateBy(Integer createBy) { this.createBy = createBy; } public Date getCreationDate() { return creationDate; } public void setCreationDate(Date creationDate) { this.creationDate = creationDate; } public Integer getModifyBy() { return modifyBy; } public void setModifyBy(Integer modifyBy) { this.modifyBy = modifyBy; } public Date getModifyDate() { return modifyDate; } public void setModifyDate(Date modifyDate) { this.modifyDate = modifyDate; } public String getProviderName() { return providerName; } public void setProviderName(String providerName) { this.providerName = providerName; } }
-
编写基础公共类
-
数据库配置文件
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf-8&useSSL=true username=root password=nm123456
-
编写数据库的公共类
package com.niumo.dao; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; //操作数据库的公共类 public class BaseDao { private static String driver; private static String url; private static String username; private static String password; //静态代码块,类加载的时候就初始化了 static{ Properties properties = new Properties(); //通过类加载器读取对应的资源 InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties"); try { properties.load(is); } catch (IOException e) { e.printStackTrace(); } driver = properties.getProperty("driver"); url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); } //获取数据库的连接 public static Connection getConnection(){ Connection connection = null; try { Class.forName(driver); connection = DriverManager.getConnection(url,username,password); } catch (Exception e) { e.printStackTrace(); } return connection; } //编写查询公共类 public static ResultSet execute(Connection connection,PreparedStatement preparedStatement,ResultSet resultSet,String sql,Object[] params) throws SQLException { //预编译的sql,在后面直接执行就可以了 preparedStatement = connection.prepareStatement(sql); for(int i = 0; i < params.length; i++){ //setObject,占位符从1开始,但是我们的数组是从0开始! preparedStatement.setObject(i+1,params[i]); } resultSet = preparedStatement.executeQuery(); return resultSet; } //编写增删改公共方法 public static int execute(Connection connection,PreparedStatement preparedStatement,String sql,Object[] params) throws SQLException { preparedStatement = connection.prepareStatement(sql); for(int i = 0; i < params.length; i++){ //setObject,占位符从1开始,但是我们的数组是从0开始! preparedStatement.setObject(i+1,params[i]); } int updateRows = preparedStatement.executeUpdate(); return updateRows; } //释放资源 public static boolean closeResource(Connection connection,PreparedStatement preparedStatement,ResultSet resultSet){ boolean flag = true; if(resultSet!=null){ try{ resultSet.close(); //GC回收 resultSet = null; } catch (SQLException e) { e.printStackTrace(); flag = false; } } if(preparedStatement!=null){ try{ preparedStatement.close(); //GC回收 preparedStatement = null; } catch (SQLException e) { e.printStackTrace(); flag = false; } } if(connection!=null){ try{ connection.close(); //GC回收 connection = null; } catch (SQLException e) { e.printStackTrace(); flag = false; } } return flag; } }
-
编写字符编码过滤器
package com.niumo.filter; import javax.servlet.*; import java.io.IOException; public class CharacterEncodingFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding("utf-8"); servletResponse.setCharacterEncoding("utf-8"); filterChain.doFilter(servletRequest,servletResponse); } public void destroy() { } }
-
-
导入静态资源
- calendar
- css
- images
- js
P31 smbms登录流程实现
登录功能实现
-
编写前端页面
-
jsp
-
login.jsp
-
-
设置首页
<!--设置欢迎页面--> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list>
-
编写dao层登录用户登录的接口
package com.niumo.dao.user; import com.niumo.pojo.User; import java.sql.Connection; import java.sql.SQLException; public interface UserDao { //得到要登录的用户 public User getLoginUser(Connection connection,String userCode) throws SQLException; }
-
编写dao接口的实现类
package com.niumo.dao.user; import com.niumo.dao.BaseDao; import com.niumo.pojo.User; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class UserDaoImpl implements UserDao{ //得到要登录的用户 public User getLoginUser(Connection connection, String userCode) throws SQLException { PreparedStatement pstm = null; ResultSet rs = null; User user = null; if(connection!=null){ String sql = "select * from smbms_user where userCode=?"; Object[] params = {userCode}; rs = BaseDao.execute(connection,pstm,rs,sql,params); if(rs.next()){ user = new User(); user.setId(rs.getInt("id")); user.setUserCode(rs.getString("userCode")); user.setUserName(rs.getString("userName")); user.setUserPassword(rs.getString("userPassword")); user.setGender(rs.getInt("gender")); user.setBirthday(rs.getDate("birthday")); user.setPhone(rs.getString("phone")); user.setAddress(rs.getString("address")); user.setUserRole(rs.getInt("userRole")); user.setCreateBy(rs.getInt("createBy")); user.setCreationDate(rs.getTimestamp("creationDate")); user.setModifyBy(rs.getInt("modifyBy")); user.setModifyDate(rs.getTimestamp("modifyDate")); } BaseDao.closeResource(null,pstm,rs); } return user; } }
-
业务层接口
package com.niumo.service.user; import com.niumo.pojo.User; public interface UserService { //用户登录 public User login(String userCode, String password); }
-
业务层实现类
package com.niumo.service.user; import com.niumo.dao.BaseDao; import com.niumo.dao.user.UserDao; import com.niumo.dao.user.UserDaoImpl; import com.niumo.pojo.User; import org.junit.Test; import java.sql.Connection; import java.sql.SQLException; public class UserServiceImpl implements UserService{ //业务层都会调用dao层,所以我们要引入Dao层: private UserDao userDao; public UserServiceImpl(){ userDao = new UserDaoImpl(); } public User login(String userCode, String password) { Connection connection = null; User user = null; try{ connection = BaseDao.getConnection(); //通过业务层调用对应的具体的数据库操作 user= userDao.getLoginUser(connection,userCode); } catch (SQLException e) { e.printStackTrace(); }finally { BaseDao.closeResource(connection,null,null); } return user; } }
-
编写Servlet
package com.niumo.servlet.user; import com.niumo.pojo.User; import com.niumo.service.user.UserService; import com.niumo.service.user.UserServiceImpl; import com.niumo.util.Constants; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class LoginServlet extends HttpServlet { //Servlet:控制层,调用业务层代码 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("LoginServlet--start..."); //获取用户名和密码 String userCode = req.getParameter("userCode"); String userPassword = req.getParameter("userPassword"); //和数据库中的密码进行对比,调用业务层; UserService userService= new UserServiceImpl(); User user = userService.login(userCode,userPassword); if(user!=null&&userPassword.equals(user.getUserPassword())){//查有此人,可以登录 //将用户的信息放到Session中; req.getSession().setAttribute(Constants.USER_SESSION,user); //跳转到主页 resp.sendRedirect("jsp/frame.jsp"); }else{//查无此人,无法登录 //转发回登录页面,顺带提示它,用户名或者密码错误; req.setAttribute("error","用户名或者密码不正确"); req.getRequestDispatcher("login.jsp").forward(req,resp); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
package com.niumo.util; public class Constants { public final static String USER_SESSION = "userSession"; }
-
注册Servlet
<servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.niumo.servlet.user.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/login.do</url-pattern> </servlet-mapping>
-
测试访问,确保以上功能成功!
P32 smbms注销及权限过滤
登录功能优化
注销功能:
思路:移除Session,返回登录页面
package com.niumo.servlet.user;
import com.niumo.util.Constants;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//移除用户的
req.getSession().removeAttribute(Constants.USER_SESSION);
resp.sendRedirect(req.getContextPath()+"/login.jsp"); //返回登录页面
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
注册xml
<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.niumo.servlet.user.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/jsp/logout.do</url-pattern>
</servlet-mapping>
登录拦截优化
编写一个过滤器
package com.niumo.filter;
import com.niumo.pojo.User;
import com.niumo.util.Constants;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//过滤器,从Session中获取用户
User user = (User) request.getSession().getAttribute(Constants.USER_SESSION);
if(user==null){//已经被移除或者注销了,或者未登录
response.sendRedirect("/smbms/error.jsp");
}else {
filterChain.doFilter(servletRequest,servletResponse);
}
}
public void destroy() {
}
}
<!--用户登录过滤器-->
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.niumo.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SysFilter</filter-name>
<url-pattern>/jsp/*</url-pattern>
</filter-mapping>
测试,登录,注销,权限,都要保证OK!
P33 smbms密码修改实现
密码修改
-
导入前端素材
<li><a href="${pageContext.request.contextPath }/jsp/pwdmodify.jsp">密码修改</a></li>
-
写项目,建议从底层向上写
-
UserDao 接口
package com.niumo.dao.user; import com.niumo.pojo.User; import java.sql.Connection; import java.sql.SQLException; public interface UserDao { //得到要登录的用户 public User getLoginUser(Connection connection,String userCode) throws SQLException; //修改当前用户密码 public int updatePwd(Connection connection,int id,String password) throws SQLException; }
-
UserDao 接口实现类
package com.niumo.dao.user; import com.niumo.dao.BaseDao; import com.niumo.pojo.User; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class UserDaoImpl implements UserDao{ //得到要登录的用户 public User getLoginUser(Connection connection, String userCode) throws SQLException { PreparedStatement pstm = null; ResultSet rs = null; User user = null; if(connection!=null){ String sql = "select * from smbms_user where userCode=?"; Object[] params = {userCode}; rs = BaseDao.execute(connection,pstm,rs,sql,params); if(rs.next()){ user = new User(); user.setId(rs.getInt("id")); user.setUserCode(rs.getString("userCode")); user.setUserName(rs.getString("userName")); user.setUserPassword(rs.getString("userPassword")); user.setGender(rs.getInt("gender")); user.setBirthday(rs.getDate("birthday")); user.setPhone(rs.getString("phone")); user.setAddress(rs.getString("address")); user.setUserRole(rs.getInt("userRole")); user.setCreateBy(rs.getInt("createBy")); user.setCreationDate(rs.getTimestamp("creationDate")); user.setModifyBy(rs.getInt("modifyBy")); user.setModifyDate(rs.getTimestamp("modifyDate")); } BaseDao.closeResource(null,pstm,rs); } return user; } //修改当前用户密码 public int updatePwd(Connection connection, int id, String password) throws SQLException { System.out.println("UserDaoImpl:"+password); PreparedStatement pstm = null; int execute = 0; if(connection!=null){ String sql = "update smbms_user set userPassword = ? where id = ?"; Object params[] = {password,id}; execute = BaseDao.execute(connection,pstm,sql,params); BaseDao.closeResource(null,pstm,null); } return execute; } }
-
UserService层
package com.niumo.service.user; import com.niumo.pojo.User; public interface UserService { //用户登录 public User login(String userCode, String password); //根据用户ID修改密码 public boolean updatePwd(int id,String pwd); }
-
UserService实现类
package com.niumo.service.user; import com.niumo.dao.BaseDao; import com.niumo.dao.user.UserDao; import com.niumo.dao.user.UserDaoImpl; import com.niumo.pojo.User; import org.junit.Test; import java.sql.Connection; import java.sql.SQLException; public class UserServiceImpl implements UserService{ //业务层都会调用dao层,所以我们要引入Dao层: private UserDao userDao; public UserServiceImpl(){ userDao = new UserDaoImpl(); } public User login(String userCode, String password) { Connection connection = null; User user = null; try{ connection = BaseDao.getConnection(); //通过业务层调用对应的具体的数据库操作 user= userDao.getLoginUser(connection,userCode); } catch (SQLException e) { e.printStackTrace(); }finally { BaseDao.closeResource(connection,null,null); } return user; } public boolean updatePwd(int id, String pwd) { System.out.println("UserServiceImpl:"+pwd); Connection connection = null; boolean flag = false; //修改密码 try{ connection = BaseDao.getConnection(); if(userDao.updatePwd(connection,id,pwd)>0){ flag = true; } } catch (SQLException e) { e.printStackTrace(); }finally { BaseDao.closeResource(connection,null,null); } return flag; } }
-
Servlet记得实现复用,需要提取出方法!
package com.niumo.servlet.user; import com.alibaba.fastjson.JSONArray; import com.mysql.cj.util.StringUtils; import com.niumo.pojo.User; import com.niumo.service.user.UserService; import com.niumo.service.user.UserServiceImpl; import com.niumo.util.Constants; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; //实现Servlet复用 public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getParameter("method"); if(method.equals("savepwd")&&method!=null){ this.upadtePwd(req,resp); }else if(method.equals("pwdmodify")&&method!=null){ this.pwdModify(req,resp); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } public void upadtePwd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //从Session里面拿ID; Object o = req.getSession().getAttribute(Constants.USER_SESSION); String newpassword = req.getParameter("newpassword"); System.out.println("UserServlet:"+newpassword); boolean flag = false; if(o!=null && newpassword!=null && newpassword.length()!=0){ UserService userService = new UserServiceImpl(); flag = userService.updatePwd(((User)o).getId(),newpassword); if(flag){ req.setAttribute("message","修改密码成功,请退出,使用新密码登录"); //密码修改成功,移除当前Session req.getSession().removeAttribute(Constants.USER_SESSION); }else{ req.setAttribute("message","修改密码失败"); } }else{ req.setAttribute("message","新密码有问题"); } req.getRequestDispatcher("pwdmodify.jsp").forward(req,resp); } //验证旧密码,session中有用户的密码 public void pwdModify(HttpServletRequest req, HttpServletResponse resp){ //从Session里面拿ID; Object o = req.getSession().getAttribute(Constants.USER_SESSION); String oldpassword = req.getParameter("oldpassword"); //万能的Map : 结果集 Map<String,String> resultMap = new HashMap<String,String>(); if(o==null){ //Session失效了,session过期了 resultMap.put("result","sessionerror"); }else if (StringUtils.isNullOrEmpty(oldpassword)){ //输入的密码为空 resultMap.put("result","error"); }else{ String userPassword = ((User)o).getUserPassword(); //Session中用户的密码 if(oldpassword.equals((userPassword))){ resultMap.put("result","true"); }else{ resultMap.put("result","false"); } } try{ resp.setContentType("application/json"); PrintWriter writer = resp.getWriter(); //JSONArray 阿里巴巴的JSON工具类,转换格式 /* resultMap = ["result","sessionerror","result","error"] Json格式 = {key:value} */ writer.write(JSONArray.toJSONString(resultMap)); writer.flush(); writer.close(); } catch (IOException e) { e.printStackTrace(); } } }
-
测试
P34 Ajax验证旧密码实现
优化密码修改使用Ajax
-
阿里巴巴的fastjson
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.79</version> </dependency>
-
后台代码修改
package com.niumo.servlet.user; import com.alibaba.fastjson.JSONArray; import com.mysql.cj.util.StringUtils; import com.niumo.pojo.User; import com.niumo.service.user.UserService; import com.niumo.service.user.UserServiceImpl; import com.niumo.util.Constants; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; //实现Servlet复用 public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getParameter("method"); if(method.equals("savepwd")&&method!=null){ this.upadtePwd(req,resp); }else if(method.equals("pwdmodify")&&method!=null){ this.pwdModify(req,resp); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } public void upadtePwd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //从Session里面拿ID; Object o = req.getSession().getAttribute(Constants.USER_SESSION); String newpassword = req.getParameter("newpassword"); System.out.println("UserServlet:"+newpassword); boolean flag = false; if(o!=null && newpassword!=null && newpassword.length()!=0){ UserService userService = new UserServiceImpl(); flag = userService.updatePwd(((User)o).getId(),newpassword); if(flag){ req.setAttribute("message","修改密码成功,请退出,使用新密码登录"); //密码修改成功,移除当前Session req.getSession().removeAttribute(Constants.USER_SESSION); }else{ req.setAttribute("message","修改密码失败"); } }else{ req.setAttribute("message","新密码有问题"); } req.getRequestDispatcher("pwdmodify.jsp").forward(req,resp); } //验证旧密码,session中有用户的密码 public void pwdModify(HttpServletRequest req, HttpServletResponse resp){ //从Session里面拿ID; Object o = req.getSession().getAttribute(Constants.USER_SESSION); String oldpassword = req.getParameter("oldpassword"); //万能的Map : 结果集 Map<String,String> resultMap = new HashMap<String,String>(); if(o==null){ //Session失效了,session过期了 resultMap.put("result","sessionerror"); }else if (StringUtils.isNullOrEmpty(oldpassword)){ //输入的密码为空 resultMap.put("result","error"); }else{ String userPassword = ((User)o).getUserPassword(); //Session中用户的密码 if(oldpassword.equals((userPassword))){ resultMap.put("result","true"); }else{ resultMap.put("result","false"); } } try{ resp.setContentType("application/json"); PrintWriter writer = resp.getWriter(); //JSONArray 阿里巴巴的JSON工具类,转换格式 /* resultMap = ["result","sessionerror","result","error"] Json格式 = {key:value} */ writer.write(JSONArray.toJSONString(resultMap)); writer.flush(); writer.close(); } catch (IOException e) { e.printStackTrace(); } } }
var oldpassword = null; var newpassword = null; var rnewpassword = null; var saveBtn = null; $(function(){ oldpassword = $("#oldpassword"); newpassword = $("#newpassword"); rnewpassword = $("#rnewpassword"); saveBtn = $("#save"); oldpassword.next().html("*"); newpassword.next().html("*"); rnewpassword.next().html("*"); oldpassword.on("blur",function(){ $.ajax({ type:"GET", url:path+"/jsp/user.do", data:{method:"pwdmodify",oldpassword:oldpassword.val()},//Ajax传递的参数 dataType:"json", success:function(data){ if(data.result == "true"){//旧密码正确 validateTip(oldpassword.next(),{"color":"green"},imgYes,true); }else if(data.result == "false"){//旧密码输入不正确 validateTip(oldpassword.next(),{"color":"red"},imgNo + " 原密码输入不正确",false); }else if(data.result == "sessionerror"){//当前用户session过期,请重新登录 validateTip(oldpassword.next(),{"color":"red"},imgNo + " 当前用户session过期,请重新登录",false); }else if(data.result == "error"){//旧密码输入为空 validateTip(oldpassword.next(),{"color":"red"},imgNo + " 请输入旧密码",false); } }, error:function(data){ //请求出错 validateTip(oldpassword.next(),{"color":"red"},imgNo + " 请求错误",false); } }); }).on("focus",function(){ validateTip(oldpassword.next(),{"color":"#666666"},"* 请输入原密码",false); }); newpassword.on("focus",function(){ validateTip(newpassword.next(),{"color":"#666666"},"* 密码长度必须是大于6小于20",false); }).on("blur",function(){ if(newpassword.val() != null && newpassword.val().length >= 6 && newpassword.val().length < 20 ){ validateTip(newpassword.next(),{"color":"green"},imgYes,true); }else{ validateTip(newpassword.next(),{"color":"red"},imgNo + " 密码输入不符合规范,请重新输入",false); } }); rnewpassword.on("focus",function(){ validateTip(rnewpassword.next(),{"color":"#666666"},"* 请输入与上面一致的密码",false); }).on("blur",function(){ if(rnewpassword.val() != null && rnewpassword.val().length >= 6 && rnewpassword.val().length < 20 && newpassword.val() == rnewpassword.val()){ validateTip(rnewpassword.next(),{"color":"green"},imgYes,true); }else{ validateTip(rnewpassword.next(),{"color":"red"},imgNo + " 两次密码输入不一致,请重新输入",false); } }); saveBtn.on("click",function(){ oldpassword.blur(); newpassword.blur(); rnewpassword.blur(); if( oldpassword.attr("validateStatus") == "true" &&newpassword.attr("validateStatus") == "true" && rnewpassword.attr("validateStatus") == "true"){ if(confirm("确定要修改密码?")){ $("#userForm").submit(); } } }); });
-
测试
P35 smbms用户管理底层实现
用户管理实现
思路:
-
导入分页的工具类
PageSupport.java
-
用户列表页面导入
userlist.jsp
rollpage.jsp
1、获取用户数量
-
UserDao
//根据用户名或者角色查询用户总数 public int getUserCount(Connection connection,String username,int userRole) throws SQLException;
-
UserDaoImpl
//根据用户名或者角色查询用户总数【最难理解的SQL】 public int getUserCount(Connection connection, String username, int userRole) throws SQLException PreparedStatement pstm = null; ResultSet rs = null; int count = 0; if(connection!=null){ StringBuffer sql = new StringBuffer(); sql.append("select count(1) as count from smbms_user u,smbms_role r where u.userRole = r.i ArrayList<Object> list = new ArrayList<Object>();//存放我们的参数 if(!StringUtils.isNullOrEmpty(username)){ sql.append(" and u.userName like ?"); list.add("%"+username+"%");//index:0 } if(userRole>0){ sql.append(" and u.userRole = ?"); list.add(userRole);//index:1 } //怎么把List转换为数组 Object[] params = list.toArray(); System.out.println("UserDaoImpl->getUserCount:"+sql.toString()); //输出最后完整的SQL语句 rs = BaseDao.execute(connection,pstm,rs,sql.toString(),params); if(rs.next()){ count = rs.getInt("count"); //从结果集中获取最终的数量 } BaseDao.closeResource(null,pstm,rs); } return count; }
-
UserService
//查询记录数 public int getUserCount(String username,int userRole);
-
UserServiceImpl
//查询记录数 public int getUserCount(String username, int userRole) { Connection connection = null; int count = 0; try{ connection = BaseDao.getConnection(); count = userDao.getUserCount(connection,username,userRole); } catch (SQLException e) { e.printStackTrace(); }finally { BaseDao.closeResource(connection,null,null); } return count; }
2、获取用户列表
-
userdao
//通过条件查询-userList public List<User> getUserList(Connection connection,String username,int userRole,int currentPageNo,int pageSize) throws SQLException;
-
userdaoImpl
//通过条件查询-userList public List<User> getUserList(Connection connection, String username, int userRole, int currentPageNo, int pageSize) throws SQLException { PreparedStatement pstm = null; ResultSet rs = null; List<User> userList = new ArrayList<User>(); if(connection!=null){ StringBuffer sql = new StringBuffer(); sql.append("select u.*,r.roleName as userRoleName from smbms_user u,smbms_role r where u.userRole = r.id"); List<Object> list = new ArrayList<Object>(); if(!StringUtils.isNullOrEmpty(username)){ sql.append(" and u.username like ?"); list.add("%"+username+"%"); } if(userRole>0){ sql.append(" and u.userRole = ?"); list.add(userRole); } //在数据库中,分页使用 limit startIndex,pageSize; 总数 //当前页 (当前页-1)*页面大小 //0,5 1 0 01234 //5,5 2 5 56789 //10,5 3 10 10~ sql.append(" order by userRole,userName DESC limit ?,?"); currentPageNo = (currentPageNo-1)*pageSize; list.add(currentPageNo); list.add(pageSize); Object[] params = list.toArray(); System.out.println("UserDaoImpl->getUserList:" + sql.toString()); rs = BaseDao.execute(connection,pstm,rs,sql.toString(),params); while(rs.next()){ User _user = new User(); _user.setId(rs.getInt("id")); _user.setUserCode(rs.getString("userCode")); _user.setUserName(rs.getString("userName")); _user.setGender(rs.getInt("gender")); _user.setBirthday(rs.getDate("birthday")); _user.setPhone(rs.getString("phone")); _user.setUserRole(rs.getInt("userRole")); _user.setUserRoleName(rs.getString("userRoleName")); userList.add(_user); } BaseDao.closeResource(null,pstm,rs); } return userList; }
-
UserService
//根据条件查询用户列表 public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize);
-
UserServiceImpl
public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize) { Connection connection = null; List<User> userList = null; System.out.println("queryUserName ---- > "+ queryUserName); System.out.println("queryUserRole ---- > "+ queryUserRole); System.out.println("currentPageNo ---- > "+ currentPageNo); System.out.println("pageSize ---- > "+ pageSize); try{ connection = BaseDao.getConnection(); userList = userDao.getUserList(connection,queryUserName,queryUserRole,currentPageNo,pageSize); } catch (SQLException e) { e.printStackTrace(); }finally { BaseDao.closeResource(connection,null,null); } return userList; }
P36 smbms用户管理分页
3、获取角色操作
为了我们职责统一,可以把角色的操作单独放在一个包中,和POJO类对应。
-
RoleDao
//获取角色列表 public List<Role> getRoleList(Connection connection) throws SQLException;
-
RoleDaoImpl
//获取角色列表 public List<Role> getRoleList(Connection connection) throws SQLException { PreparedStatement pstm = null; ResultSet rs = null; List<Role> roleList = new ArrayList<Role>(); if(connection!=null){ String sql = "select * from smbms_role"; Object[] params = {}; rs = BaseDao.execute(connection,pstm,rs,sql,params); while(rs.next()){ Role _role = new Role(); _role.setId(rs.getInt("id")); _role.setRoleCode(rs.getString("roleCode")); _role.setRoleName(rs.getString("roleName")); roleList.add(_role); } BaseDao.closeResource(null,pstm,rs); } return roleList; }
-
RoleService
//获取角色列表 public List<Role> getRoleList();
-
RoleServiceImpl
package com.niumo.service.role; import com.niumo.dao.BaseDao; import com.niumo.dao.role.RoleDao; import com.niumo.dao.role.RoleDaoImpl; import com.niumo.pojo.Role; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class RoleServiceImpl implements RoleService{ //引入Dao private RoleDao roleDao; public RoleServiceImpl() { roleDao = new RoleDaoImpl(); } public List<Role> getRoleList() { Connection connection = null; List<Role> roleList = null; try{ connection = BaseDao.getConnection(); roleList = roleDao.getRoleList(connection); } catch (SQLException e) { e.printStackTrace(); }finally { BaseDao.closeResource(connection,null,null); } return roleList; } }
4、用户显示的Servlet
-
获取用户前端的数据(查询)
-
判断请求是否需要执行,看参数的值判断
-
为了实现分页,需要计算出当前页面和总页面,页面大小…
-
用户列表展示
-
返回前端
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getParameter("method"); if(method.equals("savepwd")&&method!=null){ this.upadtePwd(req,resp); }else if(method.equals("pwdmodify")&&method!=null){ this.pwdModify(req,resp); }else if(method.equals("query")&&method!=null){ this.query(req,resp); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } //重点、难点 public void query(HttpServletRequest req, HttpServletResponse resp){ //查询用户列表 //从前端获取数据; String queryUserName = req.getParameter("queryname"); String temp = req.getParameter("queryUserRole"); String pageIndex = req.getParameter("pageIndex"); int queryUserRole = 0; //获取用户列表 UserServiceImpl userService = new UserServiceImpl(); List<User> userList = null; //第一次走这个请求,一定是第一页,页面大小固定的 int pageSize = 5; //可以把这个写到配置文件中,方便后期修改; int currentPageNo = 1; if(queryUserName == null){ queryUserName = ""; } if(temp!=null && !temp.equals("")){ queryUserRole = Integer.parseInt(temp); //给查询赋值!0,1,2,3 } if(pageIndex!=null){ currentPageNo = Integer.parseInt(pageIndex); } //获取用户的总数(分页: 上一页,下一页的情况) int totalCount = userService.getUserCount(queryUserName,queryUserRole); //总页数支持 PageSupport pageSupport = new PageSupport(); pageSupport.setCurrentPageNo(currentPageNo); pageSupport.setPageSize(pageSize); pageSupport.setTotalCount(totalCount); int totalPageCount = pageSupport.getTotalPageCount(); //控制首页和尾页 //如果页面要小于1了,就显示第一页的东西 if(currentPageNo<1){ currentPageNo = 1; }else if (currentPageNo>totalPageCount){ //当前页面大于了最后一页; currentPageNo = totalPageCount; } //获取用户列表展示 userList = userService.getUserList(queryUserName,queryUserRole,currentPageNo,pageSize); req.setAttribute("userList",userList); RoleServiceImpl roleService = new RoleServiceImpl(); List<Role> roleList = roleService.getRoleList(); req.setAttribute("roleList",roleList); req.setAttribute("totalCount",totalCount); req.setAttribute("currentPageNo",currentPageNo); req.setAttribute("totalPageCount",totalPageCount); req.setAttribute("queryUserName",queryUserName); req.setAttribute("queryUserRole",queryUserRole); //返回前端 try{ req.getRequestDispatcher("userlist.jsp").forward(req,resp); } catch (ServletException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
小黄鸭调试法
此概念是参照于一个来自《
程序员修炼之道
》书中的一个故事。传说中程序大师随身携带一只小黄鸭,在调试代码的时候会在桌上放上这只小黄鸭,然后详细地向鸭子解释每行代码 [1] 。
许多程序员都有过向别人(甚至可能向完全不会编程的人)提问及解释编程问题,就在解释的过程中击中了问题的解决方案。一边阐述代码的意图一边观察它实际上的意图并做调试,这两者之间的任何不协调会变得很明显,并且更容易发现自己的错误。如果没有玩具小鸭子也可以考虑向其它东西倾诉,比如桌上的花花草草,键盘鼠标。
类似的,有一种现象叫做cone of answers,这是一个常见的现象。你的朋友跑来问你一个问题,但是当他自己把问题说完,或者说到一半的时候就想出了答案走了,留下一脸茫然的你。是的,这个时候你就起到了那只小黄鸭的作用。
相似的概念还有不少,例如自白调试、纸板程序员或程序员的假人、想出脑外等等。总的来说,在你试图表述自己的想法的过程中,自然地在促使自己去整理思路,重新考虑问题。
P37 smbms架构分析及方法学习
smbms架构分析
P38 文件传输原理及介绍
1、 准备工作
对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的。
一般选择采用apache的开源工具common-fileupload这个文件上传组件。
common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。
我们下载最新的jar包
- https://mvnrepository.com/artifact/commons-io/commons-io
- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
commons-io-2.11.0.jar
commons-fileupload-1.4.jar
2、使用类介绍
【文件上传的注意事项】
-
为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
-
为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
1.txt 1.txt -时间戳 -uuid -md5 -位运算算法
-
要限制上传文件的最大值。
-
可以限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。
.mp4
.txt .doc …
.jpg .png .bmp …
【需要用到的类详解】
ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象,在使用ServletFileUpload对象解析请求时,
需要DiskFileItemFactory对象。所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或
setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。
FileItem类
在HTML页面input必须有 name
<input type="file" name="filename">
表单如果包含一个文件上传输入项的话,这个表单的enctype属性就必须设置为multipart/form-data
【常用方法介绍】
//isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单
//还是一个文件表单,如果是普通表单字段则返回true,否则返回false
boolean isFormField();
//getFiledName方法用于返回表单标签name属性的值。
String getFieldName();
//getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回
String getString();
//getName方法用于获得文件上传字段中的文件名。
String getName();
//以流的形式返回上传文件的数据内容。
InputStream getInputStream();
//delete方法用来清空FileItem类对象中存放的主体内容
//如果主体内容被保存在临时文件中,delete方法将删除该临时文件。
void delete();
ServletFileUpload类
ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象中。使用其
parseRequest(HttpServletRequest)方法
,可以将通过
表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回。使用该方法处理上传文件简单易用。
P39 文件上传及拓展鸡汤
3、代码编写
-
FileServlet.java
package com.niumo.servlet; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.ProgressListener; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.util.List; import java.util.UUID; public class FileServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { //判断上传的文件是普通表单还是带文件的表单 if(!ServletFileUpload.isMultipartContent(request)){ return; //终止方法运行,说明这是一个普通的表单,直接返回 } //创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件; String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload"); File uploadFile = new File(uploadPath); if(!uploadFile.exists()){ uploadFile.mkdir(); //创建这个目录 } //缓存,临时文件 //临时路径,假如文件超过了预期的大小,我们就把他放到一个临时文件中,过几天自动删除,或者提醒用户转存为永久 String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp"); File file = new File(tmpPath); if(!file.exists()){ file.mkdir(); //创建这个临时目录 } //处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦 //但是我们都建议使用 Apache的文件上传组件来实现,common-fileupload,它需要依赖于 common-io组件; /* ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象,在使用ServletFileUpload对象解析请求时, 需要DiskFileItemFactory对象。所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或 setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。 */ //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的; DiskFileItemFactory factory = getDiskFileItemFactory(file); //2.获取ServletFileUpload ServletFileUpload upload = getServletFileUpload(factory); //3.处理上传的文件 String msg = uploadParseRequest(upload,request,uploadPath); //servlet请求转发消息 request.setAttribute("msg",msg); request.getRequestDispatcher("info.jsp").forward(request,response); } catch (FileUploadException e) { e.printStackTrace(); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } public static DiskFileItemFactory getDiskFileItemFactory(File file){ DiskFileItemFactory factory = new DiskFileItemFactory(); //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中; factory.setSizeThreshold(1024*1024); //缓存区大小为1M factory.setRepository(file); //临时目录的保存目录,需要一个File return factory; } public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){ ServletFileUpload upload = new ServletFileUpload(factory); //监听文件上传进度; upload.setProgressListener(new ProgressListener() { @Override //pBytesRead:已经读取到的文件大小 //pContentLength:文件大小 public void update(long pBytesRead, long pContentLength, int pItems) { System.out.println("总大小:"+ pContentLength+"已上传:"+pBytesRead); } }); //处理乱码问题 upload.setHeaderEncoding("UTF-8"); //设置单个文件的最大值 upload.setFileSizeMax(1024*1024*10); //设置总共能够上传文件的大小 //1024 = 1kb * 1024 = 1M * 10 = 10M upload.setSizeMax(1024 * 1024 * 10); return upload; } public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadPath) throws FileUploadException, IOException { String msg = ""; //把前端请求解析,封装成一个FileItem对象,需要从ServletFileUpload对象中获取 List<FileItem> fileItems = upload.parseRequest(request); //fileItem 每一个表单对象 for (FileItem fileItem : fileItems) { //判断上传的文件是普通的表单还是带文件的表单 if (fileItem.isFormField()) { //getFiledName指的是前端表单控件的name; String name = fileItem.getFieldName(); String value = fileItem.getString("UTF-8"); //处理乱码 System.out.println(name + ":" + value); } else { //文件 //=========================处理文件=========================// String uploadFileName = fileItem.getName(); //可能存在文件名不合法的情况 if (uploadFileName.trim().equals("") || uploadFileName == null) { continue; } //获得上传的文件名 /images/girl/paojie.png String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1); //获得文件的后缀名 String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1); /* 如果文件后缀名 fileExtName 不是我们所需要的 就直接return,不处理,告诉用户文件类型不对。 */ System.out.println("文件信息 [文件名:" + fileName + "---文件类型:" + fileExtName + "]"); //可以使用UUID(唯一识别的通用码),保证文件名唯一; //UUID.randomUUID(),随机生一个唯一识别的通用码; //网络传输中的东西,都需要序列化 //POJO,实体类,如果想要在多个电脑上运行,传输===>需要把对象都序列化了 // JNI = Java Native Interface //implements Serializable : 标记接口 , JVM---> Java栈 本地方法栈 native ---> C++ String uuidPath = UUID.randomUUID().toString(); //=========================存放地址=========================// //存到哪? uploadPath //文件真实存在的路径 realPath String realPath = uploadPath + "/" + uuidPath; //给每个文件创建一个对应的文件夹 File realPathFile = new File(realPath); if (!realPathFile.exists()) { realPathFile.mkdir(); } //=========================文件传输=========================// //获得文件上传的流 InputStream inputStream = fileItem.getInputStream(); //创建一个文件输出流 //realPath = 真实的文件夹; //差了一个文件;加上输出文件的名字+"/"+uuidFileName FileOutputStream fos = new FileOutputStream(realPathFile + "/" + fileName); //创建一个缓冲区 byte[] buffer = new byte[1024 * 1024]; //判断是否读取完毕 int len = 0; //如果大于0说明还存在数据; while ((len = inputStream.read(buffer)) > 0) { fos.write(buffer, 0, len); } //关闭流 fos.close(); inputStream.close(); msg = "文件上传成功!"; fileItem.delete(); //上传成功,清除临时文件 } } return msg; } }
-
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>FileServlet</servlet-name> <servlet-class>com.niumo.servlet.FileServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>FileServlet</servlet-name> <url-pattern>/upload.do</url-pattern> </servlet-mapping> </web-app>
-
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>文件上传</title> </head> <body> <%--通过表单上传文件 get: 上传文件大小有限制 post: 上传文件大小没有限制 --%> <%--${pageContext.request.contextPath}获取服务器路径--%> <form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post"> 上传用户:<input type="text" name="username"><br/> <p>上传文件1:<input type="file" name="file1"></p> <p>上传文件2:<input type="file" name="file2"></p> <p><input type="submit"> | <input type="reset"></p> </form> </body> </html>
-
info.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>info.jsp</title> </head> <body> ${msg} </body> </html>
4、java关键字
P40 邮件发送原理及实现
电子邮件
要在网络上实现邮件功能,必须要有专门的
邮件服务器。
这些邮件服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
SMTP服务器地址:一般是smtp.xxx.com,比如163邮箱是smtp.163.com,qq邮箱是smtp.qq.com。
电子邮箱(E-Mail地址)的获得需要在邮件服务器上进行申请。比如我们要使用QQ邮箱,就需要开通邮箱功能;
传输协议
SMTP协议
发送邮件:我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。
POP3协议
接收邮件:我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。
概述
我们将用代码完成邮件的发送。这在实际项目中应用的非常广泛,比如注册需要发送邮件进行账号激活,再比如OA项目中利用邮件进行任务提醒等等。
使用Java发送 E-mail 十分简单,但是首先你应该准备 JavaMailAPI 和 JavaActivationFramework。
得到两个jar包:
- mail.jar
- activation.jar
纯文本的简单邮件发送
package com.niumo;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.security.GeneralSecurityException;
import java.util.Properties;
//发送一封简单的邮件
public class MailDemo01 {
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.setProperty("mail.host","smtp.qq.com"); // 设置QQ邮件服务器
prop.setProperty("mail.transport.protocol","smtp"); // 邮件发送协议
prop.setProperty("mail.smtp.auth","true"); // 需要验证用户名密码
// 关于QQ邮箱,还要设置SSL加密,加上以下代码即可,大厂,其他邮箱不需要
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable","true");
prop.put("mail.smtp.ssl.socketFactory",sf);
//使用JavaMail发送邮件的5个步骤
//1、创建定义整个应用程序所需的环境信息的 Session 对象
//QQ才有!其他邮箱就不用
Session session = Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码
return new PasswordAuthentication("发件人邮件用户名@qq.com","授权码");
}
});
//开启Session的debug模式,这样可以查看到程序发送Email的运行状态
session.setDebug(true);
//2、通过session得到transport对象
Transport ts = session.getTransport();
//3、使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com","发件人邮件用户名@qq.com","授权码");
//4、创建邮件:写邮件
//注意需要传递Session;
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("发件人邮件用户名@qq.com"));
//指明邮件的收件人
message.setRecipient(Message.RecipientType.TO,new InternetAddress("收件人邮件用户名@163.com"));
//邮件的标题
message.setSubject("牛魔瘦了");
//邮件的文本内容
message.setContent("<h1 style=\"color: red\">你好呀!</h1>","text/html;charset=UTF-8");
//5、发送邮件
ts.sendMessage(message,message.getAllRecipients());
//6、关闭连接
ts.close();
}
}
P41 网站注册发邮件实现
MIME(多用途互联网邮件扩展类型)
MimeBodyPart类
javax.mail.internet.MimeBodyPart类 表示的是一个MIME消息,它和MimeMessage类一样都是从Part接口继承过来。
MimeMultipart类
javax.mail.internet.MimeMultipart是抽象类 Multipart的实现子类,它用来组合多个MIME消息。一个MimeMultipart对象可以包含多个
代表MIME消息的MimeBodyPart对象。
带图片的复杂邮件发送
package com.niumo;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.security.GeneralSecurityException;
import java.util.Properties;
//发送一封简单的邮件
public class MailDemo01 {
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.setProperty("mail.host","smtp.qq.com"); // 设置QQ邮件服务器
prop.setProperty("mail.transport.protocol","smtp"); // 邮件发送协议
prop.setProperty("mail.smtp.auth","true"); // 需要验证用户名密码
// 关于QQ邮箱,还要设置SSL加密,加上以下代码即可,大厂,其他邮箱不需要
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable","true");
prop.put("mail.smtp.ssl.socketFactory",sf);
//使用JavaMail发送邮件的5个步骤
//1、创建定义整个应用程序所需的环境信息的 Session 对象
//QQ才有!其他邮箱就不用
Session session = Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码
return new PasswordAuthentication("发件人邮件用户名@qq.com","授权码");
}
});
//开启Session的debug模式,这样可以查看到程序发送Email的运行状态
session.setDebug(true);
//2、通过session得到transport对象
Transport ts = session.getTransport();
//3、使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com","发件人邮件用户名@qq.com","授权码");
//4、创建邮件:写邮件
//注意需要传递Session;
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("发件人邮件用户名@qq.com"));
//指明邮件的收件人
message.setRecipient(Message.RecipientType.TO,new InternetAddress("收件人邮件用户名@163.com"));
//邮件的标题
message.setSubject("牛魔瘦了");
//=======================================================================
//准备图片数据
MimeBodyPart image = new MimeBodyPart();
//图片需要经过数据处理... DataHandler:数据处理
DataHandler dh = new DataHandler(new FileDataSource("D:\\chaochao\\work\\projects\\study\\功能扩展\\mail-java\\src\\resources\\niumo.png"));
image.setDataHandler(dh); //在我们的Body中放入这个处理的图片数据
image.setContentID("niumo.png"); //给图片设置一个ID,我们在后面可以使用!
//准备正文数据
MimeBodyPart text = new MimeBodyPart();
text.setContent("这是一封邮件正文带图片<img src='cid:niumo.png'>的邮件","text/html;charset=UTF-8");
//描述数据关系
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(image);
mm.setSubType("related");
//设置到消息中,保存修改
message.setContent(mm); //把最后编辑好的邮件放到消息当中
message.saveChanges(); //保存修改!
//=======================================================================
//5、发送邮件
ts.sendMessage(message,message.getAllRecipients());
//6、关闭连接
ts.close();
}
}
带图片和附件的复杂邮件发送
package com.niumo;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Properties;
//发送一封简单的邮件
public class MailDemo01 {
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.setProperty("mail.host","smtp.qq.com"); // 设置QQ邮件服务器
prop.setProperty("mail.transport.protocol","smtp"); // 邮件发送协议
prop.setProperty("mail.smtp.auth","true"); // 需要验证用户名密码
// 关于QQ邮箱,还要设置SSL加密,加上以下代码即可,大厂,其他邮箱不需要
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable","true");
prop.put("mail.smtp.ssl.socketFactory",sf);
//使用JavaMail发送邮件的5个步骤
//1、创建定义整个应用程序所需的环境信息的 Session 对象
//QQ才有!其他邮箱就不用
Session session = Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码
return new PasswordAuthentication("发件人邮件用户名@qq.com","授权码");
}
});
//开启Session的debug模式,这样可以查看到程序发送Email的运行状态
session.setDebug(true);
//2、通过session得到transport对象
Transport ts = session.getTransport();
//3、使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com","发件人邮件用户名@qq.com","授权码");
//4、连接上之后我们需要发送邮件;
MimeMessage mimeMessage = imageMail(session);
//5、发送邮件
ts.sendMessage(mimeMessage,mimeMessage.getAllRecipients());
//6、关闭连接
ts.close();
}
public static MimeMessage imageMail(Session session) throws MessagingException{
//消息的固定信息
MimeMessage mimeMessage = new MimeMessage(session);
//邮件发送人
mimeMessage.setFrom(new InternetAddress("邮件发送人@qq.com"));
//邮件接收人
mimeMessage.setRecipient(Message.RecipientType.TO,new InternetAddress("邮件接收人@163.com"));
mimeMessage.setSubject("牛魔瘦了"); //邮件主题
/*
编写邮件内容
1.图片
2.附件
3.文本
*/
//图片
MimeBodyPart body1 = new MimeBodyPart();
body1.setDataHandler(new DataHandler(new FileDataSource("D:\\chaochao\\work\\projects\\study\\功能扩展\\mail-java\\src\\resources\\nm.png")));
body1.setContentID("nm.png"); //图片设置ID
//文本
MimeBodyPart body2 = new MimeBodyPart();
body2.setContent("请注意,我不是广告<img src='cid:nm.png'>","text/html;charset=utf-8");
//附件
MimeBodyPart body3 = new MimeBodyPart();
body3.setDataHandler(new DataHandler(new FileDataSource("D:\\chaochao\\work\\projects\\study\\功能扩展\\mail-java\\src\\resources\\JavaWeb_02_Tomcat详解.md")));
body3.setFileName("JavaWeb_02_Tomcat详解.md"); //附件设置名字
MimeBodyPart body4 = new MimeBodyPart();
body4.setDataHandler(new DataHandler(new FileDataSource("D:\\chaochao\\work\\projects\\study\\功能扩展\\mail-java\\src\\resources\\JavaWeb_03_HTTP协议详解.md")));
body4.setFileName("JavaWeb_03_HTTP协议详解.md"); //附件设置名字
//拼装邮件正文内容
MimeMultipart multipart1 = new MimeMultipart();
multipart1.addBodyPart(body1);
multipart1.addBodyPart(body2);
multipart1.setSubType("related"); //1.文本和图片内嵌成功!
//将拼装好的正文内容设置为主体
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(multipart1);
//拼接附件
MimeMultipart allFile = new MimeMultipart();
allFile.addBodyPart(body3); //附件
allFile.addBodyPart(body4); //附件
allFile.addBodyPart(contentText); //正文
allFile.setSubType("mixed"); //正文和附件都存在邮件中,所有类型设置为mixed;
//放到Message消息中
mimeMessage.setContent(allFile);
mimeMessage.saveChanges(); //保存修改
return mimeMessage;
}
}
JavaWeb发送邮件
现在很多的网站都提供有用户注册功能,通常我们注册成功之后就会收到一封来自注册网站的邮件。邮件里面的内容可能包含了我们的注册的用户名和密码以及一个激活账号的超链接等信息。今天我们也来实现一个这样的功能,用户注册成功之后,就将用户的注册信息以Email的形式发送到用户的注册邮箱当中,实现发送邮件功能就得借助于JavaMail了。
代码实现:
-
RegisterServlet.java
package com.niumo.servlet; import com.niumo.pojo.User; import com.niumo.utils.Sendmail; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; //脚手架 public class RegisterServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //接收用户请求,封装成对象 String username = req.getParameter("username"); String password = req.getParameter("password"); String email = req.getParameter("email"); User user = new User(username,password,email); //用户注册成功之后,给用户发送一封邮件 //我们使用线程来专门发送邮件,防止出现耗时,和网站注册人数过多的情况; Sendmail send = new Sendmail(user); //启动线程,线程启动之后就会执行run方法来发送邮件 send.start(); //注册用户 req.setAttribute("message","注册成功,我们已经发了一封注册信息的电子邮件,请查收!如果网络不稳定,可能过会儿才能收到!!!"); req.getRequestDispatcher("info.jsp").forward(req,resp); } }
-
Sendmail.java
package com.niumo.utils; //网站3秒原则:用户体验 //多线程实现用户体验! (异步处理) import com.niumo.pojo.User; import com.sun.mail.util.MailSSLSocketFactory; import javax.mail.*; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import java.security.GeneralSecurityException; import java.util.Properties; public class Sendmail extends Thread{ //用于给用户发送邮件的邮箱 private String from = "发送邮件的邮箱@qq.com"; //邮箱得用户名 private String username = "发送邮件的邮箱@qq.com"; //邮箱的密码 private String password = "授权码"; //发送邮件的服务器地址 private String host = "smtp.qq.com"; private User user; public Sendmail(User user){ this.user = user; } //重写run方法的实现,在run方法中发送邮件给指定的用户 @Override public void run() { try{ Properties prop = new Properties(); prop.setProperty("mail.host", host); // 设置QQ邮件服务器 prop.setProperty("mail.transport.protocol","smtp"); // 邮件发送协议 prop.setProperty("mail.smtp.auth","true"); // 需要验证用户名密码 // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可,大厂,其他邮箱不需要 MailSSLSocketFactory sf = new MailSSLSocketFactory(); sf.setTrustAllHosts(true); prop.put("mail.smtp.ssl.enable","true"); prop.put("mail.smtp.ssl.socketFactory",sf); //使用JavaMail发送邮件的5个步骤 //1、创建定义整个应用程序所需的环境信息的 Session 对象 //QQ才有!其他邮箱就不用 Session session = Session.getDefaultInstance(prop, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { //发件人邮件用户名、授权码 return new PasswordAuthentication("发送邮件的邮箱@qq.com","授权码"); } }); //开启Session的debug模式,这样可以查看到程序发送Email的运行状态 session.setDebug(true); //2、通过session得到transport对象 Transport ts = session.getTransport(); //3、使用邮箱的用户名和授权码连上邮件服务器 ts.connect(host,username,password); //4、创建邮件:写邮件 //注意需要传递Session; MimeMessage message = new MimeMessage(session); //指明邮件的发件人 message.setFrom(new InternetAddress(from)); //指明邮件的收件人 message.setRecipient(Message.RecipientType.TO,new InternetAddress(user.getEmail())); //邮件的标题 message.setSubject("用户注册邮件"); //邮件的文本内容 String info = "恭喜您注册成功,您的用户名:"+user.getUsername()+",您的密码:"+user.getPassword()+",请妥善保管,如有问题请联系网站客服!!!"; message.setContent(info,"text/html;charset=UTF-8"); message.saveChanges(); //5、发送邮件 ts.sendMessage(message,message.getAllRecipients()); //6、关闭连接 ts.close(); } catch (Exception e) { throw new RuntimeException(e); } } }
-
User.java
package com.niumo.pojo; import java.io.Serializable; public class User implements Serializable { private String username; private String password; private String email; public User() { } public User(String username, String password, String email) { this.username = username; this.password = password; this.email = email; } 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 getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + ", email='" + email + '\'' + '}'; } }
-
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0" metadata-complete="true"> <servlet> <servlet-name>RegisterServlet</servlet-name> <servlet-class>com.niumo.servlet.RegisterServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>RegisterServlet</servlet-name> <url-pattern>/RegisterServlet.do</url-pattern> </servlet-mapping> </web-app>
-
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>注册</title> </head> <body> <form action="${pageContext.request.contextPath}/RegisterServlet.do" method="post"> 用户名:<input type="text" name="username"><br/> 密码:<input type="password" name="password"><br/> 邮箱:<input type="text" name="email"><br/> <input type="submit" value="注册"> </form> </body> </html>
-
info.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>牛魔瘦了网站温馨提示</h1> ${message} </body> </html>
-
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.niumo</groupId> <artifactId>WebMail</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> </dependencies> </project>
Spring方式
-
DemoApplicationTests.java
package com.niumo.demo; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.MimeMessageHelper; import javax.mail.internet.MimeMessage; import java.io.File; @SpringBootTest class DemoApplicationTests { @Autowired JavaMailSenderImpl mailSender; @Test void contextLoads() { //发送邮件 //收件人 //内容 SimpleMailMessage message = new SimpleMailMessage(); message.setSubject("牛魔瘦了Java"); message.setText("Hello"); message.setFrom("发送邮件的邮箱@qq.com"); message.setTo("接收邮件的邮箱@163.com"); mailSender.send(message); } @Test public void test2() throws Exception { MimeMessage mimeMessage = mailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true); helper.setSubject("牛魔瘦了Java"); helper.setText("<h1>Hello</h1>",true); //附件 helper.addAttachment("images/1.png",new File("src\\main\\resources\\images\\1.png")); helper.addAttachment("images/2.png",new File("src\\main\\resources\\images\\2.png")); helper.setFrom("发送邮件的邮箱@qq.com"); helper.setTo("接收邮件的邮箱@163.com"); mailSender.send(mimeMessage); } }
-
application.properties
spring.mail.username=发送邮件的邮箱@qq.com spring.mail.password=授权码 spring.mail.host=smtp.qq.com spring.mail.properties.mail.smtp.ssl.enable=true
P42 之后该怎么持续学习
1、MyBatis(持久化)
2、Spring(容器思想)
3、SpringMVC
4、Linux
5、Spring Boot
6、Spring Cloud
电脑没有16G内存,不可能跑起来项目
7、Hadoop