SMBMS项目
Servlet层负责接收用户数据,调用业务层,以及转发视图
service层就负责处理业务(从数据库调取信息)
持久层(Dao):连接查询数据库
前端:负责页面展示
数据库:SMBMS
做一个项目首先要看数据库查看表的结构:
- 借用sqlyog等工具查看表的结构
1、项目搭建准备
1.1、Maven
1.2、配置tomcat
1.3、导依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gong</groupId>
<artifactId>smbms</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!--测试用的-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<!--jsp-->
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<!--连接数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<!--jstl标签-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!--jstl依赖的-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
</project>
这些只是目前要用到的
1.4、创建项目包结构
-main
- java
- com.kuang
- dao 持久化层
- filter 过滤层
- pojo 实体层
- service 业务层
- servlet 调用业务层
- resources
- db.properties 数据库配置文件
- webapp
1.5、编写实体类
- ORM映射: 表 - 类(将数据库的字段映射成类 get、set),放到pojo中
1.6、编写基础公共类
- 数据库配置文件
- 编写数据库的公共类
- 编写字符编码过滤器
-
数据库配置文件
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/smbms?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=12345678
-
编写数据库的公共类
package com.gong.dao;
import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class BaseDao {
private static String driver;
private static String url;
private static String username;
private static String password;
static {
InputStream resourceAsStream = BaseDao.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
try {
properties.load(resourceAsStream);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
} catch (IOException e) {
e.printStackTrace();
}
}
//连接数据库
public static Connection getConnection(){
Connection connection = null;
try {
Class.forName(driver);
connection = DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
//便携查询公共方法
public static ResultSet execute(Connection connection,PreparedStatement preparedStatement,ResultSet resultSet,String sql,Object[] params) throws Exception{
preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
preparedStatement.setObject(i+1,params[i]);
}
resultSet = preparedStatement.executeQuery();
return resultSet;
}
//编写增删改公共类
public static int execute(Connection connection,String sql,Object[] params) throws Exception{
PreparedStatement preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
preparedStatement.setObject(i+1,params[i]);
}
int updateRows = preparedStatement.executeUpdate();
return updateRows;
}
//释放资源
public static boolean closeResource(Connection connection,PreparedStatement preparedStatement,ResultSet resultSet){
boolean flag = true;
if (resultSet!=null){
try {
resultSet.close();
resultSet=null;
} catch (SQLException throwables) {
throwables.printStackTrace();
flag = false;
}
}
if (connection!=null){
try {
connection.close();
connection = null;//gc回收
} catch (SQLException throwables) {
throwables.printStackTrace();
flag = false;
}
}
if (preparedStatement!=null){
try {
preparedStatement.close();
preparedStatement = null;
} catch (SQLException throwables) {
throwables.printStackTrace();
flag = false;
}
}
return flag;
}
}
连接数据库,增删改查方法实现
-
编写字符编码过滤器
package com.gong.filter;
import javax.servlet.*;
import java.io.IOException;
public class CharaterEncodingFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=UTF-8");
filterChain.doFilter(servletRequest,servletResponse);
}
public void destroy() {
}
}
要配置过滤器在web.xml中后面就不提醒了
<filter>
<filter-name>CharaterEncodingFilter</filter-name>
<filter-class>com.gong.filter.CharaterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharaterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1.7、导入静态资源
- webapp
以上都是准备阶段,下面才正式进入项目
2、登录
登录思想:根据用户输入的用户名(用户编码)调用查询查询有没有这个用户,并且对比密码是否正确
2.1、编写前端页面
2.2、设置首页
<!--设置欢迎页面-->
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
2.3、编写dao层登录用户登录接口
package com.gong.dao.user;
import com.gong.pojo.User;
import java.sql.Connection;
//获取用户信息接口
public interface UserDao {
public User getLoginUser(Connection connection,String userCode) throws Exception;
}
2.4、编写dao接口的实现类
package com.gong.dao.user;
import com.gong.dao.BaseDao;
import com.gong.pojo.User;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* 提供获得用户信息的方法
*/
public class UserDaoImpl implements UserDao {
public User getLoginUser(Connection connection, String userCode) throws Exception {
ResultSet rs = null;
PreparedStatement preparedStatement = null;
User user = null;
String sql = "select * from smbms_user where userCode =?";
Object[] params = {userCode};
rs = BaseDao.execute(connection,preparedStatement,rs, sql, params);
if (rs.next()){
user = new User();
user.setId(rs.getInt("id"));
user.setUserCode(rs.getString("userCode"));
user.setUserName(rs.getString("userName"));
user.setUserPassword(rs.getString("userPassword"));
user.setGender(rs.getInt("gender"));
user.setBirthday(rs.getDate("birthday"));
user.setPhone(rs.getString("phone"));
user.setAddress(rs.getString("address"));
user.setUserRole(rs.getInt("userRole"));
user.setCreatedBy(rs.getInt("createdBy"));
user.setCreationDate(rs.getDate("creationDate"));
user.setModifyBy(rs.getInt("modifyBy"));
user.setModifyDate(rs.getDate("modifyDate"));
}
BaseDao.closeResource(null, preparedStatement, rs);
return user;
}
}
2.5、业务层接口
package com.gong.service.user;
import com.gong.pojo.User;
public interface UserLoginService {
User Login(String userCode,String password) throws Exception;
}
2.6、业务层接口的实现类
调用Dao的方法获取欲登录用户的信息
package com.gong.service.user;
import com.gong.dao.BaseDao;
import com.gong.dao.user.UserDaoImpl;
import com.gong.pojo.User;
import org.junit.Test;
import java.sql.Connection;
/**
* 调用UserDaoImpl获取用户数据库信息
* 方便在servlet中对比
*/
public class UserLoginServiceImpl implements UserLoginService {
private UserDaoImpl UserDaoImpl;
public UserLoginServiceImpl() {
UserDaoImpl = new UserDaoImpl();
}
public User Login(String userCode, String password) {
Connection connection = null;
User user = null;
try {
connection = BaseDao.getConnection();
user = UserDaoImpl.getLoginUser(connection, userCode);
} catch (Exception e) {
e.printStackTrace();
}finally {
BaseDao.closeResource(connection, null, null);
}
return user;
}
}
2.7、编写Servlet
package com.gong.servlet.user;
import com.gong.pojo.User;
import com.gong.service.user.UserLoginServiceImpl;
import com.gong.util.Constant;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class UserLoginServletImpl extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入UserLoginServletImpl");
//前端传来获取用户的信息
String userCode = (String)req.getParameter("userCode");
String password = (String)req.getParameter("userPassword");
//下面两行从数据库获取用户信息
UserLoginServiceImpl userLoginService = new UserLoginServiceImpl();
User user = userLoginService.login(userCode,password);
//判断用户密码是否正确
if (user != null && user.getUserPassword().equals(password)){
req.getSession().setAttribute(Constant.USER_SESSION,user);
resp.sendRedirect("jsp/frame.jsp");
}else {
req.getSession().setAttribute("error", "用户名或者密码错误");
resp.sendRedirect("login.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2.8、注册Servlet
<servlet>
<servlet-name>UserLoginServletImpl</servlet-name>
<servlet-class>com.gong.servlet.user.UserLoginServletImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserLoginServletImpl</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
2.9、测试访问,确保以上功能成功
3、登录功能优化
3.1、注销功能
- 思路:移除Session,返回登录页面(因为有过滤层session没了就不能进入其他页面)
package com.gong.servlet.user;
import com.gong.util.Constant;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class UserLogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//移除session中用户信息
req.getSession().removeAttribute(Constant.USER_SESSION);
req.getSession().removeAttribute("error");
resp.sendRedirect("../login.jsp");
//System.out.println(req.getContextPath());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3.2、登录拦截优化
package com.gong.filter;
import com.gong.util.Constant;
import com.sun.deploy.net.HttpRequest;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class sysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//强转成HttpServletRequest才能获取session
HttpServletRequest req = (HttpServletRequest)servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
//session中的USER_SESSION空则说明注销了或者没登录,禁止访问某些页面
if (req.getSession().getAttribute(Constant.USER_SESSION)==null){
resp.sendRedirect("/smbms/error.jsp");
}else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
public void destroy() {
}
}
4、修改密码
导入前端页面,写项目,建议从底层往上写
思想:首先判断旧密码是否正确,用户登录后session中存放着旧密码对比一下就可以判断是否正确,所有判断都满足后根据用户id(session中有)改密码就行(update)
4.1、编写Dao接口
//修改密码
public int updatePwd(Connection connection,int id,String password)throws Exception;
4.2、Dao层实现类
public int updatePwd(Connection connection, int id, String password) throws Exception {
int execute = 0;
if (connection!=null){
String sql = "update smbms_user set userPassword = ? where id = ?";
connection.prepareStatement(sql);
Object[] params = {password,id};
execute = BaseDao.execute(connection, sql, params);
}
return execute;
}
4.3、Service层接口
//修改密码
boolean updatePwd(int id,String password);
4.4、Service接口实现类
//修改密码
public boolean updatePwd(int id, String password) {
boolean flag = false;
Connection connection =null;
try {
connection = BaseDao.getConnection();
//将数据给Dao层进行修改密码
int i = UserDaoImpl.updatePwd(connection, id, password);
if (i>0){
flag = true;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放资源
BaseDao.closeResource(connection, null, null);
}
return flag;
}
4.5、编写Servlet
实现Servlet复用,将方法提出来
package com.gong.servlet.user;
import com.gong.pojo.User;
import com.gong.service.user.UserLoginServiceImpl;
import com.gong.util.Constant;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class UpdatePwdServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//复用
String method = req.getParameter("method");
if (method.equals("savepwd")){
this.updatePwd(req, resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
//提成方法实现Servlet复用
public void updatePwd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String newpassword = req.getParameter("newpassword");
boolean flag = false;
//获取到用户
Object o = req.getSession().getAttribute(Constant.USER_SESSION);
if (o!=null && newpassword!=null && newpassword.length()!=0){
flag = new UserLoginServiceImpl().updatePwd(((User)o).getId(), newpassword);
if (flag){
req.setAttribute("message", "密码修改成功,请重新登录");
req.getSession().removeAttribute(Constant.USER_SESSION);
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
req.setAttribute("message", "密码修改失败");
}
}else{
req.setAttribute("message", "新密码有问题");
}
req.getRequestDispatcher("pwdmodify.jsp").forward(req, resp);
}
}
4.6、注册Servlet
<servlet>
<servlet-name>UpdatePwd</servlet-name>
<servlet-class>com.gong.servlet.user.UpdatePwdServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UpdatePwd</servlet-name>
<url-pattern>/jsp/user.do</url-pattern>
</servlet-mapping>
4.7、优化密码修改使用Ajax
之前我们只实现了密码修改但是没有验证旧密码是否正确
- 验证旧密码方法有很多,下面的方法是最推荐的,企业常用
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<!-- 其他类型转json工具阿里的-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
fastjson maven 阿里巴巴的:作用是将其他类型转换为json格式
//验证旧密码是否正确
public void pwdModify(HttpServletRequest req, HttpServletResponse resp){
//oldpassword是json传递过来的不是 当失去焦点就传过来了
String oldpassword = req.getParameter("oldpassword");
//session中有我们之前的密码信息
Object o = req.getSession().getAttribute(Constant.USER_SESSION);
Map<String, String> resultMap = new HashMap<String, String>();
if (o==null){//session过期
resultMap.put("result", "sessionerror");
}else if (StringUtils.isNullOrEmpty(oldpassword)){//输入的旧密码为空
resultMap.put("result", "error");
}else {
String userPassword = ((User)o).getUserPassword();
if (userPassword.equals(oldpassword)){//旧密码正确
resultMap.put("result", "true");
}else {//旧密码错误
resultMap.put("result", "false");
}
}
try {
PrintWriter writer = resp.getWriter();
//写出格式为json 类似与我们之前写出的"text/html"
resp.setContentType("application/json");
//JSONArray是导入包的方法将其他类型转换成json,
// 我们自己可以利用字符串拼接形式将map转为json
String s = JSONArray.toJSONString(resultMap);
writer.write(s);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
5、用户管理
思路:
5.1、导入分页的工具类
5.2、用户列表页面导入
- userlist.jsp
- rollpage.jsp
5.3、获取用户数量
根据用户名或者身份编号查询用户个数
①UserDao
//根据用户名或者身份编号查询用户个数
int getUserCount(Connection connection,String userName,int id) throws Exception;
②UserDaoImpl
//根据用户名或者身份编号查询用户个数
public int getUserCount(Connection connection, String userName, int id) throws Exception {
PreparedStatement pstm = null;
ResultSet rs = null;
int count = 0;
StringBuffer sql = new StringBuffer();
ArrayList<Object> list = new ArrayList<Object>();
if (connection !=null){
sql.append("select count(1) as count from smbms_user u,smbms_role r where u.userRole=r.id");
if (!StringUtils.isNullOrEmpty(userName)){
sql.append(" and u.userName like ?");//拼接sql
list.add("%"+userName+"%");
}
if (id>0){
sql.append(" and r.id = ?");
list.add(id);
}
}
System.out.println(sql.toString());//查看sql语句
Object[] params = list.toArray();
rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);
if (rs.next()){
count = rs.getInt("count");//count是上面sql我们重命名的
}
BaseDao.closeResource(null, pstm, rs);
return count;
}
③UserService
int getUserCount(String userName,int id) throws Exception;
④UserServiceImpl
//根据用户名或者身份编号查询用户个数
public int getUserCount(String userName, int id) throws Exception {
Connection connection = BaseDao.getConnection();
int userCount = UserDaoImpl.getUserCount(connection, userName, id);
BaseDao.closeResource(connection, null, null);
return userCount;
}
5.4、获取用户列表
获取用户列表并实现分页查询
①UserDao
//根据用户名或者身份id查询用户列表
List<User> getUserList(Connection connection,String userName,int id,int currentPageNo,int pageSize)throws Exception;
②UserDaoImpl
public List<User> getUserList(Connection connection, String userName, int id,int currentPageNo,int pageSize) throws Exception {
ArrayList<User> userList = new ArrayList<User>();//用户列表
ArrayList<Object> list = new ArrayList<Object>();//sql参数
User user = new User();
PreparedStatement pstm = null;
ResultSet rs = null;
StringBuffer sql = new StringBuffer();
if (connection!=null){
sql.append("select u.*,r.roleName roleName from smbms_role r,smbms_user u where u.userRole =r.id");
if (!StringUtils.isNullOrEmpty(userName)){//名字不为空
sql.append(" and u.userName like ?");
list.add("%"+userName+"%");
}
if (id>0){//角色身份id存在
sql.append( "and r.id = ?");
list.add(id);
}
//分页查询
sql.append(" order by u.id ASC limit ?,?");
/*
1 0 5
2 5 5
3 10 5 可以看出下面这个计算公式由来
*/
currentPageNo = (currentPageNo-1)*pageSize;//当前第几个数据
list.add(currentPageNo);
list.add(pageSize);//页面显示信息个数
Object[] params = list.toArray();
System.out.println("UserDaoImpl->getUserList:sql:"+sql.toString());
rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);
while (rs.next()){
user.setId(rs.getInt("id"));
user.setUserCode(rs.getString("userCode"));
user.setUserName(rs.getString("userName"));
user.setUserPassword(rs.getString("userPassword"));
user.setGender(rs.getInt("gender"));
user.setBirthday(rs.getDate("birthday"));
user.setPhone(rs.getString("phone"));
user.setAddress(rs.getString("address"));
user.setUserRole(rs.getInt("userRole"));
user.setCreatedBy(rs.getInt("createdBy"));
user.setCreationDate(rs.getDate("creationDate"));
user.setModifyBy(rs.getInt("modifyBy"));
user.setModifyDate(rs.getDate("modifyDate"));
user.getUserRoleName(rs.getString("roleName"));
userList.add(user);
}
BaseDao.closeResource(null, pstm, rs);
}
return userList;
}
③UserService
//获取用户列表
List<User> getUserList(String userName, int id, int currentPageNo, int pageSize)throws Exception;
④UserServiceImpl
//根据用户名或者身份编号获取用户列表
public List<User> getUserList(String userName, int id, int currentPageNo, int pageSize) throws Exception {
List<User> users = new ArrayList<User>();
Connection connection = BaseDao.getConnection();
//执行Dao持久层方法根据用户名或者id查询信息
List<User> userList = UserDaoImpl.getUserList(connection, userName, id, currentPageNo, pageSize);
//释放资源
BaseDao.closeResource(connection, null, null);
return userList;
}
5.5、获取角色操作
为了职责统一,可以把角色的操作单独放在一个包中,并和POJO类进行对应。
①RoleDao
package com.gong.dao.role;
import com.gong.pojo.Role;
import java.sql.Connection;
import java.util.List;
public interface RoleDao {
List<Role> getRoleList(Connection connection);
}
②RoleDaoImpl
package com.gong.dao.role;
import com.gong.dao.BaseDao;
import com.gong.pojo.Role;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class RoleDaoImpl implements RoleDao {
//获取role角色职位列表
public List<Role> getRoleList(Connection connection) {
//查询role职位信息
String sql = "select * from smbms_role";
Object[] params = {};
ResultSet rs = null;
PreparedStatement pstm = null;
List<Role> roleList = new ArrayList<Role>();
if (connection!=null){
try {
rs = BaseDao.execute(connection, pstm, rs, sql, params);
while (rs.next()){
Role role = new Role();
role.setId(rs.getInt("id"));
role.setRoleName("roleName");
role.setRoleCode("roleCode");
roleList.add(role);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
BaseDao.closeResource(null, pstm, rs);
}
}
return roleList;
}
}
③RoleService
package com.gong.service.role;
import com.gong.pojo.Role;
import java.util.List;
public interface RoleService {
//获取角色列表
List<Role> getRoleList();
}
④RoleServiceImpl
package com.gong.service.role;
import com.gong.dao.BaseDao;
import com.gong.dao.role.RoleDao;
import com.gong.dao.role.RoleDaoImpl;
import com.gong.pojo.Role;
import java.sql.Connection;
import java.util.List;
public class RoleServiceImpl implements RoleService {
private RoleDao roleDao;
public RoleServiceImpl() {
roleDao = new RoleDaoImpl();
}
public List<Role> getRoleList() {
Connection connection = BaseDao.getConnection();
List<Role> roleList = roleDao.getRoleList(connection);
return roleList;
}
//获取角色正常
// @Test
// public void test(){
// List<Role> roleList = this.getRoleList();
// System.out.println(roleList.toString());
// }
}
5.6、用户显示的Servlet
- 获取用户前端的数据(查询)
- 判断请求是否需要执行,看参数的值判断
- 为了实现分页,需要计算出当前页面和总页面,页面大小…
- 用户列表展示
- 返回前端
小黄鸭调试法:
- 程序员修炼之道
- 和小黄鸭边说边分析(物体)
//展示查询用户页信息(全局最难处)
public void query(HttpServletRequest req, HttpServletResponse resp) throws Exception {
//1.从前端获取用户信息
String queryname = req.getParameter("queryname");
String temp = req.getParameter("queryUserRole");//角色id
String pageIndex = req.getParameter("pageIndex");
int queryUserRole = 0;//给一个初始化方便首次登录显示全部
//2.获取用户
UserLoginServiceImpl userService = new UserLoginServiceImpl();
//首次进入页面显示多少个固定死
int pageSize = 5;//可以写在配置文件方便后期修改
int currentPageNo = 1;
//null和空不一样的""的长度是0
if (queryname==null){
queryname = "";
}
//给角色id赋值 0,1,2,3
if (temp!=null && !temp.equals("")){
queryUserRole = Integer.parseInt(temp);
}
//默认第一页,用pageIndex获取当前页
if (pageIndex!=null){
currentPageNo = Integer.parseInt(pageIndex);
}
//获取用户总数(分页问题)
int totalCount = userService.getUserCount(queryname, queryUserRole);
//总页数等支持
PageSupport pageSupport = new PageSupport();
pageSupport.setPageSize(pageSize);
pageSupport.setTotalCount(totalCount);
pageSupport.setCurrentPageNo(currentPageNo);
//显示页数
int totalPageCount = (int)(totalCount/pageSize)+1;
//控制首页和尾页,页面小于1就显示第一页内容
if (currentPageNo<1){
currentPageNo = 1;
}else if (currentPageNo>totalPageCount){
currentPageNo = totalPageCount;
}
//3.给前端传递数据
List<User> userList = userService.getUserList(queryname, queryUserRole, currentPageNo, pageSize);
req.setAttribute("userList",userList);//用户列表
RoleServiceImpl roleService = new RoleServiceImpl();
List<Role> roleList = roleService.getRoleList();
//前端要用到什么数据就传递什么数据
req.setAttribute("roleList",roleList);//角色列表
req.setAttribute("totalCount",totalCount);//用户总数
req.setAttribute("currentPageNo",currentPageNo);//当前页
req.setAttribute("totalPageCount",totalPageCount);//总页数
//请求转发
req.getRequestDispatcher("userlist.jsp").forward(req,resp);
}
5.7、增加用户
思想:很简单三层架构按顺序来就行
- 一切的增删改操作都需要处理事务 - ACID原则
增加用户:
- 前端(表单提交)
/jsp/user.do?method=add
- servlet
userService.addUser(user)
- service
userDao.add(connection,user)
- Dao
BaseDao.execute(connection,pstm,sql,params)
其他方法大概都是增加用户这个流程都差不多(就写一个增加用户演示一下)
①UserDao
//增加用户信息
int addUser(Connection connection,User user)throws Exception;
②UserDaoImpl
//增加用户
public int addUser(Connection connection, User user) throws Exception {
PreparedStatement pstm = null;
ResultSet rs = null;
int count=0;
if (connection!=null){
String sql = "insert into smbms_user(userCode,userName,userPassword," +
" gender,birthday,phone,address,userRole" +
",createdBy,creationDate)" +
"values (?,?,?,?,?,?,?,?,?,?)";
Object[] params = {user.getUserCode(),user.getUserName(),user.getUserPassword()
,user.getGender(),user.getBirthday(),user.getPhone(),user.getAddress()
,user.getUserRole(),user.getCreatedBy(),user.getCreationDate()
};
count = BaseDao.execute(connection, sql, params);
BaseDao.closeResource(null, pstm, rs);
}
return count;
}
③UserService
//增加用户
boolean addUser(User user) throws SQLException;
④UserServiceImpl
//增加用户
public boolean addUser(User user) throws SQLException {
boolean flag = false;
int count = 0;
if (!StringUtils.isNullOrEmpty(user.getUserPassword())){
Connection connection = BaseDao.getConnection();
//要开启事务回滚
try {
connection.setAutoCommit(false);
count = UserDaoImpl.addUser(connection, user);
connection.commit();
if (count>0){
flag = true;
System.out.println("添加用户成功");
}else {
System.out.println("用户添加失败");
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("用户添加失败");
connection.rollback();//失败回滚
}finally {
BaseDao.closeResource(connection, null, null);
}
}
return flag;
}
⑤servlet
public void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException, SQLException {
System.out.println("当前正在执行增加用户操作");
//从前端得到页面的请求的参数即用户输入的值
String userCode = req.getParameter("userCode");
String userName = req.getParameter("userName");
String userPassword = req.getParameter("userPassword");
//String ruserPassword = req.getParameter("ruserPassword");
String gender = req.getParameter("gender");
String birthday = req.getParameter("birthday");
String phone = req.getParameter("phone");
String address = req.getParameter("address");
String userRole = req.getParameter("userRole");
//把这些值塞进一个用户属性中
User user = new User();
user.setUserCode(userCode);
user.setUserName(userName);
user.setUserPassword(userPassword);
user.setAddress(address);
user.setGender(Integer.valueOf(gender));
user.setPhone(phone);
try {
user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(birthday));
} catch (ParseException e) {
e.printStackTrace();
}
user.setUserRole(Integer.valueOf(userRole));
user.setCreationDate(new Date());
//查找当前正在登陆的用户的id
user.setCreatedBy(((User)req.getSession().getAttribute(Constant.USER_SESSION)).getId());
UserLoginServiceImpl userService = new UserLoginServiceImpl();
Boolean flag = userService.addUser(user);
//如果添加成功,则页面转发,否则重新刷新,再次跳转到当前页面
if(flag){
resp.sendRedirect(req.getContextPath()+"/jsp/user.do?method=query");
}else{
req.getRequestDispatcher("useradd.jsp").forward(req,resp);
}
}
删除用户
一样的很简单,根据id删就行
①UserDao
int deleteUser(Connection connection,int id) throws Exception;
②UserDaoImpl
//删除用户
public int deleteUser(Connection connection, int id) throws Exception {
PreparedStatement pstm = null;
ResultSet rs = null;
int delResult = 0;
Object[] params = {id};
String sql = "delete from smbms_user where id = ?";
if (connection!=null){
delResult = BaseDao.execute(connection, sql, params);
}
BaseDao.closeResource(null, pstm, rs);
return delResult;
}
③UserService
//删除用户
boolean delUser(int id) throws Exception;
④UserServiceImpl
public boolean delUser(int id) throws SQLException {
boolean flag = false;
Connection connection = BaseDao.getConnection();
//开启事务
try {
connection.setAutoCommit(false);
int i = UserDaoImpl.deleteUser(connection, id);
connection.commit();
if (i>0){
System.out.println("删除用户成功");
flag = true;
}
} catch (Exception e) {
connection.rollback();
e.printStackTrace();
}finally {
BaseDao.closeResource(connection, null, null);
}
return flag;
}
⑤Servlet
private void deluser(HttpServletRequest req, HttpServletResponse resp) throws IOException {
boolean flag = false;
String userid = req.getParameter("uid");
System.out.println("Servlet--deluser"+userid);
Map<String, String> map = new HashMap<String, String>();//返回给json键值对
if (StringUtils.isNullOrEmpty(userid)){
map.put("delResult", "notexist");
}else {
UserLoginServiceImpl userService = new UserLoginServiceImpl();
Integer uid = Integer.valueOf(userid);
try {
flag = userService.delUser(uid);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
if (flag){
map.put("delResult", "true");
}else {
map.put("delResult", "false");
}
}
//写出json
PrintWriter writer = resp.getWriter();
resp.setContentType("application/json");
String s = JSONArray.toJSONString(map);
writer.write(s);
writer.flush();
writer.close();
}
项目搭建
Empty Project
Project
File - Module
文件上传和下载
在web应用中,文件上传和下载功能是非常常用的功能。
准备工作
- 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的。
- 一般选择采用apache的开源工具
common-fileupload
这个文件上传组件; common-fileupload
是依赖于common-io
这个包的,所以还需要下载这个包
使用类介绍
文件上传注意事项(上传文件调优方法)
- 为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放在WEB-INF目录下。
- 为防止文件覆盖的现象发生,要为上传文件产生一个 唯一的文件名。(时间戳+uuid(生成随机且不会重复的数字)、md5、位运算算法)
- 要限制上传文件的最大值。(服务器要钱)
- 可以限制上传文件的类型 ,在收到上传文件名时,判断后缀名是否合法。
需要用到的类详解
-
ServletFileUpload
负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象,在使用ServletFileUpload
对象解析请求时需要DiskFileItemFactory
对象。所以,我们需要在进行解析工作前构造好DiskFileItemFactory
对象,通过ServletFileUpload
对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。 -
ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象中,使用其
parseRequest(HttpServletRequest)
方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回。使用该方法处理上传文件简单易用。 -
FileItem类
在HTML页面input必须有name
<input type="file" name="filename">
表单如果包含一个文件上传输入项的话,这个表单的enctype属性就必须设置为multipart/form-data
<!--浏览器表单的类型如果为multipart/form-data,在服务器端想获取数据就要通过流。--><form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post"> 上传用户:<input type="text" name="username"><br/> 上传文件1:<input type="file" name="file1"><br/> 上传文件2:<input type="file" name="file2"><br/> <input type="submit" value="提交"></form>
常用方法
isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单,还是一个文件表单;如果是普通表单字段则返回true,否则返回falseboolean isFormField();getFieldName方法用于返回表单标签name属性的值String getFieldName();getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回String getString();getName方法用于获得文件上传字段中的文件名String getName();以流的形式返回上传文件的数据内容InputStream getInputStream()delete方法用于清空FileItem类对象中存放的主体内容;如果主体内容被保存在临时文件中,delete方法将删除该临时文件void delete();
判断上传的文件是普通表单还是文件表单
邮件发送
- 要在网络上实现邮件功能,必须要有专门的邮件服务器。
- 这些邮件服务器类似于显示生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
- SMTP服务器地址:一般是smtp.xxx.com,比如163邮箱是smtp.163.com,qq邮箱是smtp.qq.com。
- 电子邮箱(E-Mail地址)的获得需要在邮件服务器上进行申请。比如我们要使用QQ邮箱,就需要开通邮箱功能;
传输协议
SMTP协议
发送邮件:
我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。
POP3协议
接收邮件:
我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。
使用java发送E-mail十分简单,但是首先你应该准备JavaMail API和Java Activation Framework。
得到两个jar包
mail.jar
activation.jar
MIME:多用途互联网邮件扩展类型
它是一个互联网标准,扩展了电子邮件标准,使其能够支持:
- 声音、图像、视频、- 附件
MimeBodyPart类
javax.mail.internet.MimeBodyPart类表示的是一个MIME消息,它和MimeMessage类一样都是从Part接口继承过来。
MimeMultipart类
javax.mail.internet.MimeMultipart是抽象类Multipart的实现子类,它用来组合多个MIME消息。一个MimeMultipart对象可以包含多个代表MIME消息的MimeBodyPart对象。
微服务项目
File - new Project - Spring Initializr - next - next