JavaWeb_11_原生Web应用开发

尝试开发第一个web应用吧!点击跳转原生Web应用开发视频

留恋相似处,令我们停滞不前;接纳相异处,带我们改变未来。

超链接

idea运行java项目js中文乱码如何解决

配置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 固定步骤:

  1. 加载驱动
  2. 连接数据库,代表数据库
  3. 向数据库发送SQL的对象Statement,prepareStatement:CRUD
  4. 编写SQL(根据业务,不同的SQL)
  5. 执行SQL
  6. 关闭连接
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:CRUDStatement statement = connection.createStatement();//4.编写SQLString 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.编写SQLString 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.执行SQLint i = preparedStatement.executeUpdate();if(i>0){System.out.println("插入成功!");}//6.关闭连接,释放资源(一定要做)先开后关preparedStatement.close();connection.close();}
}

P29 JDBC事务

要么都成功,要么都失败!

ACID原则:保证数据的安全。

开启事务
事务提交  commit()
事务回滚  rollback()
关闭事务转账:
A:1000
B:1000A(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 {@Testpublic 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

项目搭建准备工作

  1. 搭建一个maven web项目

  2. 配置Tomcat

  3. 测试项目是否能够跑起来

  4. 导入项目中会遇到的jar包;

    servlet,jsp,mysql驱动,jstl,standard …

  5. 创建项目包结构

  1. 编写实体类;

    ORM映射:表-类映射

    package com.niumo.pojo;import java.util.Date;public class User {private Integer id; // idprivate 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; // idprivate 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; // idprivate 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; // idprivate String billCode; // 账单编号private String productName; // 商品名称private String productDesc; // 商品描述private String productUnit; //商品单位private BigDecimal productCount; //商品数量private BigDecimal totalPrice; // 总金额private Integer isPayment; // 是否支付private Integer providerId; // 供应商IDprivate 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;}
    }
    
  2. 编写基础公共类

    1. 数据库配置文件

      driver=com.mysql.cj.jdbc.Driver
      url=jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf-8&useSSL=true
      username=root
      password=nm123456
      
    2. 编写数据库的公共类

      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;}
      }
      
    3. 编写字符编码过滤器

      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() {}
      }
      
  3. 导入静态资源

    • calendar
    • css
    • images
    • js

P31 smbms登录流程实现

登录功能实现

  1. 编写前端页面

    • jsp

    • login.jsp

  2. 设置首页

    <!--设置欢迎页面-->
    <welcome-file-list><welcome-file>login.jsp</welcome-file>
    </welcome-file-list>
    
  3. 编写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;}
    
  4. 编写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;}
    }
    
  5. 业务层接口

    package com.niumo.service.user;import com.niumo.pojo.User;public interface UserService {//用户登录public User login(String userCode, String password);
    }
    
  6. 业务层实现类

    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;}
    }
    
  7. 编写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:控制层,调用业务层代码@Overrideprotected 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);}}@Overrideprotected 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";
    }
    
  8. 注册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>
    
  9. 测试访问,确保以上功能成功!

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 {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//移除用户的req.getSession().removeAttribute(Constants.USER_SESSION);resp.sendRedirect(req.getContextPath()+"/login.jsp"); //返回登录页面}@Overrideprotected 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密码修改实现

密码修改

  1. 导入前端素材

    <li><a href="${pageContext.request.contextPath }/jsp/pwdmodify.jsp">密码修改</a></li>
    
  2. 写项目,建议从底层向上写

  1. 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;}
    
  2. 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;}
    }
    
  3. 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);
    }
    
  4. 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;}
    }
    
  5. 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 {@Overrideprotected 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);}}@Overrideprotected 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","修改密码成功,请退出,使用新密码登录");//密码修改成功,移除当前Sessionreq.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();}}}
    
  6. 测试

P34 Ajax验证旧密码实现

优化密码修改使用Ajax

  1. 阿里巴巴的fastjson

    <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
    <dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.79</version>
    </dependency>
    
  2. 后台代码修改

    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 {@Overrideprotected 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);}}@Overrideprotected 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","修改密码成功,请退出,使用新密码登录");//密码修改成功,移除当前Sessionreq.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();}}});
    });
    
  3. 测试

