博客项目准备 + 用户模块

简单实现 博客项目

具体功能

1、增删改查

2、免登录: cookie 与 session

3、非法登录: 过滤器

4、分页:

5、ajax: 操作表格

6、文件上传

7、富文本编辑器

 

技术运用

1、jsp&servlet

2、jquery 及插件

3、UEditor

4、log4j

5、junit

 

开发环境

 

Eclipse + mysql + window + jdk1.8 + tomcat8

注意: tomcat8 字符集为 utf-8 (get | tomcat7 以下) POST 所有的服务都需要处理

 

 

流程

调研 需求分析 规格分析 前端 后端 测试 实施 需求变更

 

环境搭建 及 准备

1、配置 JDK

Window —> preferences (参数选择) —> java —> installed JRES

—> Add —>Standard VM (标准 Java 虚拟器设置)—> 找到对应的 JDK

2、配置 Tomcat

Window —> preferences —> Server —> Runtime Environments

 

(运行环境) —> Add —> Apache —> 选择 Apache Tomcat v8.0

—> 找到 tomcat 路径以及设置对应的 jdk

 

软件准备

 

1、新建项目

2、更改 JSP 字符集

3、更改 JSP 模板

4、新建登录页面

1)、拷贝登录的静态资源

建立文件夹放入 css js 图片 以及 UE、SweetAlert、bs3。

拷贝 login.html 到 login.jsp 中。

2)、修改静态文件引入路径

5、新建主页页面

1)、拷贝 note.css 到 statics/css 中

2)、新建 bootstrap3 拷贝 所有的 bs 的资源

3)、修改 html 中引入路径

4)、提取模板

可变的内容 放入到 其他的 jsp ,使用 jsp:include 导入

6、其他页面

1)、用户页面

User/info.jsp

2)、类型页面

Notetype/list.jsp

 

.............................

.............................待补充

.............................

.............................

具体步骤

准备工作

===========================分层思想===========================

分层思想

Servlet/Web层:

1、接收请求

2、调用Service层的方法,得到返回结果

3、响应结果给客户端

 

Service层:

1、业务逻辑判断

3、调用Dao层的方法,得到返回结果

4、将处理好的请求返回给web层

 

Dao层:

JDBC操作

数据库的增删改查

 

 

===========================单元测试===========================

项目右键 new ==> JUnit Test Case

单元测试

  1、不能有父类

  2、不能是静态方法

  3、不能有参数

  4、返回值是void

  方法上需要设置注解@Test

 

 

 

===========================日志的使用==========================

日志

1、将日志的所需要的jar包拷贝到项目的lib目录下

 log4j-1.2.17.jar、

api-1.7.12.jar、  

slf4j-log4j12-1.7.12.jar

2、准备配置文件

log4j.properties

a、设置日志输出目的地

b、设置日志的级别

3、使用日志

a、使用日志工厂类

private static Logger logger = LoggerFactory.getLogger(类名.class);

b、使用

logger.info("日志内容....");

logger.info("日志内容{}","这里的内容是填充{}占位符的");

 

日志代码示例:

log4j.properties

使用方法:

private static Logger logger = LoggerFactory.getLogger(类名.class);

在要使用的类中填入

filter过滤器

乱码过滤器

com.gy.filter.EncodeFilter

自动登录过滤器

com.gy.filter.LoginAccessFilter.java

 

 

Utils工具类

DBUtil

数据库工具

1、打开数据库连接

2、关闭资源

 

json工具类JsonUtil

字符串 ==> json字符串

将对象转换成JSON字符串,并响应给ajax的回调函数

 

密码加密工具类MD5Util

 

密码加密

 

字符串工具类StringUtil

 

String判断

用户模块

===========================功能思路===========================

用户行为 actionName

用户登录 actionName=login

用户退出 actionName=logout

进入个人中心 actionName=userCenter

加载头像 actionName=userHead

验证昵称的唯一性 actionName=checkNick

修改用户信息(上传文件) actionName=updateInfo

 

 

一、用户登录

前台:

表单实现登录

1、姓名文本框、密码框、复选框(记住密码)、登录按钮、隐藏域(设置actionName)

2、表单元素设置name属性值

3、表单验证

1、得到文本框和密码框的值

2、参数的非空判断

如果为空,不提交表单,提示信息

3、如果参数不为空,提交表单

 

后台:

整体思路:

1、接收参数

2、判断参数是否为空

如果为空,将错误原因设置到reqeust作用域中,请求转发跳转到登录页面,并return

3、通过用户名查询用户对象是否存在

如果不存在,将错误原因设置到reqeust作用域中,请求转发跳转到登录页面,并return

4、如果存在,将数据库中的密码与前台传递的密码作比较

如果不正确,将错误原因设置到reqeust作用域中,请求转发跳转到登录页面,并return

5、如果正确,登录成功

1、将用户对象存到session作用域中

2、判断用户是否选择记住密码

如记住,则存cookie对象

3、重定向跳转到indexServlet

 

Servelt层(登录):(接收请求、响应结果)

