MVC设计模式
概念 - 代码的分层
MVC:项目分层的思想
字母 | 表示 | 层 | 理解 |
---|---|---|---|
M | Modle | 模型层 | 业务的具体实现 |
V | View | 视图层 | 展示数据 |
C | Controller | 控制器层 | 控制业务流程(跳转) |
1.细化理解层数
Controller:控制器层,用于存放Servlet(页面跳转)
View:视图层,用于存放前端页面(jsp)
Modle-Biz/service:逻辑业务层,用于存放业务具体的实现
Modle-Dao/mapper:数据持久层,用于存放操作数据的实现(数据的增删改查)
MVC涉及到了前端,而后端只涉及到了MC
1.1 优缺点
缺点:使用MVC不能减少代码量, 还会增加系统结构和实现的复杂性
优点:整个项目结构清晰,业务逻辑清晰,降低了代码的耦合性,代码的重用性高
注意:一般来说,使用设计模式都会增加代码量
1.2 各层的命名规范
Controller控制器层:controller/servlet/action/web
Modle-Biz 逻辑业务层:service/biz
Modle-Dao 数据持久层:dao/persist/mapper
2.学生管理系统 web2.0 mvc版本
具体的业务逻辑详情请见 Day59 学生管理系统 web1.0(直接使用servlet+jsp写的),v2.0只是使用mvc分层思想进行构造
项目结构:(总结里有展示所有层)
注意:mapper层、service层、controller层
2.1 学生 student
StudentMapper
通过具体的业务,判断需要用到什么增删查改,然后写数据库增删查改的接口,让实现类去实现
public interface StudentMapper {
//添加学生
public void add(String username,String password,String name,String sex,int age,String hobbies,String photo);
//删除学生,通过username
public void delete(String username);
//更新学生的密码,通过username和newPassword
public void update(String username,String newPassword);
//更新学生信息(除了密码),通过username去操作,没有更新照片
public void update(String username,String name,String sex,int age,String hobbies);
//更新学生信息(除了密码),通过username更新,有更新照片
public void update(String username,String name,String sex,int age,String hobbies,String photo);
//获取学生信息,通过username
public Student getStudent(String username);
//获取学生信息,通过username和username
public Student getStudent(String username,String password);
//获取学生的所有集合信息,用于分页,offset--偏移量,count--数据条数
public List<Student> getStudents(int offset,int count);
//获取当前表的总条数
public int getAllCount();
}
StudentMapperImpl
具体操作数据库的增删查改,可以使用自己写的DBUtils 工具类
public class StudentMapperImpl implements StudentMapper {
@Override
public void add(String username, String password, String name, String sex, int age, String hobbies, String photo) {
try {
DBUtils.commonUpdate("insert into student(username,password,name,sex,age,hobbies,photo) values(?,?,?,?,?,?,?)",username,password,name,sex,age, hobbies,photo);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void delete(String username) {
try {
DBUtils.commonUpdate("delete from student where username = ?",username);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void update(String username, String newPassword) {
try {
DBUtils.commonUpdate("update student set password=? where username=?",newPassword,username);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void update(String username, String name, String sex, int age, String hobbies) {
try {
DBUtils.commonUpdate("update student set name=?,sex=?,age=?,hobbies=? where username=?",name,sex,age,hobbies,username);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void update(String username, String name, String sex, int age, String hobbies, String photo) {
try {
DBUtils.commonUpdate("update student set name=?,sex=?,age=?,hobbies=?,photo=? where username=?",name,sex,age,hobbies,photo,username);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public Student getStudent(String username) {
Student student = null;
try {
student = DBUtils.commonQueryObj(Student.class, "select * from student where username = ?", username);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return student;
}
@Override
public Student getStudent(String username, String password) {
Student student = null;
try {
student = DBUtils.commonQueryObj(Student.class, "select * from student where username = ? and password = ?", username, password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return student;
}
@Override
public List<Student> getStudents(int offset, int count) {
List<Student> students = null;
try {
students = DBUtils.commonQueryList(Student.class, "select * from student limit ?,?", offset, count);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return students;
}
@Override
public int getAllCount() {
int allcount = 0;
try {
allcount = DBUtils.getAllCount("student");
} catch (SQLException e) {
throw new RuntimeException(e);
}
return allcount;
}
}
service业务逻辑层
具体的业务流程,存放Servlet
不用进行跳转,在Controller层进行跳转
有返回值的返回true/false就可以了
StudentService
public interface StudentService {
//是否成功注册功能
public boolean isRegister(String username);
//注册功能
public boolean register(HttpServletRequest request, HttpServletResponse response);
//初始化学生信息功能
public void initModify(HttpServletRequest request, HttpServletResponse response);
//修改学生信息功能
public void modify(HttpServletRequest request, HttpServletResponse response);
//获取学生信息列表,方便分页
public void getStudents(HttpServletRequest request, HttpServletResponse response);
//删除学生功能
public void delete(HttpServletRequest request, HttpServletResponse response);
//添加学生的功能
public boolean add(HttpServletRequest request, HttpServletResponse response);
}
StudentServiceImpl
实现 StudentService接口,写具体的业务逻辑
public class StudentServiceImpl implements StudentService {
private StudentMapper studentMapper = new StudentMapperImpl();
//是否成功注册功能
@Override
public boolean isRegister(String username) {
Student student = studentMapper.getStudent(username);
if(student == null){//允许注册
return true;
}
return false;
}
//注册功能(注册表单是二进制流,涉及到了图片上传)
@Override
public boolean register(HttpServletRequest request, HttpServletResponse response) {
ParseRequestData<Student> parseRequestData = ParseRequestDataUtils.parseRequest(request, Student.class, "upload\\student");
Student stu = parseRequestData.getT();
InputStream in = parseRequestData.getIn();
OutputStream out = parseRequestData.getOut();
boolean register = isRegister(stu.getUsername());
if(register){
//将数据插入到学生表中
studentMapper.add(stu.getUsername(),stu.getPassword(),stu.getName(),stu.getSex(),stu.getAge(),stu.getHobbies(),stu.getPhoto());
//将头像存储到本地磁盘
try {
IOUtils.copy(in,out);
in.close();
out.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return true;
}else{
try {
in.close();
out.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
request.setAttribute("msg","注册失败 -- 账号已注册");
return false;
}
}
//初始化学生信息功能
@Override
public void initModify(HttpServletRequest request, HttpServletResponse response) {
String username = request.getParameter("username");
Student student = studentMapper.getStudent(username);
request.setAttribute("student",student);
}
//修改学生信息功能
@Override
public void modify(HttpServletRequest request, HttpServletResponse response) {
ParseRequestData<Student> parseRequestData = ParseRequestDataUtils.parseRequest(request, Student.class, "upload\\student");
Student stu = parseRequestData.getT();
InputStream in = parseRequestData.getIn();
OutputStream out = parseRequestData.getOut();
try {
if(stu.getPhoto() != null){//说明用户修改头像
studentMapper.update(stu.getUsername(),stu.getName(), stu.getSex(), stu.getAge(),stu.getHobbies(),stu.getPhoto());
IOUtils.copy(in,out);//文件复制
}else{
studentMapper.update(stu.getUsername(),stu.getName(), stu.getSex(), stu.getAge(),stu.getHobbies());
}
if(in != null){
in.close();
}
if(out != null){
out.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
String role = (String) request.getSession().getAttribute("role");
if("student".equals(role)){
//更新Session里的数据
request.getSession().setAttribute("name",stu.getName());
//更新Cookie里的数据
response.addCookie(CookieUtils.createCookie("name",stu.getName(),60*60*24*5));
if(stu.getPhoto() != null){
request.getSession().setAttribute("photo",stu.getPhoto());
response.addCookie(CookieUtils.createCookie("photo",stu.getPhoto(),60*60*24*5));
}
}
}
//获取学生信息列表,方便分页
@Override
public void getStudents(HttpServletRequest request, HttpServletResponse response) {
//获取当前页数
int curPage = Integer.parseInt(request.getParameter("curPage"));
//设置URL
String url = "student?action=doGetStudents&curPage=";
//设置当前页的数据条数
int count = 15;
//计算偏移量
int offset = (curPage-1)*count;
//计算总页数
int allCount = studentMapper.getAllCount();
int totalPage = PageUtils.getTotalPage(allCount,count);
//从数据库获取学生的集合
List<Student> students = studentMapper.getStudents(offset,count);
//处理学生集合
List<StudentDto> studentDtos = DtoUtils.studentDtoListHandler(students);
//封装Page对象
Page<StudentDto> page = new Page<>(url, curPage, totalPage, studentDtos);
//将数据存入到请求对象中
request.setAttribute("page",page);
}
//删除学生功能
@Override
public void delete(HttpServletRequest request, HttpServletResponse response) {
String username = request.getParameter("username");
studentMapper.delete(username);
}
//添加学生的功能
@Override
public boolean add(HttpServletRequest request, HttpServletResponse response) {
ParseRequestData<Student> parseRequestData = ParseRequestDataUtils.parseRequest(request, Student.class, "upload\\student");
Student stu = parseRequestData.getT();
InputStream in = parseRequestData.getIn();
OutputStream out = parseRequestData.getOut();
boolean register = isRegister(stu.getUsername());
if(register){
//将数据插入到学生表中
studentMapper.add(stu.getUsername(),stu.getPassword(),stu.getName(),stu.getSex(),stu.getAge(),stu.getHobbies(),stu.getPhoto());
//将头像存储到本地磁盘
try {
IOUtils.copy(in,out);
in.close();
out.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return true;
}else{
try {
in.close();
out.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
request.setAttribute("msg","添加失败 -- 账号已添加");
return false;
}
}
}
ParseRequestDataUtils
package com.qf.utils;
public class ParseRequestDataUtils {
public static <T> ParseRequestData parseRequest(HttpServletRequest request,Class<T> clazz,String path){
ParseRequestData<T> parseRequestData = new ParseRequestData<>();
//创建文件上传工厂类的对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建文件上传类的对象
ServletFileUpload upload = new ServletFileUpload(factory);
HashMap<String, String> map = new HashMap<>();
try {
//解析请求
List<FileItem> list = upload.parseRequest(request);
for (FileItem fileItem : list) {
if(fileItem.isFormField()){//文本数据
String name = fileItem.getFieldName();
String value = fileItem.getString("UTF-8");
String v = map.get(name);
if(v == null){//说明是第一次添加
map.put(name,value);
}else{//不是第一次添加就需要拼接(多选框的情况)
map.put(name,v + "," + value);
}
}else{//二进制数据
//D:\\apache-tomcat-8.0.49\\webapps\\Day23_upload_war_exploded\\upload\\student
//D:\\apache-tomcat-8.0.49\\webapps\\Day23_upload_war_exploded\\upload\\teacher
String realPath = request.getServletContext().getRealPath(path);
//文件存储目录 -- 自定义路径\\用户名
realPath = realPath + File.separator + map.get("username");
File file = new File(realPath);
if(!file.exists()){
file.mkdirs();
}
String fileName = fileItem.getName();//获取文件名
//自定义路径\\用户名\\tx01.jpg
realPath = realPath + File.separator + fileName;//拼接路径
InputStream in = fileItem.getInputStream();
if(in.available() != 0){
FileOutputStream out = new FileOutputStream(realPath);
parseRequestData.setIn(in);
parseRequestData.setOut(out);
map.put("photo",path + File.separator + map.get("username") + File.separator + fileName);
}
}
}
} catch (FileUploadException e) {
throw new RuntimeException(e);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry);
}
T t = null;
try {
t = clazz.newInstance();
//将map中的数据映射到实体类对象中
BeanUtils.populate(t,map);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
}
parseRequestData.setT(t);
return parseRequestData;
}
}
controller
根据每一个前端传过来的action功能来判断跳转
判断功能进行页面跳转
action=“student?action=doRegister”,前端设置路径加上action=xxx功能
Controller进行具体的判断,成功就重定向,失败就转发
@WebServlet("/student")
public class StudentController extends BaseServlet {
private StudentService studentService = new StudentServiceImpl();
//注册功能
public void doRegister(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
boolean register = studentService.register(request, response);
if(register){
response.sendRedirect("login.jsp");
}else{
request.getRequestDispatcher("register.jsp").forward(request,response);
}
}
//初始化修改功能
public void doInitModify(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
studentService.initModify(request,response);
request.getRequestDispatcher("stuInfo.jsp").forward(request,response);
}
//修改功能
public void doModify(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
studentService.modify(request,response);
String role = (String) request.getSession().getAttribute("role");
if("student".equals(role)){
response.sendRedirect("index.jsp");
}else if("teacher".equals(role)){
request.getRequestDispatcher("student?action=doGetStudents&curPage=1").forward(request,response);
}else if("admin".equals(role)){
request.getRequestDispatcher("student?action=doGetStudents&curPage=1").forward(request,response);
}
}
//展示数据功能
public void doGetStudents(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
studentService.getStudents(request,response);
request.getRequestDispatcher("stuList.jsp").forward(request,response);
}
//删除功能
public void doDelete(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
studentService.delete(request,response);
request.getRequestDispatcher("student?action=doGetStudents&curPage=1").forward(request,response);
}
//添加学生功能
public void doAddStu(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
boolean register = studentService.register(request, response);
if(register){
request.getRequestDispatcher("student?action=doGetStudents&curPage=1").forward(request,response);
}else{
request.getRequestDispatcher("stuAdd.jsp").forward(request,response);
}
}
//是否注册学生的提示功能(ajax)
public void isRegister(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
boolean register = studentService.isRegister(username);
String code;
if(register){
code="1";
}else {
code="-1";
}
response.getWriter().write(code);
}
}
BaseServlet
给控制层重写的servlet,以前继承HttpServlet,就会写很多的if-else判断,太麻烦了
package com.qf.servlet;
public class BaseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//url -- http://localhost:8080/Day24_MVC_war_exploded/user?action=doLogin
String action = request.getParameter("action");//doLogin
//获取Controller类的class对象
Class<? extends BaseServlet> clazz = this.getClass();
try {
//根据action获取Controller类对应的方法对象
Method method = clazz.getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
//设置操作权限
method.setAccessible(true);
//调用方法
method.invoke(this,request,response);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
2.2 老师 teacher
TeacherMapper
明确数据库的功能
public interface TeacherMapper {
//添加老师
public void add(String username,String password,String name,String sex,int age,int courseId,String photo);
//删除老师,通过username
public void delete(String username);
//更新老师的密码,通过username和newPassword
public void update(String username,String newPassword);
//更新老师信息(除了密码),通过username去操作,没有更新照片
public void update(String username,String name,String sex,int age,int courseId);
//更新老师信息(除了密码),通过username更新,有更新照片
public void update(String username,String name,String sex,int age,int courseId,String photo);
//获取老师信息,通过username
public Teacher getTeacher(String username);
//获取老师信息,通过username和username
public Teacher getTeacher(String username,String password);
//获取老师的所有集合信息,用于分页,offset--偏移量,count--数据条数
public List<Teacher> getTeachers(int offset,int count);
//获取当前表的总条数
public int getAllCount();
}
StudentMapperImpl
public class StudentMapperImpl implements StudentMapper {
@Override
public void add(String username, String password, String name, String sex, int age, String hobbies, String photo) {
try {
DBUtils.commonUpdate("insert into student(username,password,name,sex,age,hobbies,photo) values(?,?,?,?,?,?,?)",username,password,name,sex,age, hobbies,photo);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void delete(String username) {
try {
DBUtils.commonUpdate("delete from student where username = ?",username);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void update(String username, String newPassword) {
try {
DBUtils.commonUpdate("update student set password=? where username=?",newPassword,username);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void update(String username, String name, String sex, int age, String hobbies) {
try {
DBUtils.commonUpdate("update student set name=?,sex=?,age=?,hobbies=? where username=?",name,sex,age,hobbies,username);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void update(String username, String name, String sex, int age, String hobbies, String photo) {
try {
DBUtils.commonUpdate("update student set name=?,sex=?,age=?,hobbies=?,photo=? where username=?",name,sex,age,hobbies,photo,username);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public Student getStudent(String username) {
Student student = null;
try {
student = DBUtils.commonQueryObj(Student.class, "select * from student where username = ?", username);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return student;
}
@Override
public Student getStudent(String username, String password) {
Student student = null;
try {
student = DBUtils.commonQueryObj(Student.class, "select * from student where username = ? and password = ?", username, password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return student;
}
@Override
public List<Student> getStudents(int offset, int count) {
List<Student> students = null;
try {
students = DBUtils.commonQueryList(Student.class, "select * from student limit ?,?", offset, count);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return students;
}
@Override
public int getAllCount() {
int allcount = 0;
try {
allcount = DBUtils.getAllCount("student");
} catch (SQLException e) {
throw new RuntimeException(e);
}
return allcount;
}
}
业务逻辑层
TeacherService
public interface TeacherService {
public boolean isAdd(String username);
public boolean add(HttpServletRequest request, HttpServletResponse response);
public void initModify(HttpServletRequest request, HttpServletResponse response);
public void modify(HttpServletRequest request, HttpServletResponse response);
public void getTeachers(HttpServletRequest request, HttpServletResponse response);
public void delete(HttpServletRequest request, HttpServletResponse response);
}
TeacherServiceImpl
public class TeacherServiceImpl implements TeacherService {
private TeacherMapper teacherMapper = new TeacherMapperImpl();
private CourseService courseService = new CourseServiceImpl();
@Override
public boolean isAdd(String username) {
Teacher teacher = teacherMapper.getTeacher(username);
if(teacher == null){
return true;
}
return false;
}
@Override
public boolean add(HttpServletRequest request, HttpServletResponse response) {
ParseRequestData<Teacher> parseRequestData = ParseRequestDataUtils.parseRequest(request, Teacher.class, "upload\\teacher");
Teacher t = parseRequestData.getT();
InputStream in = parseRequestData.getIn();
OutputStream out = parseRequestData.getOut();
boolean add = isAdd(t.getUsername());
if(add){
//将数据插入到老师表中
teacherMapper.add(t.getUsername(),t.getPassword(),t.getName(),t.getSex(),t.getAge(),t.getCourseId(),t.getPhoto());
//将头像存储到本地磁盘
try {
IOUtils.copy(in,out);
in.close();
out.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return true;
}else{
try {
in.close();
out.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
request.setAttribute("msg","添加失败 -- 账号已存在");
return false;
}
}
@Override
public void initModify(HttpServletRequest request, HttpServletResponse response) {
String username = request.getParameter("username");
Teacher teacher = teacherMapper.getTeacher(username);
request.setAttribute("teacher",teacher);
courseService.getCourses(request,response);
}
@Override
public void modify(HttpServletRequest request, HttpServletResponse response) {
ParseRequestData<Teacher> parseRequestData = ParseRequestDataUtils.parseRequest(request, Teacher.class, "upload\\teacher");
Teacher tea = parseRequestData.getT();
InputStream in = parseRequestData.getIn();
OutputStream out = parseRequestData.getOut();
try {
if(tea.getPhoto() != null){//说明用户修改头像
teacherMapper.update(tea.getUsername(),tea.getName(), tea.getSex(), tea.getAge(),tea.getCourseId(),tea.getPhoto());
IOUtils.copy(in,out);
}else{
teacherMapper.update(tea.getUsername(),tea.getName(), tea.getSex(), tea.getAge(),tea.getCourseId());
}
if(in != null){
in.close();
}
if(out != null){
out.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
String role = (String) request.getSession().getAttribute("role");
if("teacher".equals(role)){
//更新Session里的数据
request.getSession().setAttribute("name",tea.getName());
//更新Cookie里的数据
response.addCookie(CookieUtils.createCookie("name",tea.getName(),60*60*24*5));
if (tea.getPhoto() != null){
request.getSession().setAttribute("photo",tea.getPhoto());
response.addCookie(CookieUtils.createCookie("photo",tea.getPhoto(),60*60*24*5));
}
}
}
@Override
public void getTeachers(HttpServletRequest request, HttpServletResponse response) {
//获取当前页数
int curPage = Integer.parseInt(request.getParameter("curPage"));
//设置URL
String url = "teacher?action=doGetTeachers&curPage=";
//设置当前页的数据条数
int count = 15;
//计算偏移量
int offset = (curPage-1)*count;
//计算总页数
int allCount = teacherMapper.getAllCount();
int totalPage = PageUtils.getTotalPage(allCount,count);
//从数据库获取老师的集合
List<Teacher> teachers = teacherMapper.getTeachers(offset,count);
//处理老师集合
List<TeacherDto> teacherDtos = DtoUtils.teacherDtoListHandler(teachers);
//封装Page对象
Page<TeacherDto> page = new Page<>(url, curPage, totalPage, teacherDtos);
//将数据存入到请求对象中
request.setAttribute("page",page);
}
@Override
public void delete(HttpServletRequest request, HttpServletResponse response) {
String username = request.getParameter("username");
teacherMapper.delete(username);
}
}
控制器层
TeacherController
@WebServlet("/teacher")
public class TeacherController extends BaseServlet {
private TeacherService teacherService = new TeacherServiceImpl();
public void doInitModify(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
teacherService.initModify(request,response);
request.getRequestDispatcher("teaInfo.jsp").forward(request,response);
}
public void doModify(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {
teacherService.modify(request,response);
request.getRequestDispatcher("teacher?action=doGetTeachers&curPage=1").forward(request,response);
}
public void doGetTeachers(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {
teacherService.getTeachers(request,response);
request.getRequestDispatcher("TeaList.jsp").forward(request,response);
}
public void doDelete(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
teacherService.delete(request,response);
request.getRequestDispatcher("teacher?action=doGetTeachers&curPage=1").forward(request,response);
}
public void doAddTea(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
boolean add = teacherService.add(request,response);
if(add){
request.getRequestDispatcher("teacher?action=doGetTeachers&curPage=1").forward(request,response);
}else{
request.getRequestDispatcher("teaAdd.jsp").forward(request,response);
}
}
}
2.3 用户 user
user是学生和老师的父类,两个都有的功能就写在user里
注意:在数据库中没有user这个表,这是把学生和老师相同的功能提出来了,放在user里
UserService
public interface UserService {
//绘制验证码功能
public void drawCode(HttpServletRequest request, HttpServletResponse response);
//登录功能
public boolean login(HttpServletRequest request, HttpServletResponse response);
//记住我功能
public void rememberMe(HttpServletResponse response,String username,String name,String role,String photo);
//安全退出功能
public void loginOut(HttpServletRequest request, HttpServletResponse response);
//修改验证码功能
public boolean resetPassword(HttpServletRequest request, HttpServletResponse response);
}
UserServiceImpl
public class UserServiceImpl implements UserService {
private StudentMapper studentMapper = new StudentMapperImpl();
private TeacherMapper teacherMapper = new TeacherMapperImpl();
private AdminMapper adminMapper= new AdminMapperImpl();
//绘制验证码功能
@Override
public void drawCode(HttpServletRequest request, HttpServletResponse response) {
//设置宽高的变量
int width = 120;
int height = 30;
//创建画布
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//获取画笔
Graphics graphics = image.getGraphics();
//设置背景色 -- 填充矩形
graphics.setColor(Color.BLUE);
graphics.fillRect(0,0,width,height);
//设置验证码
Random random = new Random();
String[] codes = {"A","B","C","D","E","F","G","H","J","K","M","N","P","Q","R","S","T","U","V","W","X","Y","Z","0","1","2","3","4","5","6","7","8","9"};
Color[] colors = {Color.CYAN,Color.BLACK,Color.GREEN,Color.PINK,Color.WHITE,Color.RED,Color.ORANGE};
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 4; i++) {
String randomCode = codes[random.nextInt(codes.length)];
Color randomColor = colors[random.nextInt(colors.length)];
graphics.setColor(randomColor);//设置随机颜色
graphics.setFont(new Font("宋体",Font.BOLD,20+random.nextInt(10)));//设置字体(字体,样式,大小)
graphics.drawString(randomCode,20+i*25,15+random.nextInt(10));//设置单个验证码
sb.append(randomCode);
}
//将系统验证码设置到Session对象中(会话对象)
HttpSession session = request.getSession();//获取请求里的JSESSIONID(客户端Cookie里的数据),如果没有就创建Session对象,如果有就从Session容器中获取会话对象
session.setAttribute("sysCode",sb.toString());
//设置干扰线
graphics.setColor(Color.YELLOW);
for (int i = 0; i < 3; i++) {
graphics.drawLine(random.nextInt(width),random.nextInt(height),random.nextInt(width),random.nextInt(height));//绘制直线(x1,y1,x2,y2) -> 两点为一线
}
//将画布以jpg形式的文件传出给客户端
try {
ImageIO.write(image,"jpg",response.getOutputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//登录功能
@Override
public boolean login(HttpServletRequest request, HttpServletResponse response) {
//获取请求中的数据
String username = request.getParameter("username");
String password = request.getParameter("password");
String userCode = request.getParameter("userCode");
String rememberMe = request.getParameter("rememberMe");
String role = request.getParameter("role");
//从Session对象中获取系统的验证码
String sysCode = (String) request.getSession().getAttribute("sysCode");
if(sysCode.equalsIgnoreCase(userCode)){//验证码正确
User user = null;
if("student".equals(role)){
user = studentMapper.getStudent(username,password);
}else if("teacher".equals(role)){
user = teacherMapper.getTeacher(username,password);
} else if ("admin".equals(role)) {
user = adminMapper.getAdmin(username, password);
}
if(user != null){//登录成功
//判断是否记住我
if(rememberMe != null){
if("admin".equals(role)){
rememberMe(response,user.getUsername(),user.getPassword(),role);
HttpSession session = request.getSession();
session.setAttribute("username",user.getUsername());
session.setAttribute("password",user.getPassword());
session.setAttribute("role",role);
return true;
}else if ("student".equals(role) || "teacher".equals(role)){
rememberMe(response,user.getUsername(),user.getName() ,role,user.getPhoto());
//将数据存储到Session中
HttpSession session = request.getSession();
session.setAttribute("username",user.getUsername());
session.setAttribute("name",user.getName());
session.setAttribute("role",role);
session.setAttribute("photo",user.getPhoto());
return true;
}
}
if("admin".equals(role)){
HttpSession session = request.getSession();
session.setAttribute("username",user.getUsername());
session.setAttribute("name",user.getPassword());
session.setAttribute("role",role);
}else if ("student".equals(role) || "teacher".equals(role)){
//将数据存储到Session中
HttpSession session = request.getSession();
session.setAttribute("username",user.getUsername());
session.setAttribute("name",user.getName());
session.setAttribute("role",role);
session.setAttribute("photo",user.getPhoto());
}
return true;
}else{//登录失败 -- 账号或密码错误
request.setAttribute("msg","登录失败 -- 账号或密码错误");
return false;
}
}else{//登录失败 - 验证码错误
request.setAttribute("msg","登录失败 -- 验证码错误");
return false;
}
}
//管理员的记住我
private void rememberMe(HttpServletResponse response, String username, String password, String role) {
response.addCookie(CookieUtils.createCookie("username",username,60*60*24*5));
response.addCookie(CookieUtils.createCookie("password",password,60*60*24*5));
response.addCookie(CookieUtils.createCookie("role",role,60*60*24*5));
}
//记住我功能
@Override
public void rememberMe(HttpServletResponse response,String username, String name, String role, String photo) {
//将凭证添加到Cookie中
response.addCookie(CookieUtils.createCookie("username",username,60*60*24*5));
response.addCookie(CookieUtils.createCookie("name",name,60*60*24*5));
response.addCookie(CookieUtils.createCookie("role",role,60*60*24*5));
response.addCookie(CookieUtils.createCookie("photo",photo,60*60*24*5));
}
//安全退出功能
@Override
public void loginOut(HttpServletRequest request, HttpServletResponse response) {
//删除Cookie里的数据
response.addCookie(CookieUtils.createCookie("username","",0));
response.addCookie(CookieUtils.createCookie("name","",0));
response.addCookie(CookieUtils.createCookie("role","",0));
response.addCookie(CookieUtils.createCookie("photo","",0));
response.addCookie(CookieUtils.createCookie("password","",0));
//删除Session里的数据
HttpSession session = request.getSession();
session.removeAttribute("username");
session.removeAttribute("name");
session.removeAttribute("role");
session.removeAttribute("photo");
session.removeAttribute("password");
}
//修改密码功能
@Override
public boolean resetPassword(HttpServletRequest request, HttpServletResponse response) {
//获取请求中的数据
String username = request.getParameter("username");
String password = request.getParameter("password");
String newPassword = request.getParameter("newPassword");
String role = request.getParameter("role");
User user = null;
if("student".equals(role)){
user = studentMapper.getStudent(username,password);
}else if("teacher".equals(role)){
user = teacherMapper.getTeacher(username,password);
} else if ("admin".equals(role)) {
user = adminMapper.getAdmin(username, password);
}
if(user != null){
if("student".equals(role)){
studentMapper.update(username,newPassword);
}else if("teacher".equals(role)){
teacherMapper.update(username,newPassword);
} else if ("admin".equals(role)) {
adminMapper.update(username,newPassword);
}
return true;
}else{
request.setAttribute("msg","修改密码失败 -- 原密码不正确");
return false;
}
}
}
UserController
,前端传过来的路径中带有action=“xxx功能”,然后进行xxx功能的相关业务的跳转
@WebServlet("/user")
public class UserController extends BaseServlet {
private UserService userService = new UserServiceImpl();
public void doDrawCode(HttpServletRequest request,HttpServletResponse response){
userService.drawCode(request,response);
}
public void doLogin(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {
boolean login = userService.login(request, response);
if(login){
response.sendRedirect("index.jsp");
}else{
request.getRequestDispatcher("login.jsp").forward(request,response);
}
}
public void doLoginOut(HttpServletRequest request,HttpServletResponse response) throws IOException {
userService.loginOut(request, response);
response.sendRedirect("welcome.html");
}
public void doResetPassword(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
boolean resetPassword = userService.resetPassword(request, response);
if(resetPassword){
request.getRequestDispatcher("user?action=doLoginOut").forward(request,response);
}else{
request.getRequestDispatcher("resetPassword.jsp").forward(request,response);
}
}
}
2.4 管理员
功能:
1.登录(user里有)
2.修改密码(user里有)
3.管理老师 – 老师列表页面(分页、修改、删除、添加)
4.管理学科 – 学科列表页面(展示所有学科、修改、删除、添加)
5.管理学生 – 学生列表页面(分页、修改、删除、添加)
实体类 Admin 直接继承user类
SQL – admin :username、password
public class Admin extends User{}
AdminMapper
public interface AdminMapper {
//获取管理员信息,通过username
public Admin getAdmin(String username);
//获取管理员信息,通过username和username
public Admin getAdmin(String username,String password);
//更新管理员的密码,通过username和newPassword
public void update(String username,String newPassword);
}
AdminMapperImpl
public class AdminMapperImpl implements AdminMapper {
@Override
public Admin getAdmin(String username) {
Admin admin=null;
try {
admin = DBUtils.commonQueryObj(Admin.class, "select * from admin where username =?", username);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return admin;
}
@Override
public Admin getAdmin(String username, String password) {
Admin admin=null;
try {
admin = DBUtils.commonQueryObj(Admin.class, "select * from admin where username =? and password=?", username,password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return admin;
}
@Override
public void update(String username, String newPassword) {
try {
DBUtils.commonUpdate("update admin set password = ? where username =?", newPassword, username);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
AdminService
都是uer里写了的,就没有AdminServiceImpl,controller层也没有,直接在index.jsp跳转就可以了
public interface AdminService {
//登录功能
public boolean login(HttpServletRequest request, HttpServletResponse response);
//修改验证码功能
public boolean resetPassword(HttpServletRequest request, HttpServletResponse response);
}
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>Title</title>
</head>
<body>
<button οnclick="safeExit()">安全退出</button>
<h1>详情页面</h1>
<c:if test="${role eq 'admin'}">
<h1>欢迎管理员进入到学生管理系统</h1>
</c:if>
<c:if test="${role eq 'student' || role eq 'teacher'}">
<h1>欢迎${name}${(role eq "student")?"学员":""}${(role eq "teacher")?"老师":""}进入到学生管理系统</h1>
<img src="${photo}" width="100px" height="100px"><br/>
</c:if>
<a href="resetPassword.jsp">修改密码</a>
<c:if test="${role eq 'admin'}">
<a href="student?action=doGetStudents&curPage=1">管理学生</a>
<a href="teacher?action=doGetTeachers&curPage=1">管理老师</a>
<a href="course?action=doGetCourses">管理学科</a>
</c:if>
<c:if test="${role eq 'student'}">
<a href="student?action=doInitModify&username=${username}">修改信息</a>
</c:if>
<c:if test="${role eq 'teacher'}">
<a href="teacher?action=doInitModify&username=${username}">修改信息</a>
<a href="student?action=doGetStudents&curPage=1">查看所有学生</a>
</c:if>
<script type="text/javascript">
function safeExit(){
window.location = "user?action=doLoginOut";
}
</script>
</body>
</html>
2.5 其他补充
数据库工具类DBUtils
package com.qf.utils;
public class DBUtils {
private static DruidDataSource pool;
private static ThreadLocal<Connection> local;
static{
Properties properties = new Properties();
try {
properties.load(DBUtils.class.getClassLoader().getResourceAsStream("DBConfig.properties"));
} catch (IOException e) {
throw new RuntimeException(e);
}
String driverClassName = properties.getProperty("driverClassName");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
int maxActive = Integer.parseInt(properties.getProperty("maxActive"));
//初始化数据库连接池
pool = new DruidDataSource();
//设置参数
pool.setDriverClassName(driverClassName);
pool.setUrl(url);
pool.setUsername(username);
pool.setPassword(password);
pool.setMaxActive(maxActive);
local = new ThreadLocal<>();
}
/**
* 获取连接对象
*/
public static Connection getConnection() throws SQLException {
Connection connection = local.get();//获取当前线程的Connection对象
if(connection == null){
connection = pool.getConnection();//获取数据库连接池里的连接对象
local.set(connection);//将Connection对象添加到local中
}
return connection;
}
/**
* 关闭资源
*/
public static void close(Connection connection, Statement statement, ResultSet resultSet){
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if(connection != null){
try {
if(connection.getAutoCommit()){
connection.close();
local.set(null);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
/**
* 开启事务
*/
public static void startTransaction() throws SQLException {
Connection connection = getConnection();
connection.setAutoCommit(false);
}
/**
* 提交事务
*/
public static void commit() throws SQLException {
Connection connection = local.get();
if(connection != null){
connection.commit();
connection.close();
local.set(null);
}
}
public static void rollback() throws SQLException {
Connection connection = local.get();
if(connection != null){
connection.rollback();
connection.close();
local.set(null);
}
}
/**
* 更新数据(添加、删除、修改)
*/
public static int commonUpdate(String sql,Object... params) throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
try {
connection = getConnection();
statement = connection.prepareStatement(sql);
paramHandler(statement,params);
int num = statement.executeUpdate();
return num;
}finally {
close(connection,statement,null);
}
}
/**
* 添加数据 - 主键回填(主键是int类型可以返回)
*/
public static int commonInsert(String sql,Object... params) throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = getConnection();
statement = connection.prepareStatement(sql,PreparedStatement.RETURN_GENERATED_KEYS);
paramHandler(statement,params);
statement.executeUpdate();
resultSet = statement.getGeneratedKeys();
int primaryKey = 0;
if(resultSet.next()){
primaryKey = resultSet.getInt(1);
}
return primaryKey;
}finally {
close(connection,statement,resultSet);
}
}
/**
* 查询多个数据
*/
public static <T> List<T> commonQueryList(Class<T> clazz,String sql, Object... params) throws SQLException{
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = getConnection();
statement = connection.prepareStatement(sql);
paramHandler(statement,params);
resultSet = statement.executeQuery();
//获取表数据对象
ResultSetMetaData metaData = resultSet.getMetaData();
//获取字段个数
int count = metaData.getColumnCount();
List<T> list = new ArrayList<>();
while(resultSet.next()){
T t = null;
try {
t = clazz.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
//获取字段名及数据
for (int i = 1; i <= count; i++) {
String fieldName = metaData.getColumnName(i);
Object fieldVal = resultSet.getObject(fieldName);
setField(t,fieldName,fieldVal);
}
list.add(t);
}
return list;
} finally {
DBUtils.close(connection,statement,resultSet);
}
}
/**
* 查询单个数据
*/
public static <T> T commonQueryObj(Class<T> clazz,String sql, Object... params) throws SQLException{
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = getConnection();
statement = connection.prepareStatement(sql);
paramHandler(statement,params);
resultSet = statement.executeQuery();
//获取表数据对象
ResultSetMetaData metaData = resultSet.getMetaData();
//获取字段个数
int count = metaData.getColumnCount();
if(resultSet.next()){
T t = null;
try {
t = clazz.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
//获取字段名及数据
for (int i = 1; i <= count; i++) {
String fieldName = metaData.getColumnName(i);
Object fieldVal = resultSet.getObject(fieldName);
setField(t,fieldName,fieldVal);
}
return t;
}
} finally {
DBUtils.close(connection,statement,resultSet);
}
return null;
}
/**
* 获取当前表的总条数
*/
public static int getAllCount(String table) throws SQLException {
Connection connection = getConnection();
String sql = "select count(1) from " + table;
PreparedStatement statement = connection.prepareStatement(sql);
ResultSet resultSet = statement.executeQuery();
if(resultSet.next()){
int allCount = resultSet.getInt(1);
return allCount;
}
return 0;
}
/**
* 处理statement对象参数数据的处理器
*/
private static void paramHandler(PreparedStatement statement,Object... params) throws SQLException {
for (int i = 0; i < params.length; i++) {
statement.setObject(i+1,params[i]);
}
}
/**
* 获取当前类及其父类的属性对象
* @param clazz class对象
* @param name 属性名
* @return 属性对象
*/
private static Field getField(Class<?> clazz,String name){
for(Class<?> c = clazz;c != null;c = c.getSuperclass()){
try {
Field field = c.getDeclaredField(name);
return field;
} catch (NoSuchFieldException e) {
} catch (SecurityException e) {
}
}
return null;
}
/**
* 设置对象中的属性
* @param obj 对象
* @param name 属性名
* @param value 属性值
*/
private static void setField(Object obj,String name,Object value){
Field field = getField(obj.getClass(), name);
if(field != null){
field.setAccessible(true);
try {
field.set(obj, value);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
其余代码太多,不一一展示
总结
1…MVC
注意:MVC设计模式和服务端分层思想的区别2.MVC版本的学生管理系统