机试挑战
需求分析
开发环境:IntelliJ IDEA + JDK1.8 + Tomcat8.5 + Maven + SVN + MySql
采用技术:Spring + SpringMVC +Mybatis + Shiro + html + css
功能:
请编写一个Web程序,完成对员工信息的管理,实现功能如下:
1.登录;(完成)
2.查看所有员工列表;(完成)
3.查看员工详细信息;(完成)
4.添加员工信息;(完成)
5.修改员工信息;(完成)
6.删除员工信息;(完成)
大概内容:
1.登录,添加,修改,删除操作使用AOP将操作日志入库保存;(完成)
2.全部请求使用Ajax请求方式;(部分完成)
3.前端框架自行使用;(完成)
4.数据库自行设计;(完成)
5.Session管理交由Shiro管理;
6.使用log4j进行日志文件保存;(完成)
7.使用nginx进行管理,需要实现服务停止时提示维护页面
简介
实际主要技术栈
SSM + JQuery + bootstrap
访问流程
管理员账号目前只有一个, 并对其密码使用MD5加密
账号: admin
密码: 123456
普通员工不能进行登录访问,更不能对员工信息进行操作
演示
显示所有员工
添加员工
查看信息
数据库设计
管理员table
create table admin
(
name varchar(20) primary key,
password varchar(32) not null
)
comment '管理员';
insert into admin values('admin',MD5('123456'));
员工table
create table employee
(
id smallint primary key auto_increment,
name varchar(20) not null,
sex smallint not null,
entry date not null,
depart varchar(20) not null,
phone varchar(11) not null
);
comment '员工';
insert into employee(name, sex, entry, depart, phone) VALUES ('listen', 0, CURDATE(), '开发部', '12345677889');
POJO对象
管理员
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Admin implements Serializable {
private String name;
private String password;
}
普通员工
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee implements Serializable {
private int id;
private String name;
private int sex;
private Date entry;
private String depart;
private String phone;
public Employee(String name, int sex, String depart, String phone) {
this.name = name;
this.sex = sex;
this.depart = depart;
this.phone = phone;
}
}
dao层服务
管理员操作接口
public interface AdminMapper {
Admin query(@Param("name") String name);
}
<?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.employee.dao.AdminMapper">
<select id="query" parameterType="string" resultType="admin">
select * from admin where name=#{name};
</select>
</mapper>
普通员工操作接口
public interface EmployeeMapper {
List<Employee> select();
List<Employee> selectLike(@Param("keyWords") String keyWords);
Employee query(@Param("id") int id);
int add(Employee employee);
int delete(@Param("id") int id);
int update(Map<String, Object> map);
}
<?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.employee.dao.EmployeeMapper">
<select id="select" resultType="employee">
select * from employee;
</select>
<select id="query" resultType="employee" parameterType="_int">
select * from employee where id=#{id};
</select>
<insert id="add" parameterType="employee">
insert into employee(name, sex, entry, depart, phone)
VALUES (#{name}, #{sex}, CURDATE(), #{depart}, #{phone});
</insert>
<delete id="delete" parameterType="_int">
delete from employee where id=#{id};
</delete>
<update id="update" parameterType="map">
update employee
<set>
<if test="name != null">
name=#{name},
</if>
<if test="sex != null">
sex=#{sex},
</if>
<if test="depart != null">
depart=#{depart},
</if>
<if test="phone != null">
phone=#{phone}
</if>
</set>
where id=#{id}
</update>
<select id="selectLike" resultType="employee" parameterType="string">
select * from employee where name like #{keyWords};
</select>
</mapper>
Service服务
AdminServiceImpl
public interface AdminService {
Admin query(String name);
}
public class AdminServiceImpl implements AdminService {
AdminMapper adminMapper;
public void setAdminMapper(AdminMapper adminMapper) {
this.adminMapper = adminMapper;
}
/**
* 按名字查询管理员
* @param name
* @return
*/
@Override
public Admin query(String name) {
return adminMapper.query(name);
}
}
EmployeeServiceImpl
public interface EmployeeService {
List<Employee> select();
Employee query(int id);
int add(Employee employee);
int delete(int id);
int update(Map<String, Object> map);
List<Employee> selectLike(String keyWords);
}
public class EmployeeServiceImpl implements EmployeeService {
EmployeeMapper employeeMapper;
public void setEmployeeMapper(EmployeeMapper employeeMapper) {
this.employeeMapper = employeeMapper;
}
/**
* 查询所有员工
* @return
*/
@Override
public List<Employee> select() {
return employeeMapper.select();
}
/**
* 按id查找员工
* @param id
* @return
*/
@Override
public Employee query(int id) {
return employeeMapper.query(id);
}
/**
* 添加员工
* @param employee
* @return
*/
@Override
public int add(Employee employee) {
return employeeMapper.add(employee);
}
/**
* 按照id编号删除一个员工
* @param id
* @return
*/
@Override
public int delete(int id) {
return employeeMapper.delete(id);
}
/**
* 修改员工信息, map中存储要修改的值
* @param map
* @return
*/
@Override
public int update(Map<String, Object> map) {
return employeeMapper.update(map);
}
/**
* 支持模糊查询员工
* @param keyWords
* @return
*/
@Override
public List<Employee> selectLike(String keyWords) {
return employeeMapper.selectLike(keyWords);
}
}
单元测试
管理员接口
public class AdminServiceImplTest extends TestCase {
public void testQuery() throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");
AdminService adminService = applicationContext.getBean("adminServiceImpl", AdminService.class);
Admin admin = adminService.query("admin");
System.out.println(MD5Utils.verify("123456", admin.getPassword()));
}
}
员工接口
public class EmployeeServiceImplTest extends TestCase {
private static final EmployeeService employeeService;
static {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");
employeeService = applicationContext.getBean("employeeServiceImpl", EmployeeService.class);
}
public void testSelect() {
for (Employee employee : employeeService.select()) {
System.out.println(employee);
}
}
/* public Employee(String name, int sex, String depart, String phone) {*/
public void testQuery() {
Employee employee = employeeService.query(2);
System.out.println(employee);
}
public void testAdd() {
Employee employee = new Employee("bike", 1, "人事部", "11111111111");
employeeService.add(employee);
}
public void testDelete() {
employeeService.delete(2);
}
public void testUpdate() {
Map<String, Object> map = new HashMap<>();
map.put("id", 3);
/* map.put("name", "faker");*/
map.put("sex", 0);
map.put("depart", "管理部");
map.put("phone", "99999999999");
System.out.println(employeeService.update(map));
}
public void testSelectLike() {
Logger logger = Logger.getLogger(EmployeeServiceImplTest.class);
logger.debug("hahaha");
for (Employee employee : employeeService.selectLike("%张%")) {
System.out.println(employee);
}
}
}
配置
实现拦截器
<!--关于拦截器的配置-->
<mvc:interceptors>
<mvc:interceptor>
<!--/** 包括路径及其子路径-->
<!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
<!--/admin/** 拦截的是/admin/下的所有-->
<mvc:mapping path="/**"/>
<!--bean配置的就是拦截器-->
<bean class="com.employee.config.InterceptorConfig"/>
</mvc:interceptor>
</mvc:interceptors>
public class InterceptorConfig implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
//如果已经登录过就放行
//如果访问的是login也放行
//其他的就拦截
if (httpServletRequest.getSession().getAttribute("admin") != null) {
return true;
}
if (httpServletRequest.getRequestURI().contains("login")) {
return true;
}
//不能放行, 返回到首页
httpServletResponse.sendRedirect("./index.jsp");
return false;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
AOP实现前置通知输出数据库操作日志
<!--实现aop日志入库-->
<bean id="adminBeforeLogConfig" class="com.employee.config.AdminBeforeLogConfig"/>
<bean id="employeeBeforeLog" class="com.employee.config.EmployeeBeforeLog"/>
<aop:config>
<!--配置被代理类的切入点, 注意execution的使用规则第一个* 代表任意返回类型,
第二个参数表示切入点, .*表示这个类的全部方法, ..表示参数是任意的-->
<aop:pointcut id="pointcut" expression="execution(* com.employee.service.AdminServiceImpl.*(..))"/>
<aop:advisor advice-ref="adminBeforeLogConfig" pointcut-ref="pointcut"/>
</aop:config>
<aop:config>
<!--配置被代理类的切入点, 注意execution的使用规则第一个* 代表任意返回类型,
第二个参数表示切入点, .*表示这个类的全部方法, ..表示参数是任意的-->
<aop:pointcut id="pointcut2" expression="execution(* com.employee.service.EmployeeServiceImpl.*(..))"/>
<aop:advisor advice-ref="employeeBeforeLog" pointcut-ref="pointcut2"/>
</aop:config>
public class AdminBeforeLogConfig implements MethodBeforeAdvice {
static Logger logger = Logger.getLogger(AdminBeforeLogConfig.class);
@Override
public void before(Method method, Object[] objects, Object o) {
logger.error("方法名:" + method.getName() + " 参数:"+ Arrays.toString(objects)
+" 目标:"+o);
}
}
public class EmployeeBeforeLog implements MethodBeforeAdvice {
static Logger logger = Logger.getLogger(EmployeeBeforeLog.class);
@Override
public void before(Method method, Object[] objects, Object o) {
logger.error("方法名:" + method.getName() + " 参数:"+ Arrays.toString(objects)
+" 目标:"+o);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fzqWneVd-1606400193775)(C:\Users\Huawei\AppData\Roaming\Typora\typora-user-images\1606398655371.png)]
controller
管理员controller
@Controller
public class AdminController {
@Autowired
AdminService adminService;
/**
* 实现登录
* @param request
* @return
* @throws UnsupportedEncodingException
*/
@RequestMapping(value = "/login", produces="text/html;charset=utf-8")
@ResponseBody
public String login(HttpServletRequest request) throws UnsupportedEncodingException {
request.setCharacterEncoding("UTF-8");
//获取数据
String name = request.getParameter("name");
String password = request.getParameter("password");
if (name == null || name.length() == 0 || password == null || password.length() == 0) {
return "请填写账号和密码";
}
//查找用户
Admin admin = adminService.query(name);
if (admin == null) {
return "账号或密码错误";
}
//密码检验
boolean verify;
try {
verify = MD5Utils.verify(password, admin.getPassword());
} catch (Exception e) {
return "MD5检验异常";
}
if (verify) {
//创建session保存
HttpSession session = request.getSession();
session.setAttribute("admin", admin);
}
System.out.println("[DEBUG]verify " + verify);
return verify ? "OK":"账号或密码错误";
}
/**
* 实现注销
* @param session
* @param response
* @throws IOException
*/
@RequestMapping("/down")
public void down(HttpSession session, HttpServletResponse response) throws IOException {
session.removeAttribute("admin");
response.sendRedirect("./index.jsp");
}
}
员工controller
@Controller
public class EmployeeController {
@Autowired
EmployeeService employeeService;
/**
* 获取所有员工数据, 返回modelAndView
* @param model
* @return
*/
@RequestMapping("/success")
public String success(Model model) {
System.out.println("[DEBUG] success");
model.addAttribute("list", employeeService.select());
return "showAll";
}
/**
* 添加一个员工
* @param name
* @param sex
* @param depart
* @param phone
* @return
*/
@RequestMapping(value = "/add", produces = "text/html;charset=utf-8")
@ResponseBody
public String add(String name, String sex, String depart, String phone) {
name = name.trim();
sex = sex.trim();
depart = depart.trim();
phone = phone.trim();
//检查合法性
String error = MessageCheck.checkAll(name, sex, depart, phone);
if (error.length() > 0) {
return error;
}
//进行数据库操作实现增加
int sexNum = 1;
if ("girl".equalsIgnoreCase(sex) || "女".equals(sex)) {
sexNum = 0;
}
Employee employee = new Employee(name, sexNum, depart, phone);
employeeService.add(employee);
return "OK";
}
/**
* 方便页面跳转
* @return
*/
@RequestMapping("/addEmployee")
public String newEmployee() {
return "add";
}
/**
* 支持模糊查询
* @param keyWords
* @param model
* @return
*/
@RequestMapping("/findLike")
public String findLike(String keyWords, Model model) {
List<Employee> list = employeeService.selectLike("%" + keyWords + "%");
if (list.size() == 0) model.addAttribute("ERROR", "未找到");
model.addAttribute("list", list);
return "showAll";
}
/**
* 根据id得到员工数据, 然后返回修改数据页面
* @param id
* @param model
* @return
*/
@RequestMapping("/update/{id}")
public String update(@PathVariable("id")int id, Model model) {
Employee employee = employeeService.query(id);
model.addAttribute("employee", employee);
return "update";
}
/**
* 执行修改员工数据的操作
* @param id
* @param name
* @param sex
* @param depart
* @param phone
* @return
*/
@RequestMapping(value = "/update", produces = "text/html;charset=utf-8")
@ResponseBody
public String update(int id, String name, String sex, String depart, String phone) {
name = name.trim();
sex = sex.trim();
depart = depart.trim();
phone = phone.trim();
//数据检验
String error = MessageCheck.checkAll(name, sex, depart, phone);
if (error.length() > 0) {
return error;
} else {
int sexNum = 1;
if ("girl".equalsIgnoreCase(sex) || "女".equals(sex)) {
sexNum = 0;
}
Employee query = employeeService.query(id);
Map<String, Object> map = new HashMap<>();
map.put("id", id);
if (!query.getName().equals(name)) map.put("name", name);
if (query.getSex() != sexNum) map.put("sex", sexNum);
if (!query.getDepart().equals(depart)) map.put("depart", depart);
if (!query.getPhone().equals(phone)) map.put("phone", phone);
if (map.size() <= 1) return "OK";
int update = employeeService.update(map);
System.out.println("[DEBUG]update " + update);
return "OK";
}
}
/**
* 查看某个员工的详细信息
* @param employeeId
* @param model
* @return
*/
@RequestMapping(value = "/query")
public String query(int employeeId, Model model) {
Employee employee = employeeService.query(employeeId);
model.addAttribute("employee", employee);
return "detials";
}
/**
* 删除一个员工
* @param employeeId
* @return
*/
@RequestMapping("/delete")
public String delete(int employeeId) {
int delete = employeeService.delete(employeeId);
System.out.println("[DEBUG] " + delete);
return "redirect:/success";
}
}
总结