1、接收参数

2、调用Service层的方法,得到resultInfo对象

3、判断resultInfo的code的值,判断是否登录成功

如果失败,将resultInfo对象存到request作用域中,请求转发跳转到登录页面

如果成功

1、将用户对象存到session作用域中

2、判断用户是否选择记住密码

如记住,,则存cookie对象

3、重定向跳转到indexServlet

 

Service层(登录):(业务逻辑)

1、判断参数是否为空

如果为空,设置resultInfo对象的code和msg的值,返回resultInfo给servlet层

2、调用Dao层的查询方法,通过用户名查询用户对象,返回用户对象

如果用户对象为空,设置resultInfo对象的code和msg的值,返回resultInfo给servlet层

3、如果存在,将数据库中的密码与前台传递的密码作比较

如果不正确,设置resultInfo对象的code和msg的值,

如果正确,设置resultInfo的code=1,

4、返回resultInfo给servlet层

 

Dao层(登录)

1、定义sql语句

"select * from tb_user where uname = ? "

2、参数集合

3、调用BaseDao () ==> 单个user对象

 

原生方法:(1、通过用户名查询用户对象是否存在

1、得到数据库连接

2、定义sql语句

3、预编译

4、设置参数,下标从1开始

5、执行查询,返回结果集

6、判断并分析结果集,得到用户对象

7、关闭资源

8、返回用户对象)

 

 

 

二、非法访问拦截、自动登录

LoginAccessFilter拦截

非法访问拦截

拦截什么:拦截所有资源路径

拦截到哪里:login.jsp

什么资源路径该放行:

1、指定页面,放行 (无需登录即可访问的页面需要放行,如登录、注册等页面)

2、静态资源,放行 (js、css、images等静态资源需要放行,项目中statics目录下的资源都放行)

3、指定行为,放行 (无需登录即可执行的操作需要放行,如登录操作、注册操作等)

4、登录状态,放行 (判断session中的user对象是否为空;不为空则为登录状态)

 

自动登录

前提:

1、非登录状态

2、有cookie对象

思路:

写在判断session中的user对象是否存在的条件之后 (非登录状态)

1、获取cookie数组

2、判断cookie数组是否为空

3、如果不为空,遍历cookie数组

4、得到指定名称的cookie对象中的name和value

5、分别得到value中的用户名和密码

6、请求转发跳转到登录操作

 

三、进入个人中心

顺序流程会进入 ==> IndexServlet

前台:

设置"个人中心"的超链接的访问地址为

userServlet?actionName=userCenter

(为了在主页点击 个人中心而进行刷新)

 

 

后台:

Servlet层(个人中心)

(对应在主页面点击个人中心)

1、设置首页动态包含的页面值

2、请求转发跳转到index.jsp

 

IndexServlet 主页

(对应从登录页面登录成功进入个人中心)

1、设置首页动态包含的页面值

2、请求转发跳转到index.jsp

 

 

四、加载头像

前台:

设置img标签的src属性: userServlet?actionName=userHead&imageName=${user.head}(图片名从session域对象中获取)  

 

后台:

头像中的链接是启动项(userServlet?actionName=userHead......)

servlet层(加载头像)

1、得到参数(图片名)

2、得到图片的存放路径getServletContext().getRealPath()

(提前建好文件夹)

3、通过路径,得到file对象(参数拼接)

4、判断file对象是否存在,并且是一个标准文件

5、得到图片的后缀

6、根据不同的后缀设置对应的响应类型

7、将文件对象通过工具类FileUtils.copyFile()响应给客户端

注:FileUtils.copyFile()需要拷贝jar包 :commons-io.jar

 

 

 

五、用户退出

前台:

超链接传到后台"userServlet?actionName=logout"

 

后台:

servlet层(用户退出)

1、销毁session(.invalidate()方法)

  2、删除cookie(cookie时间设为0)

  3、跳转到登录页面 (重定向)

 

 

 

六、验证昵称的唯一性

前台:

这里没做mood(心情)的处理只是获取而已

JS获取域对象中的值(需要加引号)获取旧昵称的值时使用

'${key}' 以防键误解(可能取值时报错) ==> 步骤3

昵称文本框绑定失焦事件.blur

1、得到昵称文本框的值

2、非空判断

如果为空,提示 禁用按钮 且return

3、判断值是否做了改变

如果没做改变,直接return

4、如果值发生改变

发送ajax请求,判断昵称是否可用

响应1或0,1=可用;0=不可用

如果可用,清空提示信息,按钮可用

如果不可用,提示用户,且禁用按钮

昵称文本框绑定聚焦事件

清空提示信息,按钮可用

 

后台:

Servlet层:(昵称唯一)

1、接收参数 昵称

2、从session域对象中得到用户对象,从而得到用户ID

3、调用Service层的防范,返回结果 (0或1)

4、通过输出流响应结果(需要将数值转成字符串)

 

Service层:(昵称唯一)

1、判断参数是否为空

如果为空,返回0