P35 smbms用户管理底层实现

用户管理实现

思路:

  1. 导入分页的工具类

    PageSupport.java

  2. 用户列表页面导入

    userlist.jsp

    rollpage.jsp

1、获取用户数量


  1. UserDao

    //根据用户名或者角色查询用户总数
    public int getUserCount(Connection connection,String username,int userRole) throws SQLException;
    
  2. 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.iArrayList<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;
    }
    
  3. UserService

    //查询记录数
    public int getUserCount(String username,int userRole);
    
  4. 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、获取用户列表

  1. userdao

    //通过条件查询-userList
    public List<User> getUserList(Connection connection,String username,int userRole,int currentPageNo,int pageSize) throws SQLException;
    
  2. 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;
    }
    
  3. UserService

    //根据条件查询用户列表
    public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize);
    
  4. 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类对应。

  1. RoleDao

    //获取角色列表
    public List<Role> getRoleList(Connection connection) throws SQLException;
    
  2. 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;
    }
    
  3. RoleService

    //获取角色列表
    public List<Role> getRoleList();
    
  4. 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{//引入Daoprivate 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

  1. 获取用户前端的数据(查询)

  2. 判断请求是否需要执行,看参数的值判断

  3. 为了实现分页,需要计算出当前页面和总页面,页面大小…

  4. 用户列表展示

  5. 返回前端

    @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、使用类介绍

【文件上传的注意事项】

  1. 为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。

  2. 为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名

    1.txt 1.txt -时间戳 -uuid -md5 -位运算算法

  3. 要限制上传文件的最大值。

  4. 可以限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。

    .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.获取ServletFileUploadServletFileUpload 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); //缓存区大小为1Mfactory.setRepository(file); //临时目录的保存目录,需要一个Filereturn 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 = 10Mupload.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.pngString 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//文件真实存在的路径 realPathString realPath = uploadPath + "/" + uuidPath;//给每个文件创建一个对应的文件夹File realPathFile = new File(realPath);if (!realPathFile.exists()) {realPathFile.mkdir();}//=========================文件传输=========================////获得文件上传的流InputStream inputStream = fileItem.getInputStream();//创建一个文件输出流//realPath = 真实的文件夹;//差了一个文件;加上输出文件的名字+"/"+uuidFileNameFileOutputStream 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关键字

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() {@Overrideprotected 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() {@Overrideprotected 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() {@Overrideprotected 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 {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req, resp);}@Overrideprotected 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方法中发送邮件给指定的用户@Overridepublic 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() {@Overrideprotected 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;}@Overridepublic 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/javaeehttp://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 {@AutowiredJavaMailSenderImpl mailSender;@Testvoid contextLoads() {//发送邮件//收件人//内容SimpleMailMessage message = new SimpleMailMessage();message.setSubject("牛魔瘦了Java");message.setText("Hello");message.setFrom("发送邮件的邮箱@qq.com");message.setTo("接收邮件的邮箱@163.com");mailSender.send(message);}@Testpublic 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

JavaWeb_11_原生Web应用开发相关推荐

  1. go语言原生web框架 golang项目-书城商店

    go语言原生web框架 golang项目-书城商店 golang书城商店功能介绍 书城主页 分页展示 价格搜索 登录注册 加入购物车 购买 我的订单 查看详情 后台管理 图书管理 添加修改删除图书 订 ...

  2. web系统 手机app 能访问吗?_成都APP开发:原生APP开发与Web APP开发有什么区别呢?...

    智能手机上的APP应用软件对于人们来说已经成为日常工作生活当中必不可少的工具,无论是工作生活中的聊天交流,购物,饮食,出行,娱乐都会有相应的APP软件.目前常见的APP软件开发模式有两种,一种是原生A ...

  3. javaweb应用开发与实践pdf_基于阿里云打造「云原生」Web应用——「懒猪行」Web应用开发实践...

    作者:阿里云MVP 刘远程 背景 『懒猪行』专注于境外自由行S2B业务,涉及分销.终端用户服务.供应链等多个服务环节,随着业务规模的不端增加,我们一直在探索Web应用开发的最佳实践,以加快Web应用的 ...

  4. 原生开发什么意思_成都APP开发:原生APP开发与Web APP开发有什么区别呢?

    智能手机上的APP应用软件对于人们来说已经成为日常工作生活当中必不可少的工具,无论是工作生活中的聊天交流,购物,饮食,出行,娱乐都会有相应的APP软件.目前常见的APP软件开发模式有两种,一种是原生A ...

  5. 原生APP开发与WEB APP开发的区别

    APP开发模式通常分为Web APP与Native APP原生模式两种,这两种模式均各自有自己的优势,到底是采用Native App开发还是采用Web App开发一直是业界争论的焦点,但是随着HTML ...

  6. Delphi调用微信原生Web开发接口JS-SDK开发小程序及微信支付等的Rest API

    目录 Delphi调用微信原生Web开发接口JS-SDK开发小程序及微信支付等的Rest API 一.概述及API 1.JS-SDK是对之前的 WeixinJSBridge 的一个包装 2.JS-SD ...

  7. Web APP开发和原生app开发优势及区别

    原生app开发优势: Native App就是原生App的意思,所以原生App开发也就是指基于本地智能操作系统的App开发服务.原生App实际上是一种基于智能手机本地操作系统如Android.IOS和 ...

  8. 读书笔记:编写高质量代码--web前端开发修炼之道(二:5章)

    读书笔记:编写高质量代码--web前端开发修炼之道 这本书看得断断续续,不连贯,笔记也是有些马虎了,想了解这本书内容的童鞋可以借鉴我的这篇笔记,希望对大家有帮助. 笔记有点长,所以分为一,二两个部分: ...

  9. 现代化 Web 应用开发实战

    作者 | 寒斜(阿里云云原生中间件前端负责人) " 本篇实战将介绍如何以超低成本构建动态的 Web 站点,并且实现灵活扩展,限流等效果,最后再跟大家聊一聊"现代应用"的相 ...

最新文章

  1. 爬虫学习 pyspider和scrapy小结 / 与其他工具对比
  2. 【组合数学】递推方程 ( 常系数线性非齐次递推方程求解 | 递推方程标准型及通解 | 递推方程通解证明 )
  3. 高通软件发布版本简称
  4. 3、绘制E-R图:数据库概要设计阶段
  5. BZOJ 3529: [Sdoi2014]数表
  6. 数据库-SQL分类介绍及总结
  7. WEB前端 vue学习一使用 vue-cli 搭建项目
  8. Java Web会话管理
  9. jQuery初识 - jQuery是什么
  10. myeclipse 添加mysql数据库_myeclipse添加数据库
  11. 如何用python中的turtle库画三角形_Python如何使用turtle库绘制图形
  12. 用命令行连接mysql文件时出现错误_MySQL使用cmd命令窗口安装错误信息提示的解决方法...
  13. Transformers实战系列 之 文本生成
  14. HDU6266 - Hakase and Nano 狄利克雷卷积
  15. 指尖下的js —— 多触式web前端开发之三:处理复杂手势
  16. 【其他】vue项目集成富文本编辑器
  17. 纳米金13nm|金属纳米粒子/Nano gold制备方法-齐岳生物
  18. 2021年十大网络用语发布
  19. 客户协作 over 合同谈判
  20. Qt动画之鼠标水滴点击效果

热门文章

  1. 安卓手机如何防盗_安卓手机录屏如何调整录屏方向
  2. 赢在微点答案专区英语_英语的搭讪万能句,还不来学一下? l 从零开始学英语 E0220...
  3. 与游戏服务器失去连接该怎么办?
  4. 数据结构与算法期中考试
  5. 偷摸的回校,打枪的不要!
  6. 使用OPENCV简单实现具有肤质保留功能的磨皮增白算法
  7. php 直接使用十六进制,人们通常用十六进制而不用二进制书写计算机是为什么...
  8. 从键盘输入一句英文,实现把这句英文的单词按照字典顺序排序输出。
  9. 人脸识别(Face recognition)-简要介绍
  10. easyPoi导出excel工具类和设置excel导出样式(边框,背景色,字体)