视频地址
https://www.bilibili.com/video/BV1YU4y1p7wj?from=search&seid=1307576622141006226&spm_id_from=333.337.0.0
完整代码
1、项目介绍https://github.com/ShadowLim/Java_Project
- 云R记软件就是用于记录日常生活点滴。一款简单快速的个人记事备忘工具。会议记录、日程安排、生活备忘,奇思妙想、快乐趣事以及任何突发灵感都可快速记录到系统中。
- 本系统采用B/S 架构,使用 BootStrap + Jsp + Servlet + MySQL+ Tomcat
开发,使用 Maven构建,采用 Junit单元测试、Log4j搭建日志、使用POI导入导出报表, *** 作 DB 使用大名鼎鼎的 DBUtil。 - 本项目包含用户模块、类型模块、云记模块、数据报表、首页模块这几个核心模块,核心主旨是掌握功能的分析以及前后台数据交互。
tb_note表
字段名称 | 字段类型 | 字段描述 |
---|---|---|
noteId | int | 主键,自增 |
title | varchar | 标题 |
content | text | 内容 |
typeId | int | 外键,从属tb_note_type |
pubTime | timestamp | 发布时间 |
lon | float | 经度 |
lat | float | 纬度 |
tb_note_type表
字段名称 | 字段类型 | 字段描述 |
---|---|---|
typeId | int | 主键,自动增长 |
typeName | varchar | 类别名,在同一个用户下唯一 |
userId | int | 从属用户 |
tb_user表
字段名称 | 字段类型 | 字段描述 |
---|---|---|
userId | int | 主键,自动增长 |
uname | varchar | 用户名 |
upwd | varchar | 密码 |
nick | varchar | 昵称 |
head | varchar | 头像 |
mood | varchar | 心情 |
- 3.1.1 新建项目:
选择 “File” ——> “New” ——> “Project…” ,选择 “Maven”,设置 JDK 版本,选择 Maven Web 项目的模板
-
3.1.2 配置Maven:
-
3.1.3 设置项目信息:
设置项目的名称、存放的工作空间,以及对应的 GroupId
- 3.1.4 项目结构
创建好 Maven Web项目之后,对应的目录结构如下:
- 3.1.5 修改配置
在 pomx.xml 配置文件中,修改配置、添加依赖与插件
4.0.0
com.lezijie
lezijie-note
1.0-SNAPSHOT
war
lezijie-note Maven Webapp
http://www.example.com
UTF-8
1.8
1.8
junit
junit
4.12
test
javax.servlet
javax.servlet-api
4.0.1
provided
org.slf4j
slf4j-log4j12
1.7.2
org.slf4j
slf4j-api
1.7.2
mysql
mysql-connector-java
8.0.19
com.alibaba
fastjson
1.2.62
cn.hutool
hutool-all
5.4.7
commons-io
commons-io
2.4
commons-fileupload
commons-fileupload
1.3.1
javax.servlet
jstl
1.2
org.projectlombok
lombok
1.18.12
provided
lezijie-note
org.apache.maven.plugins
maven-compiler-plugin
2.3.2
1.8
UTF-8
org.apache.tomcat.maven
tomcat7-maven-plugin
2.1
8080
/note
tomcat7
3.2 分层思想
- 在项目的 src/main 目录下,新建 java 目录(源文件夹)与 resources 目录 (资源文件夹)。
- 定义包结构
- Java 的几种对象(PO,VO,DAO,BO,POJO)解释
- PO:
persistant object 持久对象,可以看成是与数据库中的表相映射的 Java 对象。
最简单的 PO 就是对应数据库中某个表中的一条记录,多个记录可以用 PO 的集合。
PO 中应该不包含任何对数据库的 *** 作。 - VO:
value object 值对象。通常用于业务层之间的数据传递,和 PO 一样也是仅仅包含数据而已。
但应是抽象出的业务对象,可以和表对应,也可以不,这根据业务的需要。 - DAO:
data access object 数据访问对象,此对象用于访问数据库。
通常和PO结合使用,DAO 中包含了各种数据库的 *** 作方法。
通过它的方法,结合 PO 对数据库进行相关的 *** 作。 - BO:
business object 业务对象,封装业务逻辑的 java 对象。
通过调用 DAO 方法,结合 PO,VO 进行业务 *** 作。 - POJO:
plain ordinary Java object 简单无规则 java 对象。
- 配置文件
在 src/main/resources 目录下,新建 db.properties 文件
# 连接MYSQL数据库的配置文件 注:等号的前后不要写空格
# 驱动名
jdbcName=com.mysql.cj.jdbc.Driver
# 数据库连接 ( db_lezijie_note是数据库的名称)
dbUrl=jdbc:mysql://localhost:3306/db_lezijie_note?
useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
# 数据库的连接账号 (账号基本上都是root)
dbName=root
# 数据库的连接密码 (每个人的数据库密码可能不一致,需要修改)
dbPwd=root1234
- 编写 DBUtil
在 com.lezijie.note.util 目录下,新建 Java 类
package com.lezijie.note.util;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* 乐字节:专注线上IT培训
* 需要视频资料,请添加:lezijie007
*/
public class DBUtil {
// 得到配置文件对象
private static Properties properties = new Properties();
static {
try {
// 加载配置文件(输入流)
InputStream in = DBUtil.class.getClassLoader().getResourceAsStream("db.properties");
// 通过load()方法将输入流的内容加载到配置文件对象中
properties.load(in);
// 通过配置文件对象的getProperty()方法获取驱动名,并加载驱动
Class.forName(properties.getProperty("jdbcName"));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接
* @return
*/
public static Connection getConnetion() {
Connection connection = null;
try {
// 得到数据库连接的相关信息
String dbUrl = properties.getProperty("dbUrl");
String dbName = properties.getProperty("dbName");
String dbPwd = properties.getProperty("dbPwd");
// 得到数据库连接
connection = DriverManager.getConnection(dbUrl, dbName, dbPwd);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return connection;
}
/**
* 关闭资源
* @param resultSet
* @param preparedStatement
* @param connection
*/
public static void close(ResultSet resultSet,
PreparedStatement preparedStatement,
Connection connection) {
try {
// 判断资源对象如果不为空,则关闭
if (resultSet != null) {
resultSet.close();
}
if (preparedStatement != null) {
preparedStatement.close();
}
if (connection != null) {
connection.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.4 单元测试
- 3.4.1 测试目录
在 src/main 目录下,新建 test 目录(测试目录),新建 java 目录(测试源文件夹)
- 3.4.2 测试数据库
在 test/java 目录的 com.lezijie.note 包下,新建测试类
/**
* 单元测试类
*/
public class TestDB {
@Test
public void testConnection() {
System.out.println(DBUtil.getConnection());
}
}
3.5 使用日志
- 配置文件
在 src/main/resources 目录下,新建 log4j.properties 文件
### 设置###stdout,
log4j.rootLogger = all,D,E,stdout
### 输出信息到控制台 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=D://logs/log.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = D://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ]
观察D和E盘会发现有「D://logs/log.log」和「E://logs/error.log」两个文件生成。
- 使用方式
下面两个代码均贴在上方的TestDB.java中
// 使用日志工厂类,记入日志
private static Logger logger = LoggerFactory.getLogger(DBUtil.class);
// 记录日志
logger.info("在{}时,获取数据库连接", new SimpleDateFormat("yyyy-MM-dd
HH:mm:ss").format(new Date()));
4、 用户模块
用户模块
通过用户行为来区分 actionName
用户登录 login
进入个人中心 userCenter
加载头像 userHead
验证昵称的唯一性 checkNick
修改用户信息 updateUser
用户退出 logout
在 src/main/wabapp 目录下, 新建 statics 文件夹,将静态资源拷贝进来(js、css、images及相关插
件)
- 通过用户行为来区分 actionName
- 查询类型列表 list
- 删除类型 delete
- 添加/修改类型 addOrUpdate
- 通过用户行为来区分 actionName
- 进入发布云记页面 view
- 添加或修改云记 addOrUpdate
- 查询云记详情 detail
- 删除云记 delete
- 分页查询云记列表 list
- 标题查询云记列表
- 日期分组查询云记列表
- 类型分组查询云记列表
- 用户发布云记位置的散点图
- 云记发布月份的柱状图
- BaseDao
package com.lezijie.note.dao;
import com.lezijie.note.util.DBUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
/**
* 基础的JDBC *** 作类
* 更新 *** 作 (添加、修改、删除)
* 查询 *** 作
* 1. 查询一个字段 (只会返回一条记录且只有一个字段;常用场景:查询总数量)
* 2. 查询集合
* 3. 查询某个对象
*/
public class BaseDao {
/**
* 更新 *** 作
* 添加、修改、删除
* 1. 得到数据库连接
* 2. 定义sql语句 (添加语句、修改语句、删除语句)
* 3. 预编译
* 4. 如果有参数,则设置参数,下标从1开始 (数组或集合、循环设置参数)
* 5. 执行更新,返回受影响的行数
* 6. 关闭资源
*
* 注:需要两个参数:sql语句、所需参数的集合
*
* @param sql
* @param params
* @return
*/
public static int executeUpdate(String sql, List
- NoteDao
package com.lezijie.note.dao;
import cn.hutool.core.util.StrUtil;
import com.lezijie.note.po.Note;
import com.lezijie.note.vo.NoteVo;
import java.util.ArrayList;
import java.util.List;
public class NoteDao {
/**
* 添加或修改云记,返回受影响的行数
* @param note
* @return
*/
public int addOrUpdate(Note note) {
// 定义SQL语句
String sql = "";
// 设置参数
List params = new ArrayList<>();
params.add(note.getTypeId());
params.add(note.getTitle());
params.add(note.getContent());
// 判断noteId是否为空;如果为空,则为添加 *** 作;如果不为空,则为修改 *** 作
if (note.getNoteId() == null) { // 添加 *** 作
sql = "insert into tb_note (typeId, title, content, pubTime, lon, lat) values (?,?,?,now(),?,?)";
params.add(note.getLon());
params.add(note.getLat());
} else { // 修改 *** 作
sql = "update tb_note set typeId = ?, title = ? , content = ? where noteId = ?";
params.add(note.getNoteId());
}
// 调用BaseDao的更新方法
int row = BaseDao.executeUpdate(sql, params);
return row;
}
/**
* 查询当前登录用户的云记数量,返回总记录数
* @param userId
* @return
*/
public long findNoteCount(Integer userId, String title, String date, String typeId) {
// 定义SQL语句
String sql = "SELECT count(1) FROM tb_note n INNER JOIN " +
" tb_note_type t on n.typeId = t.typeId " +
" WHERE userId = ? ";
// 设置参数
List params = new ArrayList<>();
params.add(userId);
// 判断条件查询的参数是否为空 (如果查询的参数不为空,则拼接sql语句,并设置所需要的参数)
if (!StrUtil.isBlank(title)) { // 标题查询
// 拼接条件查询的sql语句
sql += " and title like concat('%',?,'%') ";
// 设置sql语句所需要的参数
params.add(title);
} else if (!StrUtil.isBlank(date)) { // 日期查询
// 拼接条件查询的sql语句
sql += " and date_format(pubTime,'%Y年%m月') = ? ";
// 设置sql语句所需要的参数
params.add(date);
} else if (!StrUtil.isBlank(typeId)) { // 类型查询
// 拼接条件查询的sql语句
sql += " and n.typeId = ? ";
// 设置sql语句所需要的参数
params.add(typeId);
}
// 调用BaseDao的查询方法
long count = (long) BaseDao.findSingleValue(sql, params);
return count;
}
/**
* 分页查询当前登录用户下当前页的数据列表,返回note集合
* @param userId
* @param index
* @param pageSize
* @return
*/
public List findNoteListByPage(Integer userId, Integer index, Integer pageSize,
String title, String date, String typeId) {
// 定义SQL语句
String sql = "SELECT noteId,title,pubTime FROM tb_note n INNER JOIN " +
"tb_note_type t on n.typeId = t.typeId WHERE userId = ? ";
// 设置参数
List params = new ArrayList<>();
params.add(userId);
// 判断条件查询的参数是否为空 (如果查询的参数不为空,则拼接sql语句,并设置所需要的参数)
if (!StrUtil.isBlank(title)) {
// 拼接条件查询的sql语句
sql += " and title like concat('%',?,'%') ";
// 设置sql语句所需要的参数
params.add(title);
} else if (!StrUtil.isBlank(date)) { // 日期查询
// 拼接条件查询的sql语句
sql += " and date_format(pubTime,'%Y年%m月') = ? ";
// 设置sql语句所需要的参数
params.add(date);
} else if (!StrUtil.isBlank(typeId)) { // 类型查询
// 拼接条件查询的sql语句
sql += " and n.typeId = ? ";
// 设置sql语句所需要的参数
params.add(typeId);
}
// 拼接分页的sql语句 (limit语句需要写在sql语句最后)
sql += " order by pubTime desc limit ?,?";
params.add(index);
params.add(pageSize);
// 调用BaseDao的查询方法
List noteList = BaseDao.queryRows(sql, params, Note.class);
return noteList;
}
/**
* 通过日期分组查询当前登录用户下的云记数量
* @param userId
* @return
*/
public List findNoteCountByDate(Integer userId) {
// 定义SQL语句
String sql = "SELECT count(1) noteCount,DATE_FORMAT(pubTime,'%Y年%m月') groupName FROM tb_note n " +
" INNER JOIN tb_note_type t ON n.typeId = t.typeId WHERE userId = ? " +
" GROUP BY DATE_FORMAT(pubTime,'%Y年%m月')" +
" ORDER BY DATE_FORMAT(pubTime,'%Y年%m月') DESC ";
// 设置参数
List params = new ArrayList<>();
params.add(userId);
// 调用BaseDao的查询方法
List list = BaseDao.queryRows(sql, params, NoteVo.class);
return list;
}
/**
* 通过类型分组查询当前登录用户下的云记数量
* @param userId
* @return
*/
public List findNoteCountByType(Integer userId) {
// 定义SQL语句
String sql = "SELECT count(noteId) noteCount, t.typeId, typeName groupName FROM tb_note n " +
" RIGHT JOIN tb_note_type t ON n.typeId = t.typeId WHERE userId = ? " +
" GROUP BY t.typeId ORDER BY COUNT(noteId) DESC ";
// 设置参数
List params = new ArrayList<>();
params.add(userId);
// 调用BaseDao的查询方法
List list = BaseDao.queryRows(sql, params, NoteVo.class);
return list;
}
/**
* 通过id查询云记对象
* @param noteId
* @return
*/
public Note findNoteById(String noteId) {
// 定义SQL
String sql = "select noteId,title,content,pubTime,typeName,n.typeId from tb_note n " +
" inner join tb_note_type t on n.typeId=t.typeId where noteId = ?";
// 设置参数
List params = new ArrayList<>();
params.add(noteId);
// 调用BaseDao的查询方法
Note note = (Note) BaseDao.queryRow(sql, params, Note.class);
return note;
}
/**
* 通过noteId删除云记记录,返回受影响的行数
* @param noteId
* @return
*/
public int deleteNoteById(String noteId) {
String sql = "delete from tb_note where noteId= ?";
// 设置参数
List params = new ArrayList<>();
params.add(noteId);
// 调用BaseDao
int row = BaseDao.executeUpdate(sql, params);
return row;
}
/**
* 通过用户ID查询云记列表
* @param userId
* @return
*/
public List queryNoteList(Integer userId) {
// 定义SQL语句
String sql = "select lon, lat from tb_note n inner join tb_note_type t on n.typeId = t.typeId where userId = ?";
// 设置参数
List params = new ArrayList<>();
params.add(userId);
// 调用BaseDao
List list = BaseDao.queryRows(sql, params, Note.class);
return list;
}
}
- NoteTypeDao
package com.lezijie.note.dao;
import com.lezijie.note.po.NoteType;
import com.lezijie.note.util.DBUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class NoteTypeDao {
/**
* 通过用户ID查询类型集合
1. 定义SQL语句
String sql = "select typeId,typeName,userId from tb_note_type where userId = ? ";
2. 设置参数列表
3. 调用BaseDao的查询方法,返回集合
4. 返回集合
* @param userId
* @return
*/
public List findTypeListByUserId(Integer userId) {
// 1. 定义SQL语句
String sql = "select typeId,typeName,userId from tb_note_type where userId = ? ";
// 2. 设置参数列表
List params = new ArrayList<>();
params.add(userId);
// 3. 调用BaseDao的查询方法,返回集合
List list = BaseDao.queryRows(sql, params, NoteType.class);
// 4. 返回集合
return list;
}
/**
* 通过类型ID查询云记记录的数量,返回云记数量
*
* @param typeId
* @return
*/
public long findNoteCountByTypeId(String typeId) {
// 定义SQL语句
String sql = "select count(1) from tb_note where typeId = ?";
// 设置参数集合
List params = new ArrayList<>();
params.add(typeId);
// 调用BaseDao
long count = (long) BaseDao.findSingleValue(sql, params);
return count;
}
/**
* 通过类型ID删除指定的类型记录,返回受影响的行数
* @param typeId
* @return
*/
public int deleteTypeById(String typeId) {
// 定义SQL语句
String sql = "delete from tb_note_type where typeId = ?";
// 设置参数集合
List params = new ArrayList<>();
params.add(typeId);
// 调用BaseDao
int row = BaseDao.executeUpdate(sql, params);
return row;
}
/**
* 查询当前登录用户下,类型名称是否唯一
* 返回1,表示成功
* 返回0,表示失败
* @param typeName
* @param userId
* @param typeId
* @return
*/
public Integer checkTypeName(String typeName, Integer userId, String typeId) {
// 定义SQL语句
String sql = "select * from tb_note_type where userId = ? and typeName = ?";
// 设置参数
List params = new ArrayList<>();
params.add(userId);
params.add(typeName);
// 执行查询 *** 作
NoteType noteType = (NoteType) BaseDao.queryRow(sql, params, NoteType.class);
// 如果对象为空,表示可用
if (noteType == null) {
return 1;
} else {
// 如果是修改 *** 作,则需要判断是否是当前记录本身
if (typeId.equals(noteType.getTypeId().toString())) {
return 1;
}
}
return 0;
}
/**
* 添加方法,返回主键
* @param typeName
* @param userId
* @return
*/
public Integer addType(String typeName, Integer userId) {
Integer key = null;
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
// 得到数据库连接
connection = DBUtil.getConnetion();
// 定义SQL语句
String sql = "insert into tb_note_type (typeName,userId) values (?,?)";
// 预编译
preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
// 设置参数
preparedStatement.setString(1,typeName);
preparedStatement.setInt(2, userId);
// 执行更新,返回受影响的行数
int row = preparedStatement.executeUpdate();
// 判断受影响的行数
if (row > 0) {
// 获取返回主键的结果集
resultSet = preparedStatement.getGeneratedKeys();
// 得到主键的值
if (resultSet.next()) {
key = resultSet.getInt(1);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭资源
DBUtil.close(resultSet,preparedStatement,connection);
}
return key;
}
/**
* 修改方法,返回受影响的行数
* @param typeName
* @param typeId
* @return
*/
public Integer updateType(String typeName, String typeId) {
// 定义SQL语句
String sql = "update tb_note_type set typeName = ? where typeId = ?";
// 设置参数
List params = new ArrayList<>();
params.add(typeName);
params.add(typeId);
// 调用BaseDao的更新方法
int row = BaseDao.executeUpdate(sql, params);
return row;
}
}
- UserDao
package com.lezijie.note.dao;
import com.lezijie.note.po.User;
import com.lezijie.note.util.DBUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class UserDao {
/**
* 通过用户名查询用户对象
* 1. 定义sql语句
* 2. 设置参数集合
* 3. 调用BaseDao的查询方法
* @param userName
* @return
*/
public User queryUserByName(String userName) {
// 1. 定义sql语句
String sql = "select * from tb_user where uname = ?";
// 2. 设置参数集合
List params = new ArrayList<>();
params.add(userName);
// 3. 调用BaseDao的查询方法
User user = (User) BaseDao.queryRow(sql, params, User.class);
return user;
}
/**
通过用户名查询用户对象, 返回用户对象
1. 获取数据库连接
2. 定义sql语句
3. 预编译
4. 设置参数
5. 执行查询,返回结果集
6. 判断并分析结果集
7. 关闭资源
* @param userName
* @return
*/
public User queryUserByName02(String userName) {
User user = null;
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
// 1. 获取数据库连接
connection = DBUtil.getConnetion();
// 2. 定义sql语句
String sql = "select * from tb_user where uname = ?";
// 3. 预编译
preparedStatement = connection.prepareStatement(sql);
// 4. 设置参数
preparedStatement.setString(1, userName);
// 5. 执行查询,返回结果集
resultSet = preparedStatement.executeQuery();
// 6. 判断并分析结果集
if (resultSet.next()) {
user = new User();
user.setUserId(resultSet.getInt("userId"));
user.setUname(userName);
user.setHead(resultSet.getString("head"));
user.setMood(resultSet.getString("mood"));
user.setNick(resultSet.getString("nick"));
user.setUpwd(resultSet.getString("upwd"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 7. 关闭资源
DBUtil.close(resultSet,preparedStatement,connection);
}
return user;
}
/**
* 通过昵称与用户ID查询用户对象
* 1. 定义SQL语句
* 通过用户ID查询除了当前登录用户之外是否有其他用户使用了该昵称
* 指定昵称 nick (前台传递的参数)
* 当前用户 userId (session作用域中的user对象)
* String sql = "select * from tb_user where nick = ? and userId != ?";
* 2. 设置参数集合
* 3. 调用BaseDao的查询方法
* @param nick
* @param userId
* @return
*/
public User queryUserByNickAndUserId(String nick, Integer userId) {
// 1. 定义SQL语句
String sql = "select * from tb_user where nick = ? and userId != ?";
// 2. 设置参数集合
List params = new ArrayList<>();
params.add(nick);
params.add(userId);
// 3. 调用BaseDao的查询方法
User user = (User) BaseDao.queryRow(sql, params, User.class);
return user;
}
/**
* 通过用户ID修改用户信息
1. 定义SQL语句
String sql = "update tb_user set nick = ?, mood = ?, head = ? where userId = ? ";
2. 设置参数集合
3. 调用BaseDao的更新方法,返回受影响的行数
4. 返回受影响的行数
* @param user
* @return
*/
public int updateUser(User user) {
// 1. 定义SQL语句
String sql = "update tb_user set nick = ?, mood = ?, head = ? where userId = ? ";
// 2. 设置参数集合
List params = new ArrayList<>();
params.add(user.getNick());
params.add(user.getMood());
params.add(user.getHead());
params.add(user.getUserId());
// 3. 调用BaseDao的更新方法,返回受影响的行数
int row = BaseDao.executeUpdate(sql, params);
return row;
}
}
9.1.2 filter层
- EncodingFilter
package com.lezijie.note.filter;
import cn.hutool.core.util.StrUtil;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
*
* 字符乱码处理过滤器
*
* 请求乱码解决
乱码原因:
服务器默认的解析编码为ISO-8859-1,不支持中文。
乱码情况:
POST请求
Tomcat7及以下版本 乱码
Tomcat8及以上版本 乱码
GET请求
Tomcat7及以下版本 乱码
Tomcat8及以上版本 不乱码
解决方案:
POST请求:
无论是什么版本的服务器,都会出现乱码,需要通过request.setCharacterEncoding("UTF-8")设置编码格式。(只针对POST请求有效)
GET请求
Tomcat8及以上版本,不会乱码,不需要处理。
Tomcat7及以下版本,需要单独处理。
new String(request.getParamater("xxx").getBytes("ISO-8859-1"),"UTF-8");
*/
@WebFilter("/*") // 过滤所有资源
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 基于HTTP
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 处理POST请求 (只针对POST请求有效,GET请求不受影响)
request.setCharacterEncoding("UTF-8");
// 得到请求类型 (GET|POST)
String method = request.getMethod();
// 如果是GET请求,则判断服务器版本
if ("GET".equalsIgnoreCase(method)) { // 忽略大小写比较
// 得到服务器版本
String serverInfo = request.getServletContext().getServerInfo(); // Apache Tomcat/7.0.79
// 通过截取字符串,得到具体的版本号
String version = serverInfo.substring(serverInfo.lastIndexOf("/")+1,serverInfo.indexOf("."));
// 判断服务器版本是否是Toncat7级以下
if (version != null && Integer.parseInt(version) < 8) {
// Tomcat7及以下版本的服务器的GET请求
MyWapper myRequest = new MyWapper(request);
// 放行资源
filterChain.doFilter(myRequest, response);
return;
}
}
filterChain.doFilter(request,response);
}
/**
* 1. 定义内部类 (类的本质是request对象)
* 2. 继承 HttpServletRequestWrapper包装类
* 3. 重写getarameterP()方法
*/
class MyWapper extends HttpServletRequestWrapper {
// 定义成员变量 HttpServletRequest对象 (提升构造器中request对象的作用域)
private HttpServletRequest request;
/**
* 带参构造
* 可以得到需要处理的request对象
* @param request
*/
public MyWapper(HttpServletRequest request) {
super(request);
this.request = request;
}
/**
* 重写getParameter方法,处理乱码问题
* @param name
* @return
*/
@Override
public String getParameter(String name) {
// 获取参数 (乱码的参数值)
String value = request.getParameter(name);
// 判断参数值是否为空
if (StrUtil.isBlank(value)) {
return value;
}
// 通过new String()处理乱码
try {
value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
}
}
- LoginAccessFilter
package com.lezijie.note.filter;
import com.lezijie.note.po.User;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 非法访问拦截
* 拦截的资源:
* 所有的资源 /*
*
* 需要被放行的资源
* 1. 指定页面,放行 (用户无需登录的即可访问的页面;例如:登录页面login.jsp、注册页面register.jsp等)
* 2. 静态资源,放行 (存放在statics目录下的资源;例如:js、css、images等)
* 3. 指定行为,放行 (用户无需登录即可执行的 *** 作;例如:登录 *** 作actionName=login等)
* 4. 登录状态,放行 (判断session作用域中是否存在user对象;存在则放行,不存在,则拦截跳转到登录页面)
*
* 免登录(自动登录)
* 通过Cookie和Session对象实现
*
* 什么时候使用免登录:
* 当用户处于未登录状态,且去请求需要登录才能访问的资源时,调用自动登录功能
*
* 目的:
* 让用户处于登录状态(自动调用登录方法)
*
* 实现:
* 从Cookie对象中获取用户的姓名与密码,自动执行登录 *** 作
* 1. 获取Cookie数组 request.getCookies()
* 2. 判断Cookie数组
* 3. 遍历Cookie数组,获取指定的Cookie对象 (name为user的cookie对象)
* 4. 得到对应的cookie对象的value (姓名与密码:userName-userPwd)
* 5. 通过split()方法将value字符串分割成数组
* 6. 从数组中分别得到对应的姓名与密码值
* 7. 请求转发到登录 *** 作 user?actionName=login&userName=姓名&userPwd=密码
* 8. return
*
* 如果以上判断都不满足,则拦截跳转到登录页面
*/
@WebFilter("/*")
public class LoginAccessFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 基于HTTP
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 得到访问的路径
String path = request.getRequestURI(); // 格式:项目路径/资源路径
// 1. 指定页面,放行 (用户无需登录的即可访问的页面;例如:登录页面login.jsp、注册页面register.jsp等)
if (path.contains("/login.jsp")) {
filterChain.doFilter(request, response);
return;
}
// 2. 静态资源,放行 (存放在statics目录下的资源;例如:js、css、images等)
if (path.contains("/statics")) {
filterChain.doFilter(request, response);
return;
}
// 3. 指定行为,放行 (用户无需登录即可执行的 *** 作;例如:登录 *** 作actionName=login等)
if (path.contains("/user")) {
// 得到用户行为
String actionName = request.getParameter("actionName");
// 判断是否是登录 *** 作
if ("login".equals(actionName)) {
filterChain.doFilter(request, response);
return;
}
}
// 4. 登录状态,放行 (判断session作用域中是否存在user对象;存在则放行,不存在,则拦截跳转到登录页面)
// 获取Session作用域中的user对象
User user = (User) request.getSession().getAttribute("user");
// 判断user对象是否为空
if (user != null) {
filterChain.doFilter(request, response);
return;
}
/**
* 免登录 (自动登录)
* 从Cookie对象中获取用户的姓名与密码,自动执行登录 *** 作
*/
// 1. 获取Cookie数组 request.getCookies()
Cookie[] cookies = request.getCookies();
// 2. 判断Cookie数组
if (cookies != null && cookies.length > 0) {
// 3. 遍历Cookie数组,获取指定的Cookie对象 (name为user的cookie对象)
for (Cookie cookie : cookies) {
if ("user".equals(cookie.getName())) {
// 4. 得到对应的cookie对象的value (姓名与密码:userName-userPwd)
String value = cookie.getValue(); // admin-123456
// 5. 通过split()方法将value字符串分割成数组
String[] val = value.split("-");
// 6. 从数组中分别得到对应的姓名与密码值
String userName = val[0];
String userPwd = val[1];
// 7. 请求转发到登录 *** 作 user?actionName=login&userName=姓名&userPwd=密码
String url = "user?actionName=login&rem=1&userName=" + userName + "&userPwd=" + userPwd;
request.getRequestDispatcher(url).forward(request, response);
// 8. return
return;
}
}
}
// 拦截请求,重定向跳转到登录页面
response.sendRedirect("login.jsp");
}
@Override
public void destroy() {
}
}
9.1.3 po层
- Note
package com.lezijie.note.po;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
@Getter
@Setter
public class Note {
private Integer noteId; // 云记ID
private String title; // 云记标题
private String content; // 云记内容
private Integer typeId; // 云记类型ID
private Date pubTime; // 发布时间
private Float lon; // 经度
private Float lat; // 纬度
private String typeName;
}
- NoteType
package com.lezijie.note.po;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class NoteType {
private Integer typeId; // 类型ID
private String typeName; // 类型名称
private Integer userId; // 用户ID
}
- User
package com.lezijie.note.po;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class User {
private Integer userId; // 用户ID
private String uname; // 用户名称
private String upwd; // 用户密码
private String nick; // 用户昵称
private String head; // 用户头像
private String mood; // 用户签名
public void setUserId(Integer userId) {
this.userId = userId;
}
}
9.1.4 service层
- NoteService
package com.lezijie.note.service;
import cn.hutool.core.util.StrUtil;
import com.lezijie.note.dao.NoteDao;
import com.lezijie.note.po.Note;
import com.lezijie.note.util.Page;
import com.lezijie.note.vo.NoteVo;
import com.lezijie.note.vo.ResultInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class NoteService {
private NoteDao noteDao = new NoteDao();
/**
* 添加或修改云记
1. 参数的非空判断
如果为空,code=0,msg=xxx,result=note对象,返回resultInfo对象
2. 设置回显对象 Note对象
3. 调用Dao层,添加云记记录,返回受影响的行数
4. 判断受影响的行数
如果大于0,code=1
如果不大于0,code=0,msg=xxx,result=note对象
5. 返回resultInfo对象
* @param typeId
* @param title
* @param content
* @return
*/
public ResultInfo addOrUpdate(String typeId, String title,
String content, String noteId, String lon, String lat) {
ResultInfo resultInfo = new ResultInfo<>();
// 1. 参数的非空判断
if (StrUtil.isBlank(typeId)) {
resultInfo.setCode(0);
resultInfo.setMsg("请选择云记类型!");
return resultInfo;
}
if (StrUtil.isBlank(title)) {
resultInfo.setCode(0);
resultInfo.setMsg("云记标题不能为空!");
return resultInfo;
}
if (StrUtil.isBlank(content)) {
resultInfo.setCode(0);
resultInfo.setMsg("云记内容不能为空!");
return resultInfo;
}
// 设置经纬度的默认,默认设置为北京 116.404, 39.915
if (lon == null || lat == null) {
lon = "116.404";
lat = "39.915";
}
// 2. 设置回显对象 Note对象
Note note = new Note();
note.setTitle(title);
note.setContent(content);
note.setTypeId(Integer.parseInt(typeId));
note.setLon(Float.parseFloat(lon));
note.setLat(Float.parseFloat(lat));
// 判断云记ID是否为空
if (!StrUtil.isBlank(noteId)) {
note.setNoteId(Integer.parseInt(noteId));
}
resultInfo.setResult(note);
// 3. 调用Dao层,添加云记记录,返回受影响的行数
int row = noteDao.addOrUpdate(note);
// 4. 判断受影响的行数
if (row > 0) {
resultInfo.setCode(1);
} else {
resultInfo.setCode(0);
resultInfo.setResult(note);
resultInfo.setMsg("更新失败!");
}
return resultInfo;
}
/**
* 分页查询云记列表
1. 参数的非空校验
如果分页参数为空,则设置默认值
2. 查询当前登录用户的云记数量,返回总记录数 (long类型)
3. 判断总记录数是否大于0
4. 如果总记录数大于0,调用Page类的带参构造,得到其他分页参数的值,返回Page对象
5. 查询当前登录用户下当前页的数据列表,返回note集合
6. 将note集合设置到page对象中
7. 返回Page对象
* @param pageNumStr
* @param pageSizeStr
* @param userId
* @param title 条件查询的参数:标题
* @return
*/
public Page findNoteListByPage(String pageNumStr, String pageSizeStr,
Integer userId, String title, String date, String typeId) {
// 设置分页参数的默认值
Integer pageNum = 1; // 默认当前页是第一页
Integer pageSize = 5; // 默认每页显示5条数据
// 1. 参数的非空校验 (如果参数不为空,则设置参数)
if (!StrUtil.isBlank(pageNumStr)) {
// 设置当前页
pageNum = Integer.parseInt(pageNumStr);
}
if (!StrUtil.isBlank(pageSizeStr)) {
// 设置每页显示的数量
pageSize = Integer.parseInt(pageSizeStr);
}
// 2. 查询当前登录用户的云记数量,返回总记录数 (long类型)
long count = noteDao.findNoteCount(userId, title, date, typeId);
// 3. 判断总记录数是否大于0
if (count < 1) {
return null;
}
// 4. 如果总记录数大于0,调用Page类的带参构造,得到其他分页参数的值,返回Page对象
Page page = new Page<>(pageNum, pageSize, count);
// 得到数据库中分页查询的开始下标
Integer index = (pageNum -1) * pageSize;
// 5. 查询当前登录用户下当前页的数据列表,返回note集合
List noteList = noteDao.findNoteListByPage(userId, index, pageSize, title, date, typeId);
// 6. 将note集合设置到page对象中
page.setDataList(noteList);
// 7. 返回Page对象
return page;
}
/**
* 通过日期分组查询当前登录用户下的云记数量
* @param userId
* @return
*/
public List findNoteCountByDate(Integer userId) {
return noteDao.findNoteCountByDate(userId);
}
/**
* 通过类型分组查询当前登录用户下的云记数量
* @param userId
* @return
*/
public List findNoteCountByType(Integer userId) {
return noteDao.findNoteCountByType(userId);
}
/**
* 查询云记详情
1. 参数的非空判断
2. 调用Dao层的查询,通过noteId查询note对象
3. 返回note对象
* @param noteId
* @return
*/
public Note findNoteById(String noteId) {
// 1. 参数的非空判断
if (StrUtil.isBlank(noteId)) {
return null;
}
// 2. 调用Dao层的查询,通过noteId查询note对象
Note note = noteDao.findNoteById(noteId);
// 3. 返回note对象
return note;
}
/**
* 删除云记
1. 判断参数
2. 调用Dao层的更新方法,返回受影响的行数
3. 判断受影响的行数是否大于0
如果大于0,返回1;否则返回0
* @param noteId
* @return
*/
public Integer deleteNote(String noteId) {
// 1. 判断参数
if (StrUtil.isBlank(noteId)) {
return 0;
}
// 2. 调用Dao层的更新方法,返回受影响的行数
int row = noteDao.deleteNoteById(noteId);
// 3. 判断受影响的行数是否大于0
if (row > 0) {
return 1;
}
return 0;
}
/**
* 通过月份查询对应的云记数量
* @param userId
* @return
*/
public ResultInfo
- NoteTypeService
package com.lezijie.note.service;
import cn.hutool.core.util.StrUtil;
import com.lezijie.note.dao.NoteTypeDao;
import com.lezijie.note.po.NoteType;
import com.lezijie.note.vo.ResultInfo;
import java.util.List;
public class NoteTypeService {
private NoteTypeDao typeDao = new NoteTypeDao();
/**
* 查询类型列表
1. 调用Dao层的查询方法,通过用户ID查询类型集合
2. 返回类型集合
* @param userId
* @return
*/
public List findTypeList(Integer userId) {
List typeList = typeDao.findTypeListByUserId(userId);
return typeList;
}
/**
* 删除类型
1. 判断参数是否为空
2. 调用Dao层,通过类型ID查询云记记录的数量
3. 如果云记数量大于0,说明存在子记录,不可删除
code=0,msg="该类型存在子记录,不可删除",返回resultInfo对象
4. 如果不存在子记录,调用Dao层的更新方法,通过类型ID删除指定的类型记录,返回受影响的行数
5. 判断受影响的行数是否大于0
大于0,code=1;否则,code=0,msg="删除失败"
6. 返回ResultInfo对象
* @param typeId
* @return
*/
public ResultInfo deleteType(String typeId) {
ResultInfo resultInfo = new ResultInfo<>();
// 1. 判断参数是否为空
if (StrUtil.isBlank(typeId)) {
resultInfo.setCode(0);
resultInfo.setMsg("系统异常,请重试!");
return resultInfo;
}
// 2. 调用Dao层,通过类型ID查询云记记录的数量
long noteCount = typeDao.findNoteCountByTypeId(typeId);
// 3. 如果云记数量大于0,说明存在子记录,不可删除
if (noteCount > 0) {
resultInfo.setCode(0);
resultInfo.setMsg("该类型存在子记录,不可删除!!");
return resultInfo;
}
// 4. 如果不存在子记录,调用Dao层的更新方法,通过类型ID删除指定的类型记录,返回受影响的行数
int row = typeDao.deleteTypeById(typeId);
// 5. 判断受影响的行数是否大于0
if (row > 0) {
resultInfo.setCode(1);
} else {
resultInfo.setCode(0);
resultInfo.setMsg("删除失败!");
}
return resultInfo;
}
/**
* 添加或修改类型
1. 判断参数是否为空 (类型名称)
如果为空,code=0,msg=xxx,返回ResultInfo对象
2. 调用Dao层,查询当前登录用户下,类型名称是否唯一,返回0或1
如果不可用,code=0,msg=xxx,返回ResultInfo对象
3. 判断类型ID是否为空
如果为空,调用Dao层的添加方法,返回主键 (前台页面需要显示添加成功之后的类型ID)
如果不为空,调用Dao层的修改方法,返回受影响的行数
4. 判断 主键/受影响的行数 是否大于0
如果大于0,则更新成功
code=1,result=主键
如果不大于0,则更新失败
code=0,msg=xxx
* @param typeName
* @param userId
* @param typeId
* @return
*/
public ResultInfo addOrUpdate(String typeName, Integer userId, String typeId) {
ResultInfo resultInfo = new ResultInfo<>();
// 1. 判断参数是否为空 (类型名称)
if (StrUtil.isBlank(typeName)) {
resultInfo.setCode(0);
resultInfo.setMsg("类型名称不能为空!");
return resultInfo;
}
// 2. 调用Dao层,查询当前登录用户下,类型名称是否唯一,返回0或1 (1=可用;0=不可用)
Integer code = typeDao.checkTypeName(typeName, userId, typeId);
// 如果不可用,code=0,msg=xxx,返回ResultInfo对象
if (code == 0) {
resultInfo.setCode(0);
resultInfo.setMsg("类型名称已存在,请重新输入!");
return resultInfo;
}
// 3. 判断类型ID是否为空
// 返回的结果
Integer key = null; // 主键或受影响的行数
if (StrUtil.isBlank(typeId)) {
// 如果为空,调用Dao层的添加方法,返回主键 (前台页面需要显示添加成功之后的类型ID)
key = typeDao.addType(typeName, userId);
} else {
// 如果不为空,调用Dao层的修改方法,返回受影响的行数
key = typeDao.updateType(typeName, typeId);
}
// 4. 判断 主键/受影响的行数 是否大于0
if (key > 0) {
resultInfo.setCode(1);
resultInfo.setResult(key);
} else {
resultInfo.setCode(0);
resultInfo.setMsg("更新失败!");
}
return resultInfo;
}
}
- UserService
package com.lezijie.note.service;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.lezijie.note.dao.UserDao;
import com.lezijie.note.po.User;
import com.lezijie.note.vo.ResultInfo;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
public class UserService {
private UserDao userDao = new UserDao();
/**
* 用户登录
1. 判断参数是否为空
如果为空
设置ResultInfo对象的状态码和提示信息
返回resultInfo对象
2. 如果不为空,通过用户名查询用户对象
3. 判断用户对象是否为空
如果为空
设置ResultInfo对象的状态码和提示信息
返回resultInfo对象
4. 如果用户对象不为空,将数据库中查询到的用户对象的密码与前台传递的密码作比较 (将密码加密后再比较)
如果密码不正确
设置ResultInfo对象的状态码和提示信息
返回resultInfo对象
5. 如果密码正确
设置ResultInfo对象的状态码和提示信息
6. 返回resultInfo对象
* @param userName
* @param userPwd
* @return
*/
public ResultInfo userLogin(String userName, String userPwd) {
ResultInfo resultInfo = new ResultInfo<>();
// 数据回显:当登录实现时,将登录信息返回给页面显示
User u = new User();
u.setUname(userName);
u.setUpwd(userPwd);
// 设置到resultInfo对象中
resultInfo.setResult(u);
// 1. 判断参数是否为空
if (StrUtil.isBlank(userName) || StrUtil.isBlank(userPwd)) {
// 如果为空 设置ResultInfo对象的状态码和提示信息
resultInfo.setCode(0);
resultInfo.setMsg("用户姓名或密码不能为空!");
// 返回resultInfo对象
return resultInfo;
}
// 2. 如果不为空,通过用户名查询用户对象
User user = userDao.queryUserByName(userName);
// 3. 判断用户对象是否为空
if (user == null) {
// 如果为空,设置ResultInfo对象的状态码和提示信息
resultInfo.setCode(0);
resultInfo.setMsg("该用户不存在!");
// 返回resultInfo对象
return resultInfo;
}
// 4. 如果用户对象不为空,将数据库中查询到的用户对象的密码与前台传递的密码作比较 (将密码加密后再比较)
// 将前台传递的密码按照MD5算法的方式加密
userPwd = DigestUtil.md5Hex(userPwd);
// 判断加密后的密码是否与数据库中的一致
if (!userPwd.equals(user.getUpwd())) {
// 如果密码不正确
resultInfo.setCode(0);
resultInfo.setMsg("用户密码不正确!");
return resultInfo;
}
resultInfo.setCode(1);
resultInfo.setResult(user);
return resultInfo;
}
/**
* 验证昵称的唯一性
* 1. 判断昵称是否为空
* 如果为空,返回"0"
* 2. 调用Dao层,通过用户ID和昵称查询用户对象
* 3. 判断用户对象存在
* 存在,返回"0"
* 不存在,返回"1"
* @param nick
* @param userId
* @return
*/
public Integer checkNick(String nick, Integer userId) {
// 1. 判断昵称是否为空
if (StrUtil.isBlank(nick)) {
return 0;
}
// 2. 调用Dao层,通过用户ID和昵称查询用户对象
User user = userDao.queryUserByNickAndUserId(nick, userId);
// 3. 判断用户对象存在
if (user != null) {
return 0;
}
return 1;
}
/**
* 修改用户信息
1. 获取参数(昵称、心情)
2. 参数的非空校验(判断必填参数非空)
如果昵称为空,将状态码和错误信息设置resultInfo对象中,返回resultInfo对象
3. 从session作用域中获取用户对象(获取用户对象中默认的头像)
4. 实现上上传文件
1. 获取Part对象 request.getPart("name"); name代表的是file文件域的那么属性值
2. 通过Part对象获取上传文件的文件名
3. 判断文件名是否为空
4. 获取文件存放的路径 WEB-INF/upload/目录中
5. 上传文件到指定目录
5. 更新用户头像 (将原本用户对象中的默认头像设置为上传的文件名)
6. 调用Dao层的更新方法,返回受影响的行数
7. 判断受影响的行数
如果大于0,则修改成功;否则修改失败
8. 返回resultInfo对象
* @param request
* @return
*/
public ResultInfo updateUser(HttpServletRequest request) {
ResultInfo resultInfo = new ResultInfo<>();
// 1. 获取参数(昵称、心情)
String nick = request.getParameter("nick");
String mood = request.getParameter("mood");
// 2. 参数的非空校验(判断必填参数非空)
if (StrUtil.isBlank(nick)) {
// 如果昵称为空,将状态码和错误信息设置resultInfo对象中,返回resultInfo对象
resultInfo.setCode(0);
resultInfo.setMsg("用户昵称不能卫空!");
return resultInfo;
}
// 3. 从session作用域中获取用户对象(获取用户对象中默认的头像)
User user = (User) request.getSession().getAttribute("user");
// 设置修改的昵称和头像
user.setNick(nick);
user.setMood(mood);
// 4. 实现上上传文件
try {
// 1. 获取Part对象 request.getPart("name"); name代表的是file文件域的name属性值
Part part = request.getPart("img");
// 2. 通过Part对象获取上传文件的文件名 (从头部信息中获取上传的文件名)
String header = part.getHeader("Content-Disposition");
// 获取具体的请求头对应的值
String str = header.substring(header.lastIndexOf("=") + 2);
// 获取上传的文件名
String fileName = str.substring(0, str.length() - 1);
// 3. 判断文件名是否为空
if (!StrUtil.isBlank(fileName)) {
// 如果用户上传了头像,则更新用户对象中的头像
user.setHead(fileName);
// 4. 获取文件存放的路径 WEB-INF/upload/目录中
String filePath = request.getServletContext().getRealPath("/WEb-INF/upload/");
// 5. 上传文件到指定目录
part.write(filePath + "/" + fileName);
}
} catch (Exception e) {
e.printStackTrace();
}
// 6. 调用Dao层的更新方法,返回受影响的行数
int row = userDao.updateUser(user);
// 7. 判断受影响的行数
if (row > 0) {
resultInfo.setCode(1);
// 更新session中用户对象
request.getSession().setAttribute("user", user);
} else {
resultInfo.setCode(0);
resultInfo.setMsg("更新失败!");
}
return resultInfo;
}
}
9.1.5 util层
- DBUtil
package com.lezijie.note.util;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* 乐字节:专注线上IT培训
* 需要视频资料,请添加:lezijie007
*/
public class DBUtil {
// 得到配置文件对象
private static Properties properties = new Properties();
static {
try {
// 加载配置文件(输入流)
InputStream in = DBUtil.class.getClassLoader().getResourceAsStream("db.properties");
// 通过load()方法将输入流的内容加载到配置文件对象中
properties.load(in);
// 通过配置文件对象的getProperty()方法获取驱动名,并加载驱动
Class.forName(properties.getProperty("jdbcName"));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接
* @return
*/
public static Connection getConnetion() {
Connection connection = null;
try {
// 得到数据库连接的相关信息
String dbUrl = properties.getProperty("dbUrl");
String dbName = properties.getProperty("dbName");
String dbPwd = properties.getProperty("dbPwd");
// 得到数据库连接
connection = DriverManager.getConnection(dbUrl, dbName, dbPwd);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return connection;
}
/**
* 关闭资源
* @param resultSet
* @param preparedStatement
* @param connection
*/
public static void close(ResultSet resultSet,
PreparedStatement preparedStatement,
Connection connection) {
try {
// 判断资源对象如果不为空,则关闭
if (resultSet != null) {
resultSet.close();
}
if (preparedStatement != null) {
preparedStatement.close();
}
if (connection != null) {
connection.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
- JsonUtil
package com.lezijie.note.util;
import com.alibaba.fastjson.JSON;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
/**
* 将对象转换成JOSN格式的字符串,响应给ajax的回调函数
*/
public class JsonUtil {
public static void toJson(HttpServletResponse response, Object result) {
try {
// 设置响应类型及编码格式 (json类型)
response.setContentType("application/json;charset=UTF-8");
// 得到字符输出流
PrintWriter out = response.getWriter();
// 通过fastjson的方法,将ResultInfo对象转换成JSON格式的字符串
String json = JSON.toJSONString(result);
// 通过输出流输出JSON格式的字符串
out.write(json);
// 关闭资源
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- Page
package com.lezijie.note.util;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* 分页工具类
*/
@Getter
@Setter
public class Page {
private Integer pageNum; // 当前页 (前台传递的参数;如果前台未传递,则默认第一页)
private Integer pageSize; // 每页显示的数量 (前台传递或后台设定)
private long totalCount; // 总记录数 (后台数据库中查询得到;count()函数)
private Integer totalPages; // 总页数 (总记录数/每页显示的数量;将参数转换为浮点型,执行除法 *** 作,向上取整)
private Integer prePage; // 上一页 (当前页-1;如果当前页-1小于1,则上一页为1)
private Integer nextPage; // 下一页 (当前页+1;如果当前页+1大于总页数,则下一页为总页数的值)
private Integer startNavPage; // 导航开始页 (当前页-5;如果当前页-5小于1,则导航开始页为1,此时导航结束页为导航开始数+9;如果导航开始数+9大于总页数,则导航结束页为总页数)
private Integer endNavPage; // 导航结束页 (当前页+4;如果当前页+4大于总页数,则导航结束页为总页数,此时导航开始页为导航结束页-9;如果导航结束页-9小于1,则导航开始页为1)
private List dataList; // 当前页的数据集合 (查询数据库中指定页的数据列表)
/**
* 带参构造
* 通过指定参数,得到其他分页参数的值
* @param pageNum
* @param pageSize
* @param totalCount
*/
public Page(Integer pageNum, Integer pageSize, long totalCount) {
this.pageNum = pageNum;
this.pageSize = pageSize;
this.totalCount = totalCount;
// 总页数 (总记录数/每页显示的数量;将参数转换为浮点型,执行除法 *** 作,向上取整)
this.totalPages = (int)Math.ceil(totalCount/(pageSize * 1.0));
// 上一页 (当前页-1;如果当前页-1小于1,则上一页为1)
this.prePage = pageNum - 1 < 1 ? 1 : pageNum - 1;
// 下一页 (当前页+1;如果当前页+1大于总页数,则下一页为总页数的值)
this.nextPage = pageNum + 1 > totalPages ? totalPages : pageNum + 1;
this.startNavPage = pageNum - 5; // 导航开始页 (当前页-5)
this.endNavPage = pageNum + 4; // 导航结束页 (当前页+4)
// 导航开始页 (当前页-5;如果当前页-5小于1,则导航开始页为1,此时导航结束页为导航开始数+9;如果导航开始数+9大于总页数,则导航结束页为总页数)
if (this.startNavPage < 1) {
// 如果当前页-5小于1,则导航开始页为1
this.startNavPage = 1;
// 此时导航结束页为导航开始数+9;如果导航开始数+9大于总页数,则导航结束页为总页数
this.endNavPage = this.startNavPage + 9 > totalPages ? totalPages : this.startNavPage + 9;
}
// 导航结束页 (当前页+4;如果当前页+4大于总页数,则导航结束页为总页数,此时导航开始页为导航结束页-9;如果导航结束页-9小于1,则导航开始页为1)
if (this.endNavPage > totalPages) {
// 如果当前页+4大于总页数,则导航结束页为总页数
this.endNavPage = totalPages;
// 此时导航开始页为导航结束页-9;如果导航结束页-9小于1,则导航开始页为1
this.startNavPage = this.endNavPage - 9 < 1 ? 1 : this.endNavPage - 9;
}
}
}
9.1.6 vo层
- NoteVo
package com.lezijie.note.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class NoteVo {
private String groupName; // 分组名称
private long noteCount; // 云记数量
private Integer typeId; // 类型ID
}
- ResultInfo
package com.lezijie.note.vo;
import lombok.Getter;
import lombok.Setter;
/**
* 封装返回结果的类
* 状态码
* 成功=1,失败=0
* 提示信息
* 返回的对象(字符串、JavaBean、集合、Map等)
*/
@Getter
@Setter
public class ResultInfo {
private Integer code; // 状态码 成功=1,失败=0
private String msg; // 提示信息
private T result; // 返回的对象(字符串、JavaBean、集合、Map等)
}
9.1.7 web层
- IndexServlet
package com.lezijie.note.web;
import com.lezijie.note.po.Note;
import com.lezijie.note.po.User;
import com.lezijie.note.service.NoteService;
import com.lezijie.note.util.Page;
import com.lezijie.note.vo.NoteVo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置首页导航高亮
request.setAttribute("menu_page", "index");
// 得到用户行为 (判断是什么条件查询:标题查询、日期查询、类型查询)
String actionName = request.getParameter("actionName");
// 将用户行为设置到request作用域中 (分页导航中需要获取)
request.setAttribute("action", actionName);
// 判断用户行为
if ("searchTitle".equals(actionName)) { // 标题查询
// 得到查询条件:标题
String title = request.getParameter("title");
// 将查询条件设置到request请求域中(查询条件的回显)
request.setAttribute("title", title);
// 标题搜索
noteList(request, response, title, null, null);
} else if ("searchDate".equals(actionName)) { // 日期查询
// 得到查询条件:日期
String date = request.getParameter("date");
// 将查询条件设置到request请求域中(查询条件的回显)
request.setAttribute("date", date);
// 日期搜索
noteList(request, response, null, date, null);
} else if ("searchType".equals(actionName)) { // 类型查询
// 得到查询条件:类型ID
String typeId = request.getParameter("typeId");
// 将查询条件设置到request请求域中(查询条件的回显)
request.setAttribute("typeId", typeId);
// 日期搜索
noteList(request, response, null, null, typeId);
} else {
// 分页查询云记列表
noteList(request, response, null, null, null);
}
// 设置首页动态包含的页面
request.setAttribute("changePage","note/list.jsp");
// 请求转发到index.jsp
request.getRequestDispatcher("index.jsp").forward(request, response);
}
/**
* 分页查询云记列表
1. 接收参数 (当前页、每页显示的数量)
2. 获取Session作用域中的user对象
3. 调用Service层查询方法,返回Page对象
4. 将page对象设置到request作用域中
* @param request
* @param response
* @param title 标题
*/
private void noteList(HttpServletRequest request, HttpServletResponse response,
String title, String date, String typeId) {
// 1. 接收参数 (当前页、每页显示的数量)
String pageNum = request.getParameter("pageNum");
String pageSize = request.getParameter("pageSize");
// 2. 获取Session作用域中的user对象
User user = (User) request.getSession().getAttribute("user");
// 3. 调用Service层查询方法,返回Page对象
Page page = new NoteService().findNoteListByPage(pageNum, pageSize, user.getUserId(), title, date, typeId);
// 4. 将page对象设置到request作用域中
request.setAttribute("page", page);
// 通过日期分组查询当前登录用户下的云记数量
List dateInfo = new NoteService().findNoteCountByDate(user.getUserId());
// 设置集合存放在request作用域中
request.getSession().setAttribute("dateInfo", dateInfo);
// 通过类型分组查询当前登录用户下的云记数量
List typeInfo = new NoteService().findNoteCountByType(user.getUserId());
// 设置集合存放在request作用域中
request.getSession().setAttribute("typeInfo", typeInfo);
}
}
- NoteServlet
package com.lezijie.note.web;
import cn.hutool.core.util.StrUtil;
import com.lezijie.note.po.Note;
import com.lezijie.note.po.NoteType;
import com.lezijie.note.po.User;
import com.lezijie.note.service.NoteService;
import com.lezijie.note.service.NoteTypeService;
import com.lezijie.note.vo.ResultInfo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/note")
public class NoteServlet extends HttpServlet {
private NoteService noteService = new NoteService();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置首页导航栏的高亮值
request.setAttribute("menu_page", "note");
// 得到用户行为
String actionName = request.getParameter("actionName");
// 判断用户行为
if ("view".equals(actionName)) {
// 进入发布云记页面
noteView(request, response);
} else if ("addOrUpdate".equals(actionName)) {
// 添加或修改云记
addOrUpdate(request, response);
} else if ("detail".equals(actionName)) {
// 查询云记详情
noteDetail(request, response);
} else if ("delete".equals(actionName)) {
// 删除云记
noteDelete(request, response);
}
}
/**
* 删除云记
1. 接收参数 (noteId)
2. 调用Service层删除方法,返回状态码 (1=成功,0=失败)
3. 通过流将结果响应给ajax的回调函数 (输出字符串)
* @param request
* @param response
*/
private void noteDelete(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 1. 接收参数 (noteId)
String noteId = request.getParameter("noteId");
// 2. 调用Service层删除方法,返回状态码 (1=成功,0=失败)
Integer code = noteService.deleteNote(noteId);
// 3. 通过流将结果响应给ajax的回调函数 (输出字符串)
response.getWriter().write(code + "");
response.getWriter().close();
}
/**
* 查询云记详情
1. 接收参数 (noteId)
2. 调用Service层的查询方法,返回Note对象
3. 将Note对象设置到request请求域中
4. 设置首页动态包含的页面值
5. 请求转发跳转到index.jsp
* @param request
* @param response
*/
private void noteDetail(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 接收参数 (noteId)
String noteId = request.getParameter("noteId");
// 2. 调用Service层的查询方法,返回Note对象
Note note = noteService.findNoteById(noteId);
// 3. 将Note对象设置到request请求域中
request.setAttribute("note", note);
// 4. 设置首页动态包含的页面值
request.setAttribute("changePage","note/detail.jsp");
// 5. 请求转发跳转到index.jsp
request.getRequestDispatcher("index.jsp").forward(request, response);
}
/**
* 添加或修改 *** 作
1. 接收参数 (类型ID、标题、内容)
2. 调用Service层方法,返回resultInfo对象
3. 判断resultInfo的code值
如果code=1,表示成功
重定向跳转到首页 index
如果code=0,表示失败
将resultInfo对象设置到request作用域
请求转发跳转到note?actionName=view
* @param request
* @param response
*/
private void addOrUpdate(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// 1. 接收参数 (类型ID、标题、内容)
String typeId = request.getParameter("typeId");
String title = request.getParameter("title");
String content = request.getParameter("content");
// 获取经纬度
String lon = request.getParameter("lon");
String lat = request.getParameter("lat");
// 如果是修改 *** 作,需要接收noteId
String noteId = request.getParameter("noteId");
// 2. 调用Service层方法,返回resultInfo对
ResultInfo resultInfo = noteService.addOrUpdate(typeId, title, content, noteId, lon, lat);
// 3. 判断resultInfo的code值
if (resultInfo.getCode() == 1) {
// 重定向跳转到首页 index
response.sendRedirect("index");
} else {
// 将resultInfo对象设置到request作用域
request.setAttribute("resultInfo", resultInfo);
// 请求转发跳转到note?actionName=view
String url = "note?actionName=view";
// 如果是修改 *** 作,需要传递noteId
if (!StrUtil.isBlank(noteId)) {
url += "¬eId="+noteId;
}
request.getRequestDispatcher(url).forward(request, response);
}
}
/**
* 进入发布云记页面
1. 从Session对象中获取用户对象
2. 通过用户ID查询对应的类型列表
3. 将类型列表设置到request请求域中
4. 设置首页动态包含的页面值
5. 请求转发跳转到index.jsp
* @param request
* @param response
*/
private void noteView(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/* 修改 *** 作 */
// 得到要修改的云记ID
String noteId = request.getParameter("noteId");
// 通过noteId查询云记对象
Note note = noteService.findNoteById(noteId);
// 将note对象设置到请求域中
request.setAttribute("noteInfo", note);
/* 修改 *** 作 */
// 1. 从Session对象中获取用户对象
User user = (User) request.getSession().getAttribute("user");
// 2. 通过用户ID查询对应的类型列表
List typeList = new NoteTypeService().findTypeList(user.getUserId());
// 3. 将类型列表设置到request请求域中
request.setAttribute("typeList", typeList);
// 4. 设置首页动态包含的页面值
request.setAttribute("changePage","note/view.jsp");
// 5. 请求转发跳转到index.jsp
request.getRequestDispatcher("index.jsp").forward(request, response);
}
}
- NoteTypeServlet
package com.lezijie.note.web;
import com.lezijie.note.po.NoteType;
import com.lezijie.note.po.User;
import com.lezijie.note.service.NoteTypeService;
import com.lezijie.note.util.JsonUtil;
import com.lezijie.note.vo.ResultInfo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/type")
public class NoteTypeServlet extends HttpServlet {
private NoteTypeService typeService = new NoteTypeService();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置首页导航的高亮值
request.setAttribute("menu_page", "type");
// 得到用户行为
String actionName = request.getParameter("actionName");
// 判断用户行为
if ("list".equals(actionName)) {
// 查询类型列表
typeList(request, response);
} else if ("delete".equals(actionName)) {
// 删除类型
deleteType(request, response);
} else if ("addOrUpdate".equals(actionName)) {
// 添加或修改类型
addOrUpdate(request, response);
}
}
/**
* 添加或修改类型
1. 接收参数 (类型名称、类型ID)
2. 获取Session作用域中的user对象,得到用户ID
3. 调用Service层的更新方法,返回ResultInfo对象
4. 将ResultInfo转换成JSON格式的字符串,响应给ajax的回调函数
* @param request
* @param response
*/
private void addOrUpdate(HttpServletRequest request, HttpServletResponse response) {
// 1. 接收参数 (类型名称、类型ID)
String typeName = request.getParameter("typeName");
String typeId = request.getParameter("typeId");
// 2. 获取Session作用域中的user对象,得到用户ID
User user = (User) request.getSession().getAttribute("user");
// 3. 调用Service层的更新方法,返回ResultInfo对象
ResultInfo resultInfo = typeService.addOrUpdate(typeName, user.getUserId(), typeId);
// 4. 将ResultInfo转换成JSON格式的字符串,响应给ajax的回调函数
JsonUtil.toJson(response, resultInfo);
}
/**
* 删除类型
1. 接收参数(类型ID)
2. 调用Service的更新 *** 作,返回ResultInfo对象
3. 将ResultInfo对象转换成JSON格式的字符串,响应给ajax的回调函数
* @param request
* @param response
*/
private void deleteType(HttpServletRequest request, HttpServletResponse response) {
// 1. 接收参数(类型ID)
String typeId = request.getParameter("typeId");
// 2. 调用Service的更新 *** 作,返回ResultInfo对象
ResultInfo resultInfo = typeService.deleteType(typeId);
// 3. 将ResultInfo对象转换成JSON格式的字符串,响应给ajax的回调函数
JsonUtil.toJson(response, resultInfo);
}
/**
* 查询类型列表
1. 获取Session作用域设置的user对象
2. 调用Service层的查询方法,查询当前登录用户的类型集合,返回集合
3. 将类型列表设置到request请求域中
4. 设置首页动态包含的页面值
5. 请求转发跳转到index.jsp页面
* @param request
* @param response
*/
private void typeList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 获取Session作用域设置的user对象
User user = (User) request.getSession().getAttribute("user");
// 2. 调用Service层的查询方法,查询当前登录用户的类型集合,返回集合
List typeList = typeService.findTypeList(user.getUserId());
// 3. 将类型列表设置到request请求域中
request.setAttribute("typeList", typeList);
// 4. 设置首页动态包含的页面值
request.setAttribute("changePage","type/list.jsp");
// 5. 请求转发跳转到index.jsp页面
request.getRequestDispatcher("index.jsp").forward(request, response);
}
}
- ReportServlet
package com.lezijie.note.web;
import com.lezijie.note.po.Note;
import com.lezijie.note.po.User;
import com.lezijie.note.service.NoteService;
import com.lezijie.note.util.JsonUtil;
import com.lezijie.note.vo.ResultInfo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@WebServlet("/report")
public class ReportServlet extends HttpServlet {
private NoteService noteService = new NoteService();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置首页导航栏的高亮值
request.setAttribute("menu_page", "report");
// 得到用户行为
String actionName = request.getParameter("actionName");
// 判断用户行为
if ("info".equals(actionName)) {
// 进入报表页面
reportInfo(request, response);
} else if ("month".equals(actionName)) {
// 通过月份查询对应的云记数量
queryNoteCountByMonth(request, response);
} else if ("location".equals(actionName)) {
// 查询用户发布云记时的坐标
queryNoteLonAndLat(request, response);
}
}
/**
* 查询用户发布云记时的坐标
* @param request
* @param response
*/
private void queryNoteLonAndLat(HttpServletRequest request, HttpServletResponse response) {
// 从Session作用域中获取用户对象
User user = (User) request.getSession().getAttribute("user");
// 调用Service层的查询方法,返回ResultInfo对象
ResultInfo> resultInfo = noteService.queryNoteLonAndLat(user.getUserId());
// 将ResultInfo对象转换成JSON格式的字符串,响应给AJAX的回调函数
JsonUtil.toJson(response, resultInfo);
}
/**
* 通过月份查询对应的云记数量
* @param request
* @param response
*/
private void queryNoteCountByMonth(HttpServletRequest request, HttpServletResponse response) {
// 从Session作用域中获取用户对象
User user = (User) request.getSession().getAttribute("user");
// 调用Service层的查询方法,返回ResultInfo对象
ResultInfo> resultInfo = noteService.queryNoteCountByMonth(user.getUserId());
// 将ResultInfo对象转换成JSON格式的字符串,响应给ajax的回调函数
JsonUtil.toJson(response, resultInfo);
}
/**
* 进入报表页面
* @param request
* @param response
*/
private void reportInfo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置首页动态包含的页面值
request.setAttribute("changePage","report/info.jsp");
// 请求转发跳转到index.jsp
request.getRequestDispatcher("index.jsp").forward(request, response);
}
}
- UserServlet
package com.lezijie.note.web;
import com.lezijie.note.po.User;
import com.lezijie.note.service.UserService;
import com.lezijie.note.vo.ResultInfo;
import org.apache.commons.io.FileUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
@WebServlet("/user")
@MultipartConfig
public class UserServlet extends HttpServlet {
private UserService userService = new UserService();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置首页导航高亮
request.setAttribute("menu_page", "user");
// 接收用户行为
String actionName = request.getParameter("actionName");
// 判断用户行为,调用对应的方法
if ("login".equals(actionName)) {
// 用户登录
userLogin(request, response);
} else if ("logout".equals(actionName)) {
// 用户退出
userLogOut(request, response);
} else if ("userCenter".equals(actionName)) {
// 进入个人中心
userCenter(request, response);
} else if ("userHead".equals(actionName)) {
// 加载头像
userHead(request, response);
} else if ("checkNick".equals(actionName)) {
// 验证昵称的唯一性
checkNick(request, response);
} else if ("updateUser".equals(actionName)) {
// 修改用户信息
updateUser(request, response);
}
}
/**
* 修改用户信息
注:文件上传必须在Servlet类上提那家注解!!! @MultipartConfig
1. 调用Service层的方法,传递request对象作为参数,返回resultInfo对象
2. 将resultInfo对象存到request作用域中
3. 请求转发跳转到个人中心页面 (user?actionName=userCenter)
* @param request
* @param response
*/
private void updateUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 调用Service层的方法,传递request对象作为参数,返回resultInfo对象
ResultInfo resultInfo = userService.updateUser(request);
// 2. 将resultInfo对象存到request作用域中
request.setAttribute("resultInfo", resultInfo);
// 3. 请求转发跳转到个人中心页面 (user?actionName=userCenter)
request.getRequestDispatcher("user?actionName=userCenter").forward(request, response);
}
/**
* 验证昵称的唯一性
* 1. 获取参数(昵称)
* 2. 从session作用域获取用户对象,得到用户ID
* 3. 调用Service层的方法,得到返回的结果
* 4. 通过字符输出流将结果响应给前台的ajax的回调函数
* 5. 关闭资源
* @param request
* @param response
*/
private void checkNick(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 1. 获取参数(昵称)
String nick = request.getParameter("nick");
// 2. 从session作用域获取用户对象,得到用户ID
User user = (User) request.getSession().getAttribute("user");
// 3. 调用Service层的方法,得到返回的结果
Integer code = userService.checkNick(nick, user.getUserId());
// 4. 通过字符输出流将结果响应给前台的ajax的回调函数
response.getWriter().write(code + "");
// 5. 关闭资源
response.getWriter().close();
}
/**
* 加载头像
* 1. 获取参数 (图片名称)
* 2. 得到图片的存放路径 (request.getServletContext().getealPathR("/"))
* 3. 通过图片的完整路径,得到file对象
* 4. 通过截取,得到图片的后缀
* 5. 通过不同的图片后缀,设置不同的响应的类型
* 6. 利用FileUtils的copyFile()方法,将图片拷贝给浏览器
* @param request
* @param response
*/
private void userHead(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 1. 获取参数 (图片名称)
String head = request.getParameter("imageName");
// 2. 得到图片的存放路径 (得到项目的真实路径:request.getServletContext().getealPathR("/"))
String realPath = request.getServletContext().getRealPath("/WEB-INF/upload/");
// 3. 通过图片的完整路径,得到file对象
File file = new File(realPath + "/" + head);
// 4. 通过截取,得到图片的后缀
String pic = head.substring(head.lastIndexOf(".")+1);
// 5. 通过不同的图片后缀,设置不同的响应的类型
if ("PNG".equalsIgnoreCase(pic)) {
response.setContentType("image/png");
} else if ("JPG".equalsIgnoreCase(pic) || "JPEG".equalsIgnoreCase(pic)) {
response.setContentType("image/jpeg");
} else if ("GIF".equalsIgnoreCase(pic)) {
response.setContentType("image/gif");
}
// 6. 利用FileUtils的copyFile()方法,将图片拷贝给浏览器
FileUtils.copyFile(file, response.getOutputStream());
}
/**
* 进入个人中心
* 1. 设置首页动态包含的页面值
* 2. 请求转发跳转到index.jsp
* @param request
* @param response
*/
private void userCenter(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 设置首页动态包含的页面值
request.setAttribute("changePage", "user/info.jsp");
// 2. 请求转发跳转到index
request.getRequestDispatcher("index.jsp").forward(request, response);
}
/**
* 用户退出
* 1. 销毁Session对象
* 2. 删除Cookie对象
* 3. 重定向跳转到登录页面
* @param request
* @param response
*/
private void userLogOut(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 1. 销毁Session对象
request.getSession().invalidate();
// 2. 删除Cookie对象
Cookie cookie = new Cookie("user", null);
cookie.setMaxAge(0); // 设置0,表示删除cookie
response.addCookie(cookie);
// 3. 重定向跳转到登录页面
response.sendRedirect("login.jsp");
}
/**
* 用户登录
1. 获取参数 (姓名、密码)
2. 调用Service层的方法,返回ResultInfo对象
3. 判断是否登录成功
如果失败
将resultInfo对象设置到request作用域中
请求转发跳转到登录页面
如果成功
将用户信息设置到session作用域中
判断用户是否选择记住密码(rem的值是1)
如果是,将用户姓名与密码存到cookie中,设置失效时间,并响应给客户端
如果否,清空原有的cookie对象
重定向跳转到index页面
* @param request
* @param response
*/
private void userLogin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 获取参数 (姓名、密码)
String userName = request.getParameter("userName");
String userPwd = request.getParameter("userPwd");
// 2. 调用Service层的方法,返回ResultInfo对象
ResultInfo resultInfo = userService.userLogin(userName, userPwd);
// 3. 判断是否登录成功
if (resultInfo.getCode() == 1) { // 如果成功
// 将用户信息设置到session作用域中
request.getSession().setAttribute("user", resultInfo.getResult());
// 判断用户是否选择记住密码(rem的值是1)
String rem = request.getParameter("rem");
// 如果是,将用户姓名与密码存到cookie中,设置失效时间,并响应给客户端
if ("1".equals(rem)) {
// 得到Cookie对象
Cookie cookie = new Cookie("user",userName +"-"+userPwd);
// 设置失效时间
cookie.setMaxAge(3*24*60*60);
// 响应给客户端
response.addCookie(cookie);
} else {
// 如果否,清空原有的cookie对象
Cookie cookie = new Cookie("user", null);
// 删除cookie,设置maxage为0
cookie.setMaxAge(0);
// 响应给客户端
response.addCookie(cookie);
}
// 重定向跳转到index页面
response.sendRedirect("index");
} else { // 失败
// 将resultInfo对象设置到request作用域中
request.setAttribute("resultInfo", resultInfo);
// 请求转发跳转到登录页面
request.getRequestDispatcher("login.jsp").forward(request, response);
}
}
}
9.2 webapp目录
10、报错记录 10.1 问题描述:「 在代码不出错的情况下,(判断是否为空)点击“登录”按钮 并未出现提示信息 」 10.2 问题描述:「 tomcat端口冲突解决 Address already in use: JVM_Bind :8080 」……
「 最可能的解决方案: 」
① cmd 命令输入 netstat –ano | findstr 8080
② 查看到 8080端口对应的进程号xxxx
③ 在任务管理器中寻找改PID
④ 右键结束该任务 或者 仍然在命令行下输入 taskkill –pid xxxx
如果上面方法没有解决 选择重启电脑
转到index
request.getRequestDispatcher(“index.jsp”).forward(request, response);
}
/**
* 用户退出
* 1. 销毁Session对象
* 2. 删除Cookie对象
* 3. 重定向跳转到登录页面
* @param request
* @param response
*/
private void userLogOut(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 1. 销毁Session对象
request.getSession().invalidate();
// 2. 删除Cookie对象
Cookie cookie = new Cookie("user", null);
cookie.setMaxAge(0); // 设置0,表示删除cookie
response.addCookie(cookie);
// 3. 重定向跳转到登录页面
response.sendRedirect("login.jsp");
}
/**
* 用户登录
1. 获取参数 (姓名、密码)
2. 调用Service层的方法,返回ResultInfo对象
3. 判断是否登录成功
如果失败
将resultInfo对象设置到request作用域中
请求转发跳转到登录页面
如果成功
将用户信息设置到session作用域中
判断用户是否选择记住密码(rem的值是1)
如果是,将用户姓名与密码存到cookie中,设置失效时间,并响应给客户端
如果否,清空原有的cookie对象
重定向跳转到index页面
* @param request
* @param response
*/
private void userLogin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 获取参数 (姓名、密码)
String userName = request.getParameter("userName");
String userPwd = request.getParameter("userPwd");
// 2. 调用Service层的方法,返回ResultInfo对象
ResultInfo resultInfo = userService.userLogin(userName, userPwd);
// 3. 判断是否登录成功
if (resultInfo.getCode() == 1) { // 如果成功
// 将用户信息设置到session作用域中
request.getSession().setAttribute("user", resultInfo.getResult());
// 判断用户是否选择记住密码(rem的值是1)
String rem = request.getParameter("rem");
// 如果是,将用户姓名与密码存到cookie中,设置失效时间,并响应给客户端
if ("1".equals(rem)) {
// 得到Cookie对象
Cookie cookie = new Cookie("user",userName +"-"+userPwd);
// 设置失效时间
cookie.setMaxAge(3*24*60*60);
// 响应给客户端
response.addCookie(cookie);
} else {
// 如果否,清空原有的cookie对象
Cookie cookie = new Cookie("user", null);
// 删除cookie,设置maxage为0
cookie.setMaxAge(0);
// 响应给客户端
response.addCookie(cookie);
}
// 重定向跳转到index页面
response.sendRedirect("index");
} else { // 失败
// 将resultInfo对象设置到request作用域中
request.setAttribute("resultInfo", resultInfo);
// 请求转发跳转到登录页面
request.getRequestDispatcher("login.jsp").forward(request, response);
}
}
}
### 9.2 webapp目录
> ……
## 10、报错记录
### 10.1 问题描述:「 在代码不出错的情况下,(判断是否为空)点击“登录”按钮 并未出现提示信息 」
### 10.2 问题描述:「 tomcat端口冲突解决 Address already in use: JVM_Bind :8080 」
「 **最可能的解决方案:** 」
① cmd 命令输入 netstat –ano | findstr 8080
② 查看到 8080端口对应的进程号xxxx
③ 在任务管理器中寻找改PID
④ 右键结束该任务 或者 仍然在命令行下输入 taskkill –pid xxxx
> **如果上面方法没有解决 选择重启电脑**
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)