一、项目搭建准备工作
【注意】jdbc配置url:useSSL=false
-
搭建一个Maven Web项目
-
配置Tomcat
web项目的默认上下文:/smbms
-
测试项目是否能跑起来
-
导入项目中会遇到的包
jsp, Servlet, mysql驱动, jstl, standard
-
编写实体类pojo(表和类映射)
User、 Bill、 Role、 Provider
-
编写基础公共类
-
数据库配置文件
driver=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/smbms?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai user=root password=dxw1997423
-
通过类加载器读取上述配置文件的资源
InputStream is = baseDao.class.getClassLoader().getResourceAsStream("db.properties");
Class是当前类的Class对象,Class.getClassLoader()是获取当前类的类加载器。类加载器的大概作用是当需要使用一个类时,加载该类的".class"文件,并创建对应的class对象,将class文件加载到虚拟机的内存。getResourceAsStream()是获取资源的输入流。类加载器默认是从classPath路径加载资源。
参考链接 -
编写数据库的公共类
package com.duan.dao; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; //操作数据库的公共类 public class baseDao { private static String driver; private static String url; private static String username; private static String password; static { Properties properties = new Properties(); //通过类加载器读取对应的资源 InputStream is = baseDao.class.getClassLoader().getResourceAsStream("db.properties"); try{ properties.load(is); }catch (IOException e){ e.printStackTrace(); } driver = properties.getProperty("driver"); url = properties.getProperty("url"); username = properties.getProperty("user"); password = properties.getProperty("password"); } //获取数据库链接 public static Connection getConnection(){ Connection connection = null; try{ Class.forName(driver); //得到数据库的连接对象。properties中的:driver=com.mysql.jdbc.Driver connection = DriverManager.getConnection(url, username, password); }catch (Exception e){ e.printStackTrace(); } return connection; } //编写查询公共类 public static ResultSet execute(Connection connection, String sql, Object []params, ResultSet resultSet, PreparedStatement preparedStatement) throws SQLException { preparedStatement = connection.prepareStatement(sql); for(int i = 0; i < params.length; i++){ //setObject,占位符从1开始,但是我们的数组是从0开始 preparedStatement.setObject(i+1, params[i]); } resultSet = preparedStatement.executeQuery(); return resultSet; } //编写增删改查公共方法 public static int execute(Connection connection, String sql, Object []params, PreparedStatement preparedStatement) throws SQLException { preparedStatement = connection.prepareStatement(sql); for(int i = 0; i < params.length; i++){ //setObject,占位符从1开始,但是我们的数组是从0开始 preparedStatement.setObject(i+1, params[i]); } int updateRows = preparedStatement.executeUpdate(); return updateRows; } //释放资源 public static boolean closeResource(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet){ boolean flag = true; if(resultSet != null){ try{ resultSet.close(); //GC回收 resultSet = null; }catch (SQLException e){ e.printStackTrace(); flag = false; } } if(preparedStatement != null){ try{ preparedStatement.close(); //GC回收 preparedStatement = null; }catch (SQLException e){ e.printStackTrace(); flag = false; } } if(connection != null){ try{ connection.close(); //GC回收 connection = null; }catch (SQLException e){ e.printStackTrace(); flag = false; } } return flag; } }
【注意】
-
参数名称一定要正确比配
-
jdbc配置url要写对
useSSL=true是进行安全验证,一般通过证书或者令牌什么的,useSSL=false就是通过账号密码进行连接,通常使用useSSL=false!!!
-
-
编写字符编码过滤器
-
-
导入静态资源
二、登录功能实现
-
编写前端页面
login.jsp
<div class="inputbox"> <label>用户名:</label> <input type="text" class="input-text" id="userCode" name="userCode" placeholder="请输入用户名" required/> </div> <div class="inputbox"> <label>密码:</label> <input type="password" id="userPassword" name="userPassword" placeholder="请输入密码" required/> </div>
-
设置首页
/jsp/frame.jsp
-
编写dao层登录用户登录的接口
User baseDao(Connection connection, String userCode) throws SQLException
-
编写dao接口的实现类
用类java.sql.Statement的executequery()方法查询的结果集永远不会返回null,可以用rs.next()方法来判断有没结果集。因为一个结果集最初将游标定位在第一行的前面,每调用一次,游标后移一个,当resultset游动到最后一行,再调用next()方法会返回false,并且游标也到了最后一行的后面!要是再调用next()的话就会出现异常!!!!!!
- 输入connection、userCode
- 编写sql语句,和参数params
- 调用**baseDao(connection, sql, params, resultSet, preparedStatement)**的查询方法
- 如果返回的resultSet有值:resulSet.next(), 生成一个user对象
- 关闭prepareStatement和resultSet
- 返回user
-
业务层接口
-
public User loginService(String userCode, String password);
-
-
业务层接口实现类
- 生成connection对象,loginDao对象:loginDao(connection, userCode)
- 利用loginDao返回的user对象的password参数与输入的password进行对比,如果不一样就代表登录信息出错,让user=null,交给上一层处理。
- 关闭connection
-
编写Servlet层
-
实例化UserServiceImpl
-
使用userServiceImpl.loginService(userCode, password)方法,返回User对象
-
判断user是否是null
- 如果不是null,即查有此人,重定向到主页
- 如果是null,即查无此人,转发回登录页面,并提示输入密码错误
public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String userCode = req.getParameter("userCode"); String password = req.getParameter("userPassword"); UserService userService = new UserServiceImpl(); User user = userService.loginService(userCode, password); if(user != null){//查有此人,可以登录 //将用户的信息放到Session中 req.getSession().setAttribute(Constants.USER_SESSION, user);//尽量放在一个常量里面 //跳转到内部主页 System.out.println("===============================查有此人"); resp.sendRedirect(req.getContextPath() + "/jsp/frame.jsp"); }else{//查无此人,无法登录 //转发回登录页面,顺带提示它,用户名或密码错误 System.out.println("登录失败,回到登录页面"); req.setAttribute("error", "用户名或者密码不正确"); req.getRequestDispatcher("login.jsp").forward(req, resp); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
-
-
注册Servlet
-
测试访问,确保以上功能成功!
三、登录功能优化
注销功能:
思路:
- 移出session,返回登录页面
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//移出用户的Session
req.getSession().removeAttribute(Constants.USER_SESSION);
//回到登录页面
resp.sendRedirect("/login.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 注册LogoutServlet
<servlet>
<servlet-name>LogoutServelt</servlet-name>
<servlet-class>com.duan.servlet.user.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogoutServelt</servlet-name>
<url-pattern>/jsp/logout.do</url-pattern>
</servlet-mapping>
登录拦截优化
如果直接输入url访问主界面,在不设置登录拦截下,由于没有判定session内容,可以直接登录到主界面。
这样是不允许的!
所以使用过滤器拦截登录:
-
将req和resp转换
-
从HttpServletRequest中提取Session信息,提取user
-
如果user是空,就直接冲定向至错误页面**(这里注意重定向的路径设置)**
-
因为此请求URL路径是
http://localhost:8080/smbms/jsp/frame.jsp
所以在此请求路径下,响应重定向至error.jsp,除了用绝对路径外,
可使用相对路径:…/error.jsp
(因此,重定向要通过请求路径来判断)
-
public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//过滤器从Session中获取用户
User user = (User)request.getSession().getAttribute(Constants.USER_SESSION);
if(user == null){
System.out.println("用户已经被移除了,马上重定向到错误页面");
//已经被移出/注销了,或者未登录
System.out.println(request.getRequestURI());// 因为复制粘贴的是登登录主页的url进行登录,所以获取request的URI就是:/smbms/jsp/frame.jsp
response.sendRedirect(request.getContextPath() + "/error.jsp");//"/error.jsp"不行
}else{
chain.doFilter(req, resp);
}
}
public void destroy() {
}
}
【注意】重定向路径问题!
在上面
四、密码修改
-
导入前端素材
<li><a href="../jsp/pwdmodify.jsp">密码修改</a></li>
【注意】调整好head.jsp中的url路径,使之能够成功跳转至pwdmodify.jsp
-
从底至上,编写dao、service、 servlet层代码
dao
public int updatePwd(Connection connection, int id, String password) throws SQLException { PreparedStatement preparedStatement = null; String sql = null; int res = 0; if(connection != null){ sql = "update smbms_user set userPassword = ? where id = ?"; Object[] params = {password, id}; res = baseDao.execute(connection, sql, params, preparedStatement); baseDao.closeResource(null, preparedStatement, null); } return res; }
service
public boolean updatePwd(int id, String password) { Connection connection = null; boolean flag = false; try{ connection = baseDao.getConnection(); int res = userDao.updatePwd(connection, id, password); if(res > 0){//返回值大于零,成功修改了 flag = true; } }catch (SQLException e){ e.printStackTrace(); }finally { baseDao.closeResource(connection, null, null); } return flag; }
servlet
public void updatePwd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //从Session里获取id! Object o = req.getSession().getAttribute(Constants.USER_SESSION); String newpassword = req.getParameter("newpassword"); boolean flag = false; //判断o是否存在 和 新的密码是否有效 if(o != null && newpassword != null && newpassword.length() != 0){ User user = (User)o; int id = user.getId(); UserServiceImpl userService = new UserServiceImpl(); System.out.println(newpassword); flag = userService.updatePwd(id, newpassword); //修改后的结果 if(flag){ //修改成功,就清空当前Session信息。 req.setAttribute("message", "修改密码成功,请退出, 使用新的密码登录"); req.getSession().removeAttribute(Constants.USER_SESSION); }else{ //修改失败 req.setAttribute("message", "修改密码失败"); } }else{ req.setAttribute("message", "新密码有问题!"); } req.getRequestDispatcher("pwdmodify.jsp").forward(req,resp); }
【注意】
-
servlet层注意在web.xml中进行url注册!
-
实现servlet的复用
利用前端中的input type=hidden, servlet读取其值,判断input需要的方法
【注意】Ajax技术
- 请求方法GET
- 请求路径url
- 请求method在Servlet中读取该值而选择相应的方法,以及Ajax传递的参数,最终返回data
- dataType:要求返回类型是json类型
- 通过阿里巴巴的Fastjson来构造json格式的字符串,在resp中writer出去。
达到效果:旧密码的输入对错直接在前端通过Ajax技术来判断!而且直接能够当即显示对错
oldpassword.on("blur",function(){
$.ajax({
type:"GET",
url:"/smbms/jsp/user.do",
//url:path+"/jsp/user.do",
data:{method:"pwdmodify",oldpassword:oldpassword.val()}, //Ajax传递的参数
//path+/jsp/user.do?method=pwdmodify&oldpassword=oldpassword.val();
dataType:"json", //主流开发都是用JSON实现前后端交互
success:function(data){
if(data.result == "true"){//旧密码正确
validateTip(oldpassword.next(),{"color":"green"},imgYes,true);
}else if(data.result == "false"){//旧密码输入不正确
validateTip(oldpassword.next(),{"color":"red"},imgNo + " 原密码输入不正确",false);
}else if(data.result == "sessionerror"){//当前用户session过期,请重新登录
validateTip(oldpassword.next(),{"color":"red"},imgNo + " 当前用户session过期,请重新登录",false);
}else if(data.result == "error"){//旧密码输入为空
validateTip(oldpassword.next(),{"color":"red"},imgNo + " 请输入旧密码",false);
}
},
error:function(data){
//请求出错
validateTip(oldpassword.next(),{"color":"red"},imgNo + " 请求错误",false);
}
});
}).on("focus",function(){
validateTip(oldpassword.next(),{"color":"#666666"},"* 请输入原密码",false);
});
五、用户管理实现
1. 获取用户数量
【重点】这里的SQL编写方法
-
UserDao
-
UserDaolmpl
- 查询方法参数:connection、userName、userRole
> 由于页面查询可以设置用户名、用户角色进行指定查询,所以后台查询也需要设置条件。
-
用户信息栏中体现的信息不只是一个smbms_user表中的信息,而是联合了smbms_role中的信息,所以SQL需要写出联表查询
select count(1) as count from smbms_user u,smbms_role r where u.userRole = r.id
-
另外还需设置查询条件,即用户名、用户角色。
由于不一定在查询条件中有输入用户名和用户角色,所以应该先进行判断,接收到的参数userName和userRole是否是空或是>0。根据不同的情况往sql中加入查询条件,以及往params中添加具体条件信息(这里需要进行模糊查询,有关姓名;所以我们的sql参数改用可以实时add元素的ArrayList的类型进行收集,最后再转换为数组,真的很方便)
所以我们编写代码使得:如果加一个条件,对应加一个 SQL 以及 指定"?"的参数
//1. 联表查询:查询 用户表中的userRole 等于 角色表中的角色id时 的所有行数!(因为页面列表中用户信息要显示用户角色名字) //"select count(1) as count from smbms_user u,smbms_role r where u.userRole = r.id"; StringBuilder sql = new StringBuilder(); sql.append("select count(1) as count from smbms_user u,smbms_role r where u.userRole = r.id"); ArrayList<Object> list = new ArrayList<Object>();//存放我们的参数 //2. 查询条件1:用户名 if(!StringUtils.isNullOrEmpty(userName)){ //如过界面中输入了userName,则往SQL中加入新的查询条件,进行模糊查询 sql.append("and u.userName like ?"); list.add("%" + userName + "%"); //index=0 } //3. 查询条件2:用户角色 if(userRole > 0){ sql.append("and u.userRole = ?"); list.add(userRole); //index=1 } System.out.println("UserDaoImpl -> numOfUser" + sql.toString()); Object[] params = list.toArray(); resultSet = baseDao.execute(connection, sql.toString(), params, resultSet, preparedStatement);
-
UserService
-
UserServiceImpl
2. 获取用户列表
【注意】SQL分页LIMIT使用方法
-
UserDao
-
UserDaoImpl
这次的代码与上面查询用户数量的代码开始有大量重复
主要添加了分页的代码:
-
由于查询用户列表的方法参数多了 当前页currentPageNo、每页用户数pageSize这两个参数
-
通过这两个参数要指定到表中具体查询的位置
【比如】
currentPageNo 表中起始行 开始pageSize行 1 0 0 1 2 3 4 2 5 5 6 7 8 9 3 10 10 11 12 13 14 第n行 (n-1) * pageSize 从起始行开始pageSize行 -
结合SQL中的LIMIT限定查询表达,两个参数下:
- 第一参数就是表中起始行:(currentPageNo-1)* pageSize
- 从起始行开始检索多少行: pageSize
//条件3: 指定分页 sql.append(" order by creationDate DESC limit ?,?");//DESC:降序 //因为limit带2个值时:第一个数是开始位置,第二个数是要检索的行数(SQL中检索出来的第一行为行0,而不是行1) //输入的currenPageNo--------->页数 //(currentPageNo - 1) * pageSize 后,currenPageNo等于页数对应表中的起始位置(行) currentPageNo = (currentPageNo - 1) * pageSize; list.add(currentPageNo); //要开始检索的位置 list.add(pageSize); //从上述位置开始检索所少个 System.out.println("sql ----- >" + sql.toString());//打印出来看看 Object[] params = list.toArray(); resultSet = baseDao.execute(connection, sql.toString(), params, resultSet, preparedStatement);
-
-
UserService
-
UserServiceImpl
与获取用户数量的Service层变化不大
3. 获取角色列表
为了我们职责统一,可以把角色的操作单独放在一个包中和pojo对应
获取角色列表的原因是:在用户角色选择栏里有所有用户角色的信息
-
UserDao
-
UserDaoImpl
读取角色表中的所有信息
select * from smbms_role
直接返回一个Role列表
public List<Role> getRoleList(Connection connection) throws SQLException { PreparedStatement preparedStatement = null; ResultSet resultSet = null; List<Role> roleList = new ArrayList<Role>(); if(connection != null){ String sql = "select * from smbms_role"; Object [] params = {}; resultSet = baseDao.execute(connection, sql, params, resultSet, preparedStatement); while(resultSet.next()){ Role role = new Role(); role.setId(resultSet.getInt("id")); role.setRoleCode(resultSet.getString("roleCode")); role.setRoleName(resultSet.getString("roleName")); roleList.add(role); } baseDao.closeResource(null, preparedStatement, resultSet); } return roleList; }
-
UserService
-
UserServiceImpl
4. 用户显示的Servlet
- 获取用户前端的数据(查询)
- 判断请求是否需要执行,看参数的值判断
- 为了实现分页,需要计算出当前页面和总页面,页面大小
- 用户列表展示
- 返回前端
//重点、难点
public void query(HttpServletRequest req, HttpServletResponse resp){
//从前端获取数据
String queryUserName = req.getParameter("queryname");
String temp = req.getParameter("queryUserRole");
String pageIndex = req.getParameter("pageIndex");
int queryUserRole = 0;//刚进入页面时没有选择用户角色条件,默认为0
//实例化ServiceImpl
UserServiceImpl userService = new UserServiceImpl();
//第一次走这个请求,一定是第一页,页面大小是固定的,所以先给默认值
int pageSize = Constants.pageSize;//设置页面容量
int currentPage = 1;//当前页码
System.out.println("queryUserName servlet--------"+queryUserName);
System.out.println("queryUserRole servlet--------"+queryUserRole);
System.out.println("query pageIndex--------- > " + pageIndex);
//根据前端输入,再修改默认值
if(queryUserName == null){
queryUserName = "";//一开始没有输入用户名,默认为""
}
if(temp != null && !temp.equals("")){
queryUserRole = Integer.parseInt(temp); //给查询赋值! 0,1,2,3
}
if(pageIndex != null){
currentPage = Integer.parseInt(pageIndex);
}
//获取用户总人数(分页: 上一页、下一页)
int userCount = userService.getUserCount(queryUserName, queryUserRole);
//实例化分页对象
PageSupport pageSupport = new PageSupport();
pageSupport.setCurrentPageNo(currentPage);
pageSupport.setPageSize(pageSize);
pageSupport.setTotalCount(userCount);
//获取总页数
int pageTotalPageCount = pageSupport.getTotalPageCount();
//控制首页和尾页
//如果页面小于1,就显示第一页的东西
if(currentPage < 1){
currentPage = 1;
}else if(currentPage > pageTotalPageCount){//如果当前页面大于最后一页:
currentPage = pageTotalPageCount;
}
//获取当页所有用户列表
List<User> userList = userService.getUserList(queryUserName, queryUserRole, currentPage, pageSize);
for (User user : userList) {
System.out.println(user.getUserName());
}
req.setAttribute("userList", userList);
//获去所有用户角色信息
RoleServiceImpl roleService = new RoleServiceImpl();
List<Role> roleList = roleService.getRoleList();
req.setAttribute("roleList", roleList);
req.setAttribute("totalCount", userCount);
req.setAttribute("currentPageNo", currentPage);
req.setAttribute("totalPageCount", pageTotalPageCount);
//返回前端
try{
req.getRequestDispatcher("userlist.jsp").forward(req, resp);
}catch (ServletException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
}
5. 增加用户
dao层:注意SQL的insert写法
public int insertUser(Connection connection, User user) throws SQLException {
PreparedStatement preparedStatement = null;
int res = 0;
if(connection != null && user != null){
String sql = "insert into smbms_user (userCode, userName, userPassword, gender, birthday, phone, address, userRole, creationDate, createdBy) values(?,?,?,?,?,?,?,?,?,?)";
String userCode = user.getUserCode();
String userName = user.getUserName();
String userPassword = user.getUserPassword();
int gender = user.getGender();
Date birthday = user.getBirthday();
String phone = user.getPhone();
String address = user.getAddress();
int userRole = user.getUserRole();
Date creationDate = user.getCreationDate();
Integer createdBy = user.getCreatedBy();
Object []params = {userCode, userPassword, gender, birthday, phone, address, userRole, creationDate, createdBy};
res = baseDao.execute(connection, sql, params, preparedStatement);
baseDao.closeResource(null, preparedStatement, null);
}
return res;
}
Service层:
【注意】JDBC事务管理、返回值类型定位boolean类型(是否成功add)
public boolean insertUser(User user) {
Connection connection = null;
boolean flag = false;
try{
connection = baseDao.getConnection();
connection.setAutoCommit(false);//开启JDBC事务管理
int res = userDao.insertUser(connection, user);
connection.commit();
if(res > 0){
flag = true;
System.out.println("add success!");
}else{
System.out.println("add failed!");
}
}catch (SQLException e){
e.printStackTrace();
try{
System.out.println("rollback==================");
connection.rollback();
}catch (SQLException e1){
e1.printStackTrace();
}
}finally{
baseDao.closeResource(connection, null, null);
}
return flag;
}
Servlet层
【注意】
- birthday字符串到Date类型的转换方式
public void add(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
String userName = req.getParameter("userName");
String userCode = req.getParameter("userCode");
String userPassword = req.getParameter("userPassword");
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.setGender(Integer.parseInt(gender));
//获得SimpleDateFormat类,我们转换为yyyy-MM-dd的时间格式
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
try{
//使用SimpleDateFormat的parse()方法生成Date
Date date = sf.parse(birthday);
user.setBirthday(date);
}catch (ParseException e){
e.printStackTrace();
}
user.setPhone(phone);
user.setAddress(address);
user.setUserRole(Integer.parseInt(userRole));
user.setCreationDate(new Date());
user.setCreatedBy(((User)req.getSession().getAttribute(Constants.USER_SESSION)).getId());
UserServiceImpl userService = new UserServiceImpl();
if(userService.insertUser(user)){
System.out.println("保存成功");
resp.sendRedirect(req.getContextPath() + "/jsp/user.do?method=query");
}else {
System.out.println("保存失败");
req.getRequestDispatcher("useradd.jsp").forward(req, resp);
}
}
【注意】重定向url问题
保存成功,重定向至req.getContextPath() + "/jsp/user.do?method=query"
,而不是到req.getContextPath() + "/jsp/userlist.jsp"
可能是应为,直接跳转到jsp页面,并没有触发到form表单的action,所以跳转到的界面没有用户列表显示。
1、 userlist.jsp中提交表单时发送url为:req.getContextPath() + "/jsp/user.do?method=query"
,即提交表单时向此url发送表单数据。而此form没有submit提交键,而是从head.jsp中<a href…触发提交(提交userlist.jsp的表单),进而进入Servlet进行处理后返回userlist.jsp,此时用户信息就显示出来了。
2、 由1可知,重定向到req.getContextPath() + "/jsp/user.do?method=query"
就可以完成form表单的提交,Servlet提取到后台信息,在重定向至userlist.jsp。就可以跳转到右用户信息的表单了。
测试时遇见问题:
(前端)用户添加页面
【注意】用户角色一栏弹不出选项?
起初以为是jsp中没有配置,而roleLIst已经在js中配置过了,js中的method=getrolelist 。所以原因是发现到了Servlet中买有写获取角色列表的方法,导致js中的ajax请求在后端拿不到rolelist信息,所以最后其补充。
js:
/*获取rolelist*/
$.ajax({
type:"GET",//请求类型
url:path+"/jsp/user.do",//请求的url
data:{method:"getrolelist"},//请求参数
dataType:"json",//ajax接口(请求url)返回的数据类型
success:function(data){//data:返回数据(json对象)
if(data != null){
userRole.html("");
var options = "<option value=\"0\">请选择</option>";
for(var i = 0; i < data.length; i++){
//alert(data[i].id);
//alert(data[i].roleName);
options += "<option value=\""+data[i].id+"\">"+data[i].roleName+"</option>";
}
userRole.html(options);
}
},
error:function(data){//当访问时候,404,500 等非200的错误状态码
validateTip(userRole.next(),{"color":"red"},imgNo+" 获取用户角色列表error",false);
}
});
userServlet:
//获取角色列表
private void getrolelist(HttpServletRequest req, HttpServletResponse resp) {
RoleServiceImpl roleService = new RoleServiceImpl();
List<Role> roleList = null;
roleList = roleService.getRoleList();
resp.setContentType("application/json");
try{
PrintWriter writer = resp.getWriter();
writer.write(JSONArray.toJSONString(roleList));
System.out.println(JSONArray.toJSONString(roleList));
writer.flush();
writer.close();
}catch (IOException e){
e.printStackTrace();
}
}
【注意】将list转换为json的方式
【注意】提交保存时,没有反应。
控制台报错:
可知是userCode信息输入的问题
经查到定位到问题错在处:
访问url相当于: //path + /jsp/user.do?method=ucexist&userCode=userCode.val();
前端通过ajax技术使用userCode查询数据库中已有同样userCode的用户数量,如果数量>0,就代表已经该userCode已经使用过了,并前端给予提示。
Servlet:
响应类型得用ajax指定的json类型返回!
//判断用户账号是否可用
public void userCodeExist(HttpServletRequest req, HttpServletResponse resp){
String userCode = req.getParameter("userCode");
User user = null;
Map<String, String> map = new HashMap<String, String>();
if(StringUtils.isNullOrEmpty(userCode)){
map.put("userCode", "exist");
}else{
UserServiceImpl userService = new UserServiceImpl();
user = userService.selectUserCodeExist(userCode);
if(user != null){
map.put("userCode", "exist");
}else {
map.put("userCode", "noexist");
}
}
try{
resp.setContentType("application/json");
PrintWriter writer = resp.getWriter();
writer.write(JSONArray.toJSONString(map));
writer.flush();
writer.close();
}catch (IOException e){
e.printStackTrace();
}
}
6. 删除用户
-
找到前端代码
<span><a class="deleteUser" href="javascript:;" userid=${user.id } username=${user.userName }><img src="${pageContext.request.contextPath }/images/schu.png" alt="删除" title="删除"/></a></span>
function deleteUser(obj){ $.ajax({ type:"GET", url:path+"/jsp/user.do", data:{method:"deluser",uid:obj.attr("userid")}, dataType:"json", success:function(data){ if(data.delResult == "true"){//删除成功:移除删除行 cancleBtn(); obj.parents("tr").remove(); }else if(data.delResult == "false"){//删除失败 //alert("对不起,删除用户【"+obj.attr("username")+"】失败"); changeDLGContent("对不起,删除用户【"+obj.attr("username")+"】失败"); }else if(data.delResult == "notexist"){ //alert("对不起,用户【"+obj.attr("username")+"】不存在"); changeDLGContent("对不起,用户【"+obj.attr("username")+"】不存在"); } }, error:function(data){ //alert("对不起,删除失败"); changeDLGContent("对不起,删除失败"); }
-
在UserServlet中编写deleteUser方法
public void deleteUser(HttpServletRequest req, HttpServletResponse resp){
String userid = req.getParameter("uid");
int id = 0;
id = Integer.parseInt(userid);
Map<String, String> map = new HashMap<String, String>();
if(id <= 0){
map.put("delResult", "notexist");
}else{
UserServiceImpl userService = new UserServiceImpl();
if(userService.deleteUser(id)){
map.put("delResult", "true");
System.out.println("删除完成!");
}else{
map.put("delResult","false");
System.out.println("删除失败!");
}
}
try{
resp.setContentType("application/json");
PrintWriter writer = resp.getWriter();
writer.write(JSONArray.toJSONString(map));
}catch (IOException e){
e.printStackTrace();
}
}
7. 修改用户信息
前端页面:红圈按钮即为修改案件
对应userlist.jsp文件中的这串代码:
<span><a class="modifyUser" href="javascript:;" userid=${user.id } username=${user.userName }><img src="${pageContext.request.contextPath }/images/xiugai.png" alt="修改" title="修改"/></a></span>
userlist.js中:
$(".modifyUser").on("click",function(){
var obj = $(this);
window.location.href=path+"/jsp/user.do?method=modify&uid="+ obj.attr("userid");
});
触发访问资源路径url:path +"/jsp/user.do?method=modify&uid=userid"
对应servlet如下:
Servlet中选用getUserById方法获取id指定的用户信息,最终将user保存到请求域中
.....
}else if(method != null && method.equals("modify")){
this.getUserById(req, resp, "usermodify.jsp");
}
.....
public void getUserById(HttpServletRequest req, HttpServletResponse resp, String url) throws ServletException, IOException {
String id = req.getParameter("uid");
if(!StringUtils.isNullOrEmpty(id)){
//调用后台方法得到user对象
UserService userService = new UserServiceImpl();
User user = userService.selectUserById(Integer.parseInt(id));
req.setAttribute("user", user);
req.getRequestDispatcher(url).forward(req, resp);//获取到要修改的用户,跳转到usermodify.jsp界面。
}
}
跳转到usermodify.jsp去执行修改操作,usermodify.jsp页面中起初显示要修改用户的每项信息,在其上修改即可。
usermodify.jsp中的form表单action直接跳转至Servlet中,method的value是modifyexe,对应Servlet中的modify方法。通过此方法来进行修改操作。
Servelt:
//修改用户信息
public void modify(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
String id = req.getParameter("uid");
String userName = req.getParameter("userName");
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");
System.out.println("我读取到了信息");
User user = new User();
user.setId(Integer.parseInt(id));
user.setUserName(userName);
user.setGender(Integer.parseInt(gender));
try{
user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(birthday));
}catch (ParseException e){
e.printStackTrace();
}
user.setPhone(phone);
user.setAddress(address);
user.setUserRole(Integer.parseInt(userRole));
user.setModifyBy(((User)(req.getSession().getAttribute(Constants.USER_SESSION))).getId());
user.setModifyDate(new Date());
System.out.println("我准备将user信息发送到Service层");
UserServiceImpl userService = new UserServiceImpl();
if (userService.modifyUser(user)) {
resp.sendRedirect(req.getContextPath() + "/jsp/user.do?method=query");
}else{
req.getRequestDispatcher("usermodify.jsp").forward(req, resp);
}
}
Service:
//修改用户信息
public boolean modifyUser(User user) {
Connection connection = null;
int res = 0;
boolean flag = false;
try{
connection = baseDao.getConnection();
res = userDao.modify(connection, user);
if(res > 0){
flag = true;
}
}catch (Exception e){
e.printStackTrace();
}finally{
baseDao.closeResource(connection, null, null);
}
return flag;
}
Dao:
public int modify(Connection connection, User user) throws Exception {
// TODO Auto-generated method stub
int flag = 0;
PreparedStatement pstm = null;
if(null != connection){
String sql = "update smbms_user set userName=?,"+
"gender=?,birthday=?,phone=?,address=?,userRole=?,modifyBy=?,modifyDate=? where id = ? ";
Object[] params = {user.getUserName(),user.getGender(),user.getBirthday(),
user.getPhone(),user.getAddress(),user.getUserRole(),user.getModifyBy(),
user.getModifyDate(),user.getId()};
flag = baseDao.execute(connection, sql, params, pstm);
baseDao.closeResource(null, pstm, null);
}
return flag;
}
【注意】前端接口的作用和其跳转去向,以及其所对接的后端接口处理功能。
modifyUser(User user) {
Connection connection = null;
int res = 0;
boolean flag = false;
try{
connection = baseDao.getConnection();
res = userDao.modify(connection, user);
if(res > 0){
flag = true;
}
}catch (Exception e){
e.printStackTrace();
}finally{
baseDao.closeResource(connection, null, null);
}
return flag;
}
Dao:
```java
public int modify(Connection connection, User user) throws Exception {
// TODO Auto-generated method stub
int flag = 0;
PreparedStatement pstm = null;
if(null != connection){
String sql = "update smbms_user set userName=?,"+
"gender=?,birthday=?,phone=?,address=?,userRole=?,modifyBy=?,modifyDate=? where id = ? ";
Object[] params = {user.getUserName(),user.getGender(),user.getBirthday(),
user.getPhone(),user.getAddress(),user.getUserRole(),user.getModifyBy(),
user.getModifyDate(),user.getId()};
flag = baseDao.execute(connection, sql, params, pstm);
baseDao.closeResource(null, pstm, null);
}
return flag;
}
【注意】前端接口的作用和其跳转去向,以及其所对接的后端接口处理功能。
我只完成了用户功能方面,以此练习自己的Servlet能力。