2、调用Dao层,通过昵称和用户ID查询数据库中除了当前记录之后是否有其他记录使用该昵称,返回user对象

3、判断user对象是否为空

如果为空,返回1

如果不为空,返回0

 

Dao层:(昵称唯一)

通过昵称和用户ID查询数据库中除了当前记录之后是否有其他记录使用该昵称,返回user对象 (单个对象)

"select * from tb_user where nick = ? and userId != ?"

 

七、修改用户信息

前台:

文件上传表单

提交方式 method="POST"

enctype="multipart/form-data"

表单元素设置name属性值

 

后台:

注:需要在Servlet上加注解   @MultipartConfig

Servlet层:(修改用户信息)

1、调用Service层的方法,返回resultInfo对象

2、将resultInfo对象存到request作用域中

3、请求转发跳转到个人中心   userServlet?actionName=userCneter

 

Service层:(修改用户信息)

1、接收参数 (昵称、心情)

2、参数非空判断 (昵称)

3、从session作用域中得到user对象,得到用户ID

4、判断昵称的唯一性

4、===实现文件上传====

1、得到Part对象  request.getPart("name")  "name"代表的是前台的file文件域的name属性值

2、得到上传的文件名

3、判断文件名是否不为空

如果为空,表示未上传文件

如果不为空,则得到文件要存放的地址

4、上传文件到指定路径

5、如果上传了文件,则修改用户头像,否则使用原来的头像

6、调用Dao层的修改方法,返回受影响的行数

7、判断受影响的行数

如果大于0,成功,更新session作用域中色user对象

如果不大于0,失败

 

 

Dao层:(修改用户信息)

通过用户ID修改用户对象

 

代码段

com.gy.web(接收响应层 用户)

com.gy.web.IndexServlet.java

//登录成功会跳转到这个页面 进行处理

 

package com.gy.web;

 

import java.io.IOException;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

@WebServlet("/indexServlet")

public class IndexServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

 

 

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//System.out.println("进入首页....");

 

// 设置首页导航栏高亮值

request.setAttribute("menu_page", "index");

 

// 1. 设置首页动态包含的页面值,存到request作用域中

//为了 做成 动态包含

request.setAttribute("changePage", "note/list.jsp");

 

// 2. 请求转发跳转到首页

request.getRequestDispatcher("index.jsp").forward(request, response);

 

}

 

}

 

com.gy.web.UserServlet.java

 

package com.gy.web;

 

import java.io.File;

import java.io.IOException;

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 org.apache.commons.io.FileUtils;

 

import com.gy.po.User;

import com.gy.po.vo.ResultInfo;

import com.gy.service.UserService;

/**

 * 用户模块

 * 用户行为 actionName

用户登录 actionName=login

用户退出 actionName=logout

进入个人中心 actionName=userCenter

加载头像 actionName=userHead

验证昵称的唯一性 actionName=checkNick

修改用户信息(上传文件) actionName=updateInfo

 */

 

@MultipartConfig // 如果前台是文件上传表单,则必须加这个注解

@WebServlet("/userServlet")

public class UserServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

 

private UserService userService = new UserService();

 

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

 

System.out.println("用户模块...");

 

// 设置首页导航栏高亮值

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 ("updateInfo".equals(actionName)) {

// 修改用户信息

updateInfo(request,response);

} else {

// 当actionName为空时,跳转到登录页面

response.sendRedirect("login.jsp");

}

}

 

/**

 * 修改用户信息

1、调用Service层的方法,返回resultInfo对象

2、将resultInfo对象存到request作用域中

3、请求转发跳转到个人中心   userServlet?actionName=userCneter

 * @param request

 * @param response

 * @throws IOException

 * @throws ServletException

 */

//修改用户信息servlet

private void updateInfo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// 1、调用Service层的方法,返回resultInfo对象

ResultInfo<User> resultInfo = userService.updateInfo(request);

// 2、将resultInfo对象存到request作用域中

request.setAttribute("resultInfo", resultInfo);

// 3、请求转发跳转到个人中心   userServlet?actionName=userCneter

request.getRequestDispatcher("userServlet?actionName=userCenter").forward(request, response);

}

 

 

/**

 * 验证昵称的唯一性

1、接收参数

2、从session域对象中得到用户对象,从而得到用户ID

3、调用Service层的防范,返回结果 (0或1)

4、通过输出流响应结果(需要将数值转成字符串)

 * @param request

 * @param response

 * @throws IOException

 */

//昵称唯一servlet

private void checkNick(HttpServletRequest request, HttpServletResponse response) throws IOException {

// 1、接收参数

String nickName = request.getParameter("nickName");

 

// 2、从session域对象中得到用户对象,从而得到用户ID

User user = (User) request.getSession().getAttribute("user");

Integer userId = user.getUserId();

 

// 3、调用Service层的防范,返回结果 (0或1)

int code = userService.checkNick(nickName, userId);

 

// 4、通过输出流响应结果(需要将数值转成字符串)

response.getWriter().write(""+code);

response.getWriter().close();

}

 

 

