SSM——用户信息管理系统

SSM——用户信息管理系统

源码链接:用户信息管理系统

1 核心功能
  1. 登录、注册
  2. 添加用户信息
  3. 删除某一个用户信息
  4. 删除选中的用户信息
  5. 分页查询所有用户信息
  6. 模糊查询用户信息
  7. 更新用户信息
2 整体架构:

项目整体基于HTTP协议,前端使用 HTML+CSS+JS 构建页面整体布局,后端采用分层结构,分为Controller层,Service层,Dao层,

采用SpringBoot+SpringMvc+Mybatis来实现,达到在设计上的高内聚低耦合。

在这里插入图片描述
在这里插入图片描述

3 数据库表设计
drop database if exists usermanager;
create DATABASE if not exists usermanager character set utf8;
use usermanager;

drop table if exists usermessage;
create table `usermessage` (
`id` INT PRIMARY KEY auto_increment,
`name` varchar (60),
`username` varchar (60) default 'bit',
`password` varchar (60) default '123456',
`gender` varchar (4),
`age` int,
`address` varchar (90),
`qq` varchar (20),
`email` varchar (30)
);

INSERT INTO usermessage VALUES(1,'张飞','zhangfei','123','男',18,'成
都','1262913815','126@qq.com');
INSERT INTO usermessage VALUES(2,'关羽','guanyu','1234','男',18,'陕
西','1262913816','1262@qq.com');
INSERT INTO usermessage VALUES(3,'张三','zhangsan','1235','女',19,'陕
西','1262913817','1263@qq.com');
4 创建实体类(POJO)

User: 用户信息

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int id;
    private String name;
    private String username;
    private String password;
    private String gender;
    private int age;
    private String address;
    private String qq;
    private String email;
}

PageBean:用来返回给前端信息

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageBean<T> {
    private int totalCount; //总记录数
    private int totalPage; //总页码
    private List<T> list; //每页中的数据
    private int currentPage;//当前页码
    private int rows; //每页的记录数
}
5 UserMapper接口
@Service
public interface UserMapper {
    //注册
    int register(User registerUser);
    
    //登录
    User login(User loginUser);
    
   //增加用户
    int add(User addUser);
    
    //删除
    int delete( int id);
    
   //根据id查找
    User find(int id);
    
    //更新
    int update(User updateUser);

    //查询共有多少条记录
    int findAllRecord(HashMap<String,Object> map);

    //分页查询 map:包含:currentPage、rows、name、address、email
    List<User> findByPage(HashMap<String,Object> map);

}

6 编写UserMapper.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        
<mapper namespace="com.glp.dao.UserMapper">

    <!--注册-->
    <insert id="register" parameterType="user">
        insert into usermessage(name,username,password,gender,age,address,qq,email) values(#{name},#{username},#{password},#{gender},#{age},#{address},#{qq},#{email})
    </insert>
    
    <!--分页查询-->
    <!--select * from usermessage where 1=1 and name like ? and address like ? and email like ?
    limit ?,?-->
    <select id="findByPage" parameterType="map" resultType="user">
        select * from usermessage
        <where>
            <if test="name!=null">
                name like concat('%',#{name},'%')
            </if>
            <if test="address!=null">
                and address like concat('%',#{address},'%')
            </if>
            <if test="email!=null">
                and email like concat('%',#{email},'%')
            </if>
        </where>
        limit #{startIndex},#{rows}
    </select>
</mapper>

注:

  • 分页查询时采用了动态SQL,并且这里需要注意一下模糊查询时的sql注入问题,
    编写动态SQL时,最好先将原SQL写出来。

  • 为了方便分页查询时的传参,这里采用了HashMap进行传参

7 配置SpringBoot (application.properties)
debug=true
# 设置打印日志的级别,及打印sql语句
logging.level.root=INFO
logging.level.druid.sql.Statement=ERROR
logging.level.com.glp=DEBUG

#springmvc配置参数
spring.mvc.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8

#配置数据库连接池初始化参数
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/usermanager?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=mysql

#给实体类起别名,别名默认为原名小写
mybatis.type-aliases-package = com.glp.pojo
#指明mapper.xml文件在哪里
mybatis.mapper-locations=classpath:mapper/*.xml 

#自定义根路径
server.servlet.context-path:/usermanagers
8 service层设计

service层不仅是对Dao层的直接引用,在这里一般需要做一些逻辑上的处理。
(1)service层接口
service层接口:UserService

@Service
public interface UserService {
    //注册
    int register(User registerUser);

    //登录
    User login(User loginUser);

    //增加用户
    int add(User addUser);

    //删除
    int delete(int id);

    //根据id查找,用来判断user是否存在,如果存在,就继续执行下面的returnFront,及update
    User find(int id);

    //负责将find查到的user,通过session传给前端,在controller中进行处理

    //更新
    int update(User updateUser);

    //查询共有多少条记录
    int findAllRecord(HashMap<String,Object> map);

    //分页查询 map:包含:currentPage、rows、name、address、email
    PageBean<User> findAllByPage(HashMap<String,Object> map);
}

其他的接口基本上都和Dao层接口类似,所以直接调用dao层的接口即可。因此这里我们只讨论分页查询部分,这里采用分页查询时,我们采用findAllByPage对dao层的结果进行逻辑处理.

(2)UserServiceImpl
service层实现类:UserServiceImpl

@Service
public class UserServiceImpl implements UserService{
    @Resource
    private UserMapper userMapper;

    @Override
    public int register(User registerUser) {
        return userMapper.register(registerUser);
    }

    @Override
    public User login(User loginUser) {
        return userMapper.login(loginUser);
    }

    @Override
    public int findAllRecord(HashMap<String,Object> map) {
        return userMapper.findAllRecord(map);
    }

    //在service层做逻辑整合
    @Override
    public PageBean<User> findAllByPage(HashMap<String,Object> map) {
        PageBean<User> pageBean=new PageBean<>();

        int rows = (int)map.get("rows");
        int currentPage = (int)map.get("currentPage");

        //查询当前搜索中共有多少条记录
        int allRecord = findAllRecord(map);

        //计算总共的页数
        int totalPage;
        if(allRecord%rows==0){
            totalPage=allRecord/rows;
        }else{
            totalPage=allRecord/rows+1;
        }

        //分页查询:返回用户数据,及总页数,当前页数,一页的行数。
        int start=(currentPage-1)*rows;
        map.put("startIndex",start);
        List<User> users = userMapper.findByPage(map);
        pageBean.setCurrentPage(currentPage);
        pageBean.setList(users);
        pageBean.setRows(rows);
        pageBean.setTotalCount(allRecord);
        pageBean.setTotalPage(totalPage);
        return pageBean;
    }
}

通过Dao层的findAllRecord(map);来根据前端得到的name,address,email进行模糊查询,用来查出当前条件下查询出的总条数。

这里需要进行逻辑处理,是因为分页查询时,需要知道分页limit起始点startIndex。
同时我们需要计算 总页数 ,以及将分页查询的所有User封装到pageBean中,以在controller层传给前端。

9 Controller层设计

(1)注册,登录,添加,删除单个用户
比较简单,不做讨论

@Controller
public class UserController {
    @Resource
    private UserServiceImpl userService;

    //注册用户
    @RequestMapping("/registerServlet")
    public void register(HttpServletRequest req, HttpServletResponse resp,User u) throws IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=utf-8");
        Writer writer = resp.getWriter();
        int ret =userService.register(u);
        if(ret == 0) {
            System.out.println("注册失败!");
            writer.write("<h2> 注册失败 </h2>" );
        }else {
            System.out.println("注册成功!");
            resp.sendRedirect("/usermanagers/login.html");
        }
    }
     }

(2)修改用户
在这里插入图片描述

修改用户时,在list.html中通过点击修改页面,访问/findUserServlet,查询用户是否存在,如果存在则将用户写入Session中。

 //查看要修改的对象是否存在,如果存在就将该对象存入session中
    @RequestMapping("/findUserServlet")
    public String findIfNeedUpdate(HttpServletRequest req,HttpServletResponse resp,int id) throws UnsupportedEncodingException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");
        User user = userService.find(id);
        if(user == null) {
            System.out.println("没有要修改的对象!");
        }else {
            //将要修改的对象存入session中
            req.getSession().setAttribute("updateUser",user);
            return "redirect:/update.html"; //通过update.html调用updateServlet
        }
        return "redirect:/list.html";
    }

在这里插入图片描述
如果存在该用户,就通过重定向转到update.html页面,在update.html页面通过ajax访问/returnServlet,拿到sessiong中的user信息,将信息返回给前端:
在这里插入图片描述


    //在更新用户的时候,通过访问returnServlet拿到要修改的user对象,并将该对象填入前端界面中
    @RequestMapping("/returnServlet")
    public void returnFront(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");

        Object updateUser = req.getSession().getAttribute("updateUser");

        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(resp.getWriter(),updateUser);
    }

在这里插入图片描述
当点击提交按钮时,会触发ajax访问/updateServlet,进行真正的修改操作:

  //如果该用户存在,就可以通过update.html,进入/updateServlet
    @RequestMapping("/updateServlet")
    public void updateUser(HttpServletRequest req,HttpServletResponse resp,User user) throws IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");

        //还要从session中拿到要修改的id
        User sessionUser = (User)req.getSession().getAttribute("updateUser");
        int id = sessionUser.getId();
        user.setId(id);

        int ret = userService.update(user);
        Map<String,Object> return_map=new HashMap<>();
        if (ret==1){
            return_map.put("msg",true);
        }else{
            return_map.put("msg",false);
        }
        ObjectMapper mapper=new ObjectMapper();
        mapper.writeValue(resp.getWriter(),return_map);
    }

(3)批量删除用户:
在controller层中直接写(不在service层处理),删除选中的所有用户,也是通过service中的delete方法,会将前端传过来的id数组,逐个删除。

    @RequestMapping("/deleteSelectedServlet")
    public void deleteAllSelect(HttpServletRequest req,HttpServletResponse resp) throws IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");

        //获取数组id
        String[] values = req.getParameterValues("id[]");

        int sum=0;
        Map<String,Object> map=new HashMap<>();
        for(int i=0;i<values.length;i++){
            int j = Integer.parseInt(values[i]);
            //调用Service层方法删除
            int delete = userService.delete(j);
            sum=sum+delete;
        }
        if(sum==values.length){
            //证明删除成功
            map.put("msg",true);
        }else {
            map.put("msg",false);
        }
        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(resp.getWriter(),map);
    }

在这里插入图片描述
在这里插入图片描述

查询操作结束后,将选中的id保存到Array数组中.通过ajax函数返回给后端,在controller层通过req.getParameterValues("id[]");获取id数组,然后调用service层的delete方法,对每个id对应的用户进行删除。

(4)分页模糊查询

    //分页+模糊查询
    @RequestMapping("/findByPageServlet")
    public void findUserByPage(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=utf-8");

        //rows,currentPage,name,address,email
        String rows = req.getParameter("rows");
        String currentPage = req.getParameter("currentPage");
        String name = req.getParameter("name");
        String address = req.getParameter("address");
        String email = req.getParameter("email");

        Integer rowsInt = Integer.valueOf(rows);
        Integer currentPageInt = Integer.valueOf(currentPage);

        HashMap<String,Object> map = new HashMap<String,Object>();
        map.put("rows",rowsInt);
        map.put("currentPage",currentPageInt);
        map.put("name",name);
        map.put("address",address);
        map.put("email",email);
        
        PageBean<User> allByPage = userService.findAllByPage(map);

        //传给前端
        ObjectMapper mapper=new ObjectMapper();
        mapper.writeValue(resp.getWriter(),allByPage);
    }

}

在这里插入图片描述

这里通过map的方式将前端获取的数据传给service层的findAllByPage方法;

点击查询按钮时的操作:
在这里插入图片描述
一开始进入list.html页面时会默认调用下面这个函数,5代表一页的行数,1代表当前页。
在这里插入图片描述
注:
调用完Service层的findAllByPage(map)方法后,会得到前端需要的pageBean当前页面信息,包括用户信息list<User>,总页数totalPage,总记录数totalCount,当前页currentPage,每页行数rows。这里我们通过ObjectMapper以json形式传递给前端。

        ObjectMapper mapper=new ObjectMapper();
        mapper.writeValue(resp.getWriter(),allByPage);
10 用户登录状态拦截——拦截器

项目布置完后,发现我们不用登录也可以直接访问后面的list.html等内容,为此我们选择在项目中增加一个登录验证的部分——拦截器。
在这里插入图片描述
(1)LoginInterceptor
拦截到请求后,检查是否登录过(通过用户的Session信息),登录过则直接返回ture,允许继续访问;没有登录则直接跳转到登录页面。

package com.glp.config;
@Component  //注册到Spring容器中
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        try{
            HttpSession session = request.getSession();
            User user = (User)session.getAttribute("user");
            if(user!=null){
                return true;
            }
            //登录不成功,直接跳转到登录页面
            response.sendRedirect(request.getContextPath()+"/login.html");
        }catch (IOException o){
            o.printStackTrace();
        }
        return false;
    }
}

(2)MyConfig

package com.glp.config;
@Configuration
public class MyConfig implements WebMvcConfigurer {
    @Autowired
    private  LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加一个拦截器
        registry.addInterceptor(loginInterceptor).
        		 // 拦截配置
        		addPathPatterns("/**").
        		
        		// 排除配置
                excludePathPatterns("/**/loginServlet").
                excludePathPatterns("/**/registerServlet").
                excludePathPatterns("/**/login.html").
                excludePathPatterns("/**/register.html").
              
                excludePathPatterns("/**/*.js")
                .excludePathPatterns("/**/*.css").
                excludePathPatterns("/**/*.png").
                excludePathPatterns("/**/*.jpg");
    }

addInterceptor :添加一个拦截器,将拦截下来的路径交给它来处理
addPathPatterns: 拦截配置
excludePathPatterns: 排除配置

排除配置中主要将登录和注册的静态页面Html以及servlet请求中的动态页面都给放行,对于其他的页面都要进行拦截。
在这里插入图片描述
注意我们在拦截时采用了addPathPatterns("/**").,即所有的内容都给拦截包括静态内容,为了简单起见,在这里我们直接采用暴力的方法,对我们所要用到的静态内容,js,css,png,jpg等都给放行,

  • 4
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值