文章目錄
-
- SSM——使用者資訊管理系統
-
-
- 1 核心功能
- 2 整體架構:
- 3 資料庫表設計
- 4 建立實體類(POJO)
- 5 UserMapper接口
- 6 編寫UserMapper.xml
- 7 配置SpringBoot (application.properties)
- 8 service層設計
- 9 Controller層設計
- 10 使用者登入狀态攔截——攔截器
-
SSM——使用者資訊管理系統
源碼連結:使用者資訊管理系統
1 核心功能
- 登入、注冊
- 添加使用者資訊
- 删除某一個使用者資訊
- 删除選中的使用者資訊
- 分頁查詢所有使用者資訊
- 模糊查詢使用者資訊
- 更新使用者資訊
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','[email protected]');
INSERT INTO usermessage VALUES(2,'關羽','guanyu','1234','男',18,'陝
西','1262913816','[email protected]');
INSERT INTO usermessage VALUES(3,'張三','zhangsan','1235','女',19,'陝
西','1262913817','[email protected]');
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等都給放行,