/**

 * 用户退出

1、销毁session

2、删除cookie

3、跳转到登录页面

 * @param request

 * @param response

 * @throws IOException

 */

//用户退出servlet

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);

response.addCookie(cookie);

 

// 3、跳转到登录页面

response.sendRedirect("login.jsp");

 

}

 

/**

 * 加载用户头像

1、得到参数(图片名)

2、得到图片的存放路径

3、通过路径,得到file对象

4、判断file对象是否存在,并且是一个标准文件

5、得到图片的后缀

6、根据不同的后缀设置对应的响应类型

7、将文件对象通过工具类FileUtils.copyFile()响应给客户端

 * @param request

 * @param response

 * @throws IOException

 */

//加载头像servlet

private void userHead(HttpServletRequest request, HttpServletResponse response) throws IOException {

// 1、得到参数(图片名)

String imageName = request.getParameter("imageName");

// 2、得到图片的存放路径

String path = request.getServletContext().getRealPath("/WEB-INF/upload/");

// 3、通过路径,得到file对象

File file = new File(path + imageName);

// 4、判断file对象是否存在,并且是一个标准文件

if (file.exists() && file.isFile()) {

// 5、得到图片的后缀

String pic = imageName.substring(imageName.lastIndexOf(".")+1);

// 6、根据不同的后缀设置对应的响应类型

if ("PNG".equalsIgnoreCase(pic)) {

response.setContentType("image/png");

} else if ("GIF".equalsIgnoreCase(pic)) {

response.setContentType("image/gif");

} else if ("JPG".equalsIgnoreCase(pic) || "JPEG".equalsIgnoreCase(pic)) {

response.setContentType("image/jpeg");

}

// 7、将文件对象通过工具类FileUtils.copyFile()响应给客户端

//需要提前 导包

FileUtils.copyFile(file, response.getOutputStream());

}

 

}

 

 

/**

 * 进入个人中心

 * @param request

 * @param response

 * @throws IOException

 * @throws ServletException

 */

//个人中心 servlet

private void userCenter(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

 

// 设置首页动态包含的页面值

request.setAttribute("changePage", "user/info.jsp");

 

// 请求转发跳转到首页

request.getRequestDispatcher("index.jsp").forward(request, response);

 

}

 

 

/**

 * 用户登录

1、接收参数

2、调用Service层的方法,得到resultInfo对象

3、判断resultInfo的code的值,判断是否登录成功

如果失败,将resultInfo对象存到request作用域中,请求转发跳转到登录页面

如果成功

1、将用户对象存到session作用域中

2、判断用户是否选择记住密码

如记住,,则存cookie对象

3、重定向跳转到indexServlet

 */

//用户登录 servlet

private void userLogin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// 1、接收参数

String uname = request.getParameter("userName");

String upwd = request.getParameter("userPwd");

 

// 2、调用Service层的方法,得到resultInfo对象

ResultInfo<User> resultInfo = userService.userLogin(uname, upwd);

 

// 3、判断resultInfo的code的值,判断是否登录成功

if (resultInfo.getCode() == 1) {

// 1、将用户对象(结果集)存到session作用域中 键值

request.getSession().setAttribute("user", resultInfo.getResult());

// 2、判断用户是否选择记住密码  如记住,,则存cookie对象

String rem = request.getParameter("rem");

if ("1".equals(rem)) {

// 存cookie对象

Cookie cookie = new Cookie("user",uname+ "-" + upwd);

// 设置失效时间

cookie.setMaxAge(3*24*60*60);

// 响应cookie

response.addCookie(cookie);

}

// 3、重定向跳转到indexServlet

response.sendRedirect("indexServlet");

 

} else {

// 如果失败,将resultInfo对象存到request作用域中,请求转发跳转到登录页面

request.setAttribute("resultInfo", resultInfo);

request.getRequestDispatcher("login.jsp").forward(request, response);

}

 

}

 

}

com.gy.service(业务逻辑层 用户)

com.gy.service.UserService.java

package com.gy.service;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.Part;

 

import com.gy.dao.UserDao;

import com.gy.po.User;

import com.gy.po.vo.ResultInfo;

import com.gy.util.MD5Util;

import com.gy.util.StringUtil;

 

public class UserService {

 

private UserDao userDao = new UserDao();

 

/**

 * 用户登录

1、判断参数是否为空

如果为空,设置resultInfo对象的code和msg的值,返回resultInfo给servlet

2、调用Dao层的查询方法,通过用户名查询用户对象,返回用户对象

如果用户对象为空,设置resultInfo对象的code和msg的值,返回resultInfo给servlet

3、如果存在,将数据库中的密码与前台传递的密码作比较

如果不正确,设置resultInfo对象的code和msg的值,

如果正确,设置resultInfo的code=1,

4、返回resultInfo给servlet

 * @param uname

 * @param upwd

 * @return

 */

//用户登录 service

public ResultInfo<User> userLogin(String uname, String upwd) {

 

ResultInfo<User> resultInfo = new ResultInfo<>();

 

 

// 数据回显

User u = new User();

u.setUname(uname);

u.setUpwd(upwd);

resultInfo.setResult(u);

 

 

// 1、判断参数是否为空

if (StringUtil.isEmpty(uname) || StringUtil.isEmpty(upwd)) {

// 如果为空,设置resultInfo对象的code和msg的值,返回resultInfo给servlet

resultInfo.setCode(0);

resultInfo.setMsg("用户名或密码不能为空!!");

return resultInfo;

}

 

// 2、调用Dao层的查询方法,通过用户名查询用户对象,返回用户对象

User user = userDao.findUserByUname(uname);

 

// 判断用户对象是否为空

if (user == null) {

// 如果用户对象为空,设置resultInfo对象的code和msg的值,返回resultInfo给servlet

resultInfo.setCode(0);

resultInfo.setMsg("用户不存在!");

return resultInfo;

}

 

// 因为数据库中的密码是加密过的,所以我们先将前台传递过来的密码加密后再与数据库比较

upwd = MD5Util.encode(MD5Util.encode(upwd));

// 3、如果存在,将数据库中的密码与前台传递的密码作比较

if (upwd.equals(user.getUpwd())) {

// 如果正确,设置resultInfo的code=1

resultInfo.setCode(1);

resultInfo.setResult(user); // 用来存session作用域的

} else {

// 如果不正确,设置resultInfo对象的code和msg的值

resultInfo.setCode(0);

resultInfo.setMsg("用户密码不正确!!");

}

 

return resultInfo;

}

 

/**

 * 验证昵称的唯一性

1、判断参数是否为空

如果为空,返回0

2、调用Dao层,通过昵称和用户ID查询数据库中除了当前记录之后是否有其他记录使用该昵称,返回user对象

3、判断user对象是否为空

如果为空,返回1

如果不为空,返回0

 * @param nickName

 * @param userId

 * @return

 */

//昵称唯一service

public int checkNick(String nickName, Integer userId) {

// 1、判断参数是否为空

if (StringUtil.isEmpty(nickName)) {

return 0;

}

 

// 2、调用Dao层,通过昵称和用户ID查询数据库中除了当前记录之后是否有其他记录使用该昵称,返回user对象

User user = userDao.findUserByNickAndUserId(nickName, userId);

// 3、判断user对象是否为空

if (user != null) {

return 0;

}

 

return 1;

}

 

 

/**

 * 修改用户信息

1、接收参数 (昵称、心情)

2、参数非非空判断 (昵称)

3、从session作用域中得到user对象,得到用户ID

4、===实现文件上传====

1、得到Part对象  request.getPart("name")  "name"代表的是前台的file文件域的name属性值

2、得到上传的文件名

3、判断文件名是否不为空

如果为空,表示未上传文件

如果不为空,则得到文件要存放的地址

4、上传文件到指定路径

5、如果上传了文件,则修改用户头像,否则使用原来的头像

6、调用Dao层的修改方法,返回受影响的行数

7、判断受影响的行数

如果大于0,成功,更新session作用域中色user对象

如果不大于0,失败

 

 * @param request

 * @return

 */

//修改用户信息service

public ResultInfo<User> updateInfo(HttpServletRequest request) {

ResultInfo<User> resultInfo = new ResultInfo<>();

// 1、接收参数 (昵称、心情)

String nickName = request.getParameter("nick11");

String mood = request.getParameter("mood");

// 2、参数非非空判断 (昵称)

if (StringUtil.isEmpty(nickName)) {

resultInfo.setCode(0);

resultInfo.setMsg("用户昵称不能为空!");

return resultInfo;

}

 

// 3、从session作用域中得到user对象,得到用户ID

User user = (User) request.getSession().getAttribute("user");

 

// 验证昵称的唯一性

int code = checkNick(nickName, user.getUserId());

// 判断昵称是否可用

if (code != 1) {

resultInfo.setCode(0);

resultInfo.setMsg("用户昵称已存在,请重试!");

return resultInfo;

}

 

String head = user.getHead(); // 原本的头像值

 

// ===实现文件上传====

try {

// 1、得到Part对象  request.getPart("name")  "name"代表的是前台的file文件域的name属性值

Part part = request.getPart("img");

// 2、得到上传的文件名

String fileName = part.getSubmittedFileName();

// 3、判断文件名是否不为空

if (!StringUtil.isEmpty(fileName)) {

 

// 重新给头像赋值

head = fileName;

 

// 如果不为空,则得到文件要存放的地址

String path = request.getServletContext().getRealPath("/WEB-INF/upload/");

// 4、上传文件到指定路径

part.write(path + fileName);

}

//如果为空,表示未上传文件

 

} catch (Exception e) {

e.printStackTrace();

}

 

// 重新给user对象赋值

user.setNick(nickName);

user.setMood(mood);

user.setHead(head);

 

// 6、调用Dao层的修改方法,返回受影响的行数

int row = userDao.updateUser(user);

 

// 7、判断受影响的行数

if (row >0) {

// 如果大于0,成功,更新session作用域中色user对象

request.getSession().setAttribute("user", user);

resultInfo.setCode(1);

resultInfo.setMsg("修改成功!");

} else {

resultInfo.setCode(0);

resultInfo.setMsg("修改失败!");

}

 

return resultInfo;

}

}

 

 

 

com.gy.Dao

com.gy.Dao.UserDao.java

 

package com.gy.dao;

 

import java.util.ArrayList;

import java.util.List;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import com.gy.po.User;

 

public class UserDao {

 

// 使用日志工厂类

private static Logger logger = LoggerFactory.getLogger(UserDao.class);

 

/**

 * 通过用户名查询用户对象是否存在

1、得到数据库连接

2、定义sql语句

3、预编译

4、设置参数,下标从1开始

5、执行查询,返回结果集

6、判断并分析结果集,得到用户对象

7、关闭资源

8、返回用户对象

 * @return

 */

//原生用户登录Dao

/*

public User findUserByUname(String uname) {

User user = null;

Connection connection = null;

PreparedStatement preparedStatement = null;

ResultSet resultSet = null;

 

try {

// 1、得到数据库连接

connection = DBUtil.getConnection();

// 2、定义sql语句

String sql = "select * from tb_user where uname = ? ";

 

logger.info("当前sql语句:" + sql);

logger.info("当前sql语句2:{}",sql);

 

// 3、预编译

preparedStatement = connection.prepareStatement(sql);

// 4、设置参数,下标从1开始

preparedStatement.setString(1, uname);

// 5、执行查询,返回结果集

resultSet = preparedStatement.executeQuery();

// 6、判断并分析结果集,得到用户对象

if (resultSet.next()) {

user = new User();

user.setHead(resultSet.getString("head"));

user.setMood(resultSet.getString("mood"));

user.setNick(resultSet.getString("nick"));

user.setUname(uname);

user.setUpwd(resultSet.getString("upwd"));

user.setUserId(resultSet.getInt("userId"));

}

} catch (Exception e) {

e.printStackTrace();

} finally {

// 关闭资源

DBUtil.close(connection, preparedStatement, resultSet);

}

 

return user;*/

//用户登录Dao

public User findUserByUname(String uname) {

 

// 1、定义sql语句

String sql = "select * from tb_user where uname = ? ";

// 2、参数集合

List<Object> params = new ArrayList<>();

params.add(uname);

// 3、调用BaseDao

User user = (User) BaseDao.queryRow(sql, params, User.class);

 

return user;

 

}

 

/**

 * 通过昵称和用户ID查询数据库中除了当前记录之后是否有其他记录使用该昵称,返回user对象

 * @param nickName

 * @param userId

 * @return

 */

原生判断昵称唯一Dao

/*public User findUserByNickAndUserId(String nickName, Integer userId) {

User user = null;

Connection connection = null;

PreparedStatement preparedStatement = null;

ResultSet resultSet = null;

 

try {

// 1、得到数据库连接

connection = DBUtil.getConnection();

// 2、定义sql语句

String sql = "select * from tb_user where nick = ? and userId != ?";

 

// 3、预编译

preparedStatement = connection.prepareStatement(sql);

// 4、设置参数,下标从1开始

preparedStatement.setString(1, nickName);

preparedStatement.setInt(2, userId);

// 5、执行查询,返回结果集

resultSet = preparedStatement.executeQuery();

// 6、判断并分析结果集,得到用户对象

if (resultSet.next()) {

user = new User();

user.setHead(resultSet.getString("head"));

user.setMood(resultSet.getString("mood"));

user.setNick(resultSet.getString("nick"));

user.setUname(resultSet.getString("uname"));

user.setUpwd(resultSet.getString("upwd"));

user.setUserId(resultSet.getInt("userId"));

}

} catch (Exception e) {

e.printStackTrace();

} finally {

// 关闭资源

DBUtil.close(connection, preparedStatement, resultSet);

}

 

return user;*/

//昵称唯一Dao

public User findUserByNickAndUserId(String nickName, Integer userId)

String sql = "select * from tb_user where nick = ? and userId != ?";

List<Object> params = new ArrayList<>();

params.add(nickName);

params.add(userId);

User user = (User) BaseDao.queryRow(sql, params, User.class);

return user;

}

 

/**

 * 通过用户OD修改用户对象

 * 定义sql语句

 * 定义参数集合

 * 调用BaseDao的更新方法

 * @param user

 * @return

 */

//修改用户信息Dao

public int updateUser(User user) {

// 定义sql语句

String sql = "update tb_user set nick = ?, mood = ?, head = ? where userId = ?";

// 定义参数集合

List<Object> params = new ArrayList<Object>();

params.add(user.getNick());

params.add(user.getMood());

params.add(user.getHead());

params.add(user.getUserId());

// 调用BaseDao的更新方法

int row = BaseDao.executeUpdate(sql, params);

 

return row;

}

 

}

com.gy.filter

//乱码过滤器

com.gy.filter.EncodeFilter.java

 

package com.gy.filter;

 

import java.io.IOException;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.annotation.WebFilter;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;

import javax.servlet.http.HttpServletResponse;

 

/**

 * 请求乱码问题

 *

 * Tomcat8及以上版本 Tomcat7及以下版本

 * POST请求 会乱码,request.setCharacterEncoding("UTF-8"); 会乱码,request.setCharacterEncoding("UTF-8");

 *

 * GET请求 不会乱码,不处理 会乱码,new String(request.getParameter(name).getBytes("ISO-8859-1"),"UTF-8");

 */

@WebFilter("/*")

public class EncodeFilter implements Filter {

  

    public EncodeFilter() {}

public void destroy() {}

public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain) throws IOException, ServletException {

// 基于HTTP

HttpServletRequest request = (HttpServletRequest) arg0;

HttpServletResponse response = (HttpServletResponse) arg1;

 

// 处理POST请求乱码 (无论什么版本服务器)

request.setCharacterEncoding("UTF-8");

 

// 处理GET请求乱码

// 1、得到请求类型

String method = request.getMethod();

// 2、判断是否是GET请求

if ("GET".equalsIgnoreCase(method)) {

// 3、如果是GET请求,则获取服务器版本信息

String serverInfo = request.getServletContext().getServerInfo();

//System.out.println(serverInfo);

// 4、得到服务器的版本号

String versionStr = serverInfo.substring(serverInfo.lastIndexOf("/")+1,serverInfo.lastIndexOf("/")+2);

// 5、判断是否是Tomcat8以下版本服务器

if (Integer.parseInt(versionStr) < 8) {

// new String(request.getParameter(name).getBytes("ISO-8859-1"),"UTF-8");

// 定义类,继承HttpServletRequestWrapper封装类,重写getParameter()方法,返回的类的本质是request对象

HttpServletRequest req = new MyWapper(request);

// 放行指定request对象  (Ttomcat7及以下版本的GET请求)

chain.doFilter(req, response);

return;

}

}

 

// POST请求和Ttomcat8及以上版本的GET请求放行

chain.doFilter(request, response);

}

public void init(FilterConfig fConfig) throws ServletException {

 

}

}

 

/**

 * 1、定义类

 * 2、继承HttpServletRequestWrapper封装类

 * 3、重写getParameter()方法

 *

 */

class MyWapper extends HttpServletRequestWrapper {

 

// 定义属性。提升作用域

private HttpServletRequest request;

 

/**

 * 带参构造器

 * @param request

 */

public MyWapper(HttpServletRequest request) {

super(request);

this.request = request;

}

 

/**

 * 重写getParameter()方法,处理乱码问题

 */

@Override

public String getParameter(String name) { // name代表的是前台传递的参数名,即键

 

// 获取参数的值

String value = request.getParameter(name);

 

// 判断值是否为空,不为空处理乱码问题

if (value == null || "".equals(value.trim())) {

return value;

}

try {

// 处理乱码问题

value = new String(value.getBytes("ISO-8859-1"),"UTF-8");

} catch (Exception e) {

e.printStackTrace();

}

 

return value;

}

 

}

com.gy.LoginAccessFilter.java

//自动登录过滤器

package com.gy.filter;

 

import java.io.IOException;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.annotation.WebFilter;

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import com.gy.po.User;

 

//先全部拦截

@WebFilter("/*")   //不可少的标识

public class LoginAccessFilter implements Filter {

 

public LoginAccessFilter() {}//构造器???

 

public void destroy() {}

 

public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain)

throws IOException, ServletException {

// 基于HTTP

HttpServletRequest request = (HttpServletRequest) arg0;

HttpServletResponse response = (HttpServletResponse) arg1;

 

// 得到请求的路径

String path = request.getRequestURI();

 

// 1、指定页面,放行 (无需登录即可访问的页面需要放行,如登录、注册等页面)

if (path.contains("/login.jsp")) {

chain.doFilter(request, response);

return;

}

// 2、静态资源,放行 (jscss、images等静态资源需要放行,项目中statics目录下的资源都放行)

if (path.contains("/statics")) {

chain.doFilter(request, response);

return;

}

// 3、指定行为,放行 (无需登录即可执行的操作需要放行,如登录操作、注册操作等)

// 判断是否是用户模块

if (path.contains("/userServlet")) { // "userServlet"代表的是对应的Servlet的对外访问路径

// 在 UserServlet中查询 在其页面的操作&&已登陆

// 得到用户行为

String actionName = request.getParameter("actionName");

if ("login".equals(actionName)) {

chain.doFilter(request, response);

return;

}

}

// 4、登录状态,放行 (判断session中的user对象是否为空;不为空则为登录状态)

// 得到session域对象中的user对象

User user = (User) request.getSession().getAttribute("user");

// 判断user对象是否为空

if (user != null) {

chain.doFilter(request, response);

return;

}

 

// EX 如果用户是非登录状态   //这部视为拦截

// 判断cookie是否存在

Cookie[] cookies = request.getCookies();

// 判断cookie数组是否为空

if (cookies != null && cookies.length > 0) {

// 遍历cookie数组

for (Cookie cookie : cookies) {

String name = cookie.getName();

String value = cookie.getValue();

// 得到指定名称的cookie的值

if ("user".equals(name)) {

//格式示例:  admin-123456

// 得到用户名称和密码

//剪裁之后是个数组

String uname = value.split("-")[0];

String upwd = value.split("-")[1];

// 拼接 登录的地址

String url = "userServlet?actionName=login&userName="+uname+"&userPwd="+upwd;

// 请求转发跳转登录操作

request.getRequestDispatcher(url).forward(request, response);

return;

}

}

}

// 拦截跳转到登录页面

response.sendRedirect("login.jsp");

}

 

public void init(FilterConfig fConfig) throws ServletException {

 

}

 

}

 

com.gy.util

com.gy.util.DBUtil.java

//JDBC工具类

 

package com.gy.util;

 

import java.io.InputStream;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.util.Properties;

 

/**

 * 数据库工具类

 * 1、打开数据库连接

 * 2、关闭资源

 *

 * 常见的报错情况:

 * 1、数据库的jar包未拷贝到lib目录下

 * java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

 * 2、数据库的密码可能不正确:

 * java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)

 * 3、数据库名称不正确

 * com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown database 'java29'

 *

 */

public class DBUtil {

 

// 得到配置文件对象

private static Properties properties = new Properties();

 

static {

try {

// 得到db.properties的输入流对象

InputStream inputStream = DBUtil.class.getClassLoader().getResourceAsStream("db.properties");

// 通过properties的load()方法,加载配置文件的输入流

properties.load(inputStream);

} catch (Exception e) {

// 打印异常

e.printStackTrace();

}

}

 

/**

 * 得到数据库连接

 * 1、加载驱动

 * 2、通过地址、账号、密码得到数据库连接

 * @return

 */

public static Connection getConnection() {

Connection connection = null;

 

// 从配置对象中获取参数   getProperty()

String jdbcName = properties.getProperty("jdbcName");

String dbUrl = properties.getProperty("dbUrl");

String dbName = properties.getProperty("dbName");

String dbPwd = properties.getProperty("dbPwd");

 

try {

// 1、加载驱动

Class.forName(jdbcName);

// 2、通过地址、账号、密码得到数据库连接

connection = DriverManager.getConnection(dbUrl, dbName, dbPwd);

} catch (Exception e) {

e.printStackTrace();

}

return connection;

}

 

/**

 * 关闭资源

 * @param connection

 * @param preparedStatement

 * @param resultSet

 */

public static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) {

// 关闭资源

try {

// 先判断不为空,再关闭

if (resultSet != null) {

resultSet.close();

}

if (preparedStatement != null) {

preparedStatement.close();

}

if (connection != null) {

connection.close();

}

} catch (Exception e) {

e.printStackTrace();

}

 

}

 

 

public static void main(String[] args) {

System.out.println(getConnection());

}

 

 

}

 

com.gy.util.JsonUtil.java

//Json对象工具类

 

package com.gy.util;

 

import java.io.IOException;

import java.io.PrintWriter;

 

import javax.servlet.http.HttpServletResponse;

 

import com.alibaba.fastjson.JSON;

 

/**

 * 将对象转换成JSON字符串,并响应给ajax的回调函数

 *

 */

public class JsonUtil {

 

public static void toJson(HttpServletResponse response, Object object) throws IOException {

// 1、设置响应类型及编码

response.setContentType("application/json;charset=UTF-8");

// 2、得到输出流

PrintWriter out = response.getWriter();

// 将对象转换成json格式的字符串

String json = JSON.toJSONString(object);

// 将json字符串响应给ajax的回调函数

out.write(json);

// 关闭资源

out.close();

}

}

 

com.gy.util.MD5Util.java

//MD5工具类

 

package com.gy.util;

 

import java.security.MessageDigest;

 

import org.apache.tomcat.util.codec.binary.Base64;

 

/**

 * 将字符串通过md5加密,返回加密后的字符串

 *

 */

public class MD5Util {

 

public static String encode(String str) {

String value = "";

try {

// 得到md5的加密程序

MessageDigest messageDigest = MessageDigest.getInstance("md5");

// 加密字符串,得到byte数组

byte[] bytes = messageDigest.digest(str.getBytes());

// 通过Base64编码,将byte数组转换成字符串

value = Base64.encodeBase64String(bytes);

} catch (Exception e) {

e.printStackTrace();

}

return value;

}

 

public static void main(String[] args) {

System.out.println(MD5Util.encode(MD5Util.encode("123456")));

}

 

}

 

com.gy.util.StringUtil.java

//String工具类

package com.gy.util;

 

/**

 * 字符串工具类

 *

 */

public class StringUtil {

 

 

/**

 * 判断字符串是否为空

 * 为空,返回true;否则返回false

 * @param str

 * @return

 */

public static boolean isEmpty(String str) {

if (str == null || "".equals(str.trim())) {

return true;

}

return false;

}

 

}

properties

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/error.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 ]