博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Online Judge(OJ)搭建——3、MVC架构
阅读量:4320 次
发布时间:2019-06-06

本文共 15901 字,大约阅读时间需要 53 分钟。

Model

Model 层主要包含数据的类,这些数据一般是现实中的实体,所以,Model 层中类的定义常常和数据库 DDL 中的 create 语句类似。

通常数据库的表和类是一对一的关系,但是有的时候由于需求变化或者方便起见,Model 层的类有时不和数据库中表相互对应。比如面向对象之组合属性,在 Java 中可以用一个类组合另一个类,表示测试信息、对应多组测试用例的组合,(正常情况下,应该是一张表而不是两张表),而数据库是用两张表存储数据,利用外键关系表示测试信息、对应多组测试用例的关系。 

由于数据繁多,为了简化对象的映射,不使用JDBC,而采用持久化框架 MyBatis。

MyBatis 首先需要配置数据源:

之后创建工厂对象,再用它创建数据访问对象(DataAccessObject,DAO):

@Bean    public SqlSessionFactory sqlSessionFactory() throws IOException {        ClassLoader classLoader = RootConfig.class.getClassLoader();        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(classLoader.getResourceAsStream("config/mybatis/mybatis-config.xml"));        return sqlSessionFactory;    }    @Autowired    @Bean    public DataAccessObject dataAccessObject(SqlSessionFactory sqlSessionFactory) {        return new DataAccessObject(sqlSessionFactory);    }

DAO 对象负责数据访问。首先以 Mapper 接口的方式定义访问数据库的函数,之后在 XML 文件中实现该函数,并提供具体实现(SQL 语句细节)。这样做的好处一方面是防止命名错误,传统 MyBatis 方式是根据函数名执行相关 SQL 语句的,不用接口书写很容易出错;另一方面有助于设计(接口)和实现分离,降低耦合性。

public interface UserMapper {    public int insertUser(@Param("user")User user);    public int updateUser(@Param("user")User user);    public int deleteUser(@Param("user") User user);    public User selectUser(@Param("user") User user);}
INSERT INTO users (email, password, name, sex, role, enabled) VALUES (#{user.email}, #{user.password}, #{user.name}, #{user.sex}, #{user.role}, #{user.enabled})
UPDATE users
email = #{user.email},
password = #{user.password},
name = #{user.name},
sex = #{user.sex},
role = #{user.role},
enabled = #{user.enabled},
WHERE id = #{user.id}
DELETE FROM users WHERE id = #{user.id}

MyBatis的可以处理基本类型,但有些类型需要自定义转换,就需要 MyBatis 提供的 BaseTypeHandler 进行转换。首先编写 BaseTypeHandler(见下),之后在 MyBatis 配置文件中注册(见上)。

package per.piers.onlineJudge.handler;import org.apache.ibatis.type.BaseTypeHandler;import org.apache.ibatis.type.JdbcType;import per.piers.onlineJudge.model.Sex;import java.sql.CallableStatement;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public class SexTypeHandler extends BaseTypeHandler
{ @Override public void setNonNullParameter(PreparedStatement preparedStatement, int i, Sex sex, JdbcType jdbcType) throws SQLException { preparedStatement.setInt(i, sex.getId()); } @Override public Sex getNullableResult(ResultSet resultSet, String s) throws SQLException { int sex = resultSet.getInt(s); if (resultSet.wasNull()) { return null; } else { return Sex.getSexType(sex); } } @Override public Sex getNullableResult(ResultSet resultSet, int i) throws SQLException { int sex = resultSet.getInt(i); if (resultSet.wasNull()) { return null; } else { return Sex.getSexType(i); } } @Override public Sex getNullableResult(CallableStatement callableStatement, int i) throws SQLException { int sex = callableStatement.getInt(i); if (callableStatement.wasNull()) { return null; } else { return Sex.getSexType(i); } }}

 

View

view 层主要是界面(页面)。这里主要是 JSP 页面,因为需要动态展示一些内容。其中还运用了 JavaScript 技术和 AJAX 技术,JavaScript 主要用作页面输入域校验,AJAX 主要用于异步提交需要更新的内容。

<%@page contentType="text/html; charset=UTF-8" %><%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@taglib uri="http://www.springframework.org/tags/form" prefix="sf" %><%@taglib uri="http://www.springframework.org/security/tags" prefix="security" %>    <%@include file="../common/header.jspf" %>    注册<%@include file="../common/navbar.jspf" %>
<%@include file="../common/footer.jspf" %>
function satisfySubmit() {    var submit = document.getElementById("submit");    if (isEmailValid() && isPasswordValid() && isRepasswordValid()) {        submit.setAttribute("type", "submit");        submit.setAttribute("value", "提交注册");        submit.setAttribute("class", "btn btn-success");        submit.removeAttribute("disabled")    } else {        submit.setAttribute("type", "button");        submit.setAttribute("value", "不能注册,请检查相关项填写是否正确");        submit.setAttribute("class", "btn btn-danger");        submit.setAttribute("disabled", "");    }}
function registerUser() {    xmlhttp = new XMLHttpRequest();    if (xmlhttp != null) {        var email = document.getElementById("email").value;        var password = document.getElementById("password").value;        var name = document.getElementById("name").value;        var sexes = document.getElementsByName("sex");        var sex;        for (var i = 0; i < sexes.length; i++) {            if (sexes[i].checked) sex = sexes[i].value.toUpperCase();        }        var enabled = document.getElementById("enabled").value;        var role = document.getElementById("role").value;        var csrf = document.getElementsByName("_csrf")[0].value;        xmlhttp.onreadystatechange = stateChange;        xmlhttp.open("POST", window.location.pathname, true);        xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");        xmlhttp.send("&email=" + email + "&password=" + password + "&name=" + name + "&sex=" + sex + "&enabled=" + enabled + "&role=" + role + "&_csrf=" + csrf);    }}function stateChange() {    var success = document.getElementById("success");    if (xmlhttp.readyState == 4) { // 4 = "loaded"        if (xmlhttp.status == 200) { // 200 = "OK"            success.setAttribute("class", "text-success");            success.innerHTML = "注册成功";            alert("注册成功,点击确定进行登录")            window.location.href = getContextPath() + "/user/information"        } else if (xmlhttp.status == 409) {            success.setAttribute("class", "text-danger");            success.innerHTML = "用户邮箱已存在";        } else if (xmlhttp.status == 500) {            success.setAttribute("class", "text-danger");            success.innerHTML = "服务器可能出现了问题";        }    }}

 

Controller

Controller 是 Model 和 View 的粘合剂。Model 的增删改查的操作由 Controller 负责,View 的显示由 Controller 负责。Controller 实质上是 Java EE 的 Servlet。

在 Spring MVC 中,首先配置相关 DispatcherServlet,之后再编写 Controller。

package per.piers.onlineJudge.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.ViewResolver;import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;import org.springframework.web.servlet.config.annotation.EnableWebMvc;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;import org.springframework.web.servlet.view.InternalResourceViewResolver;@Configuration@EnableWebMvc@ComponentScan("per.piers.onlineJudge.controller")public class WebConfig extends WebMvcConfigurerAdapter {    @Bean    public ViewResolver viewResolver() {        InternalResourceViewResolver resolver = new InternalResourceViewResolver();        resolver.setPrefix("/WEB-INF/jsp/");        resolver.setExposeContextBeansAsAttributes(true);        resolver.setSuffix(".jsp");        return resolver;    }    @Override    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {        configurer.enable();    }}
package per.piers.onlineJudge.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestPart;import org.springframework.web.multipart.MultipartFile;import per.piers.onlineJudge.model.User;import per.piers.onlineJudge.util.DataAccessObject;import per.piers.onlineJudge.util.ExcelUtil;import javax.servlet.http.HttpServletRequest;import java.io.File;import java.io.IOException;import java.util.HashMap;import java.util.HashSet;@Controller@RequestMapping("/testManager")public class UserImportController {    private DataAccessObject dao;    @Autowired    public UserImportController(DataAccessObject dao) {        this.dao = dao;    }    @RequestMapping("/import/user")    public String importUser() {        return "import/user";    }    @RequestMapping(path = "/import/user", method = RequestMethod.POST)    public String importResult(@RequestPart("usersFile") MultipartFile usersFile, HttpServletRequest request, Model model) throws IOException {        String path = request.getSession().getServletContext().getRealPath("/") + "/tmp/" + usersFile.getOriginalFilename();        File file = new File(path);        file.getParentFile().mkdirs();        file.createNewFile();        usersFile.transferTo(file);        ExcelUtil excelUtil = new ExcelUtil();        HashSet
emails = excelUtil.readColumns(file, "用户邮箱"); try { if (emails == null) { model.addAttribute("failure", "读取列用户邮箱出错,可能是没有列用户邮箱"); } else { User selectUser = new User(); selectUser.setEmail(((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername()); Integer uidAdmin = dao.selectUser(selectUser).getId(); HashMap
status = dao.importUser(emails, uidAdmin); StringBuilder builder = new StringBuilder(); for (String key : status.keySet()) { builder.append(String.format("%s,%s\n", key, status.get(key))); } model.addAttribute("success", builder.toString()); } } catch (Exception e) { model.addAttribute("failure", e.getMessage()); } finally { return "import/result"; } }}

Spring 技术:这里的 Controller 是由 Spring MVC 提供的。本系统还设计了一个 ErrorController,用户异常处理的 Controller,返回错误的页面。

package per.piers.onlineJudge.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;@Controllerpublic class ErrorController {    @RequestMapping(path = "/error/401")    public String error401() {        return "error/401";    }    @RequestMapping(path = "/error/403")    public String error403() {        return "error/403";    }    @RequestMapping(path = "/error/404")    public String error404() {        return "error/404";    }    @RequestMapping(path = "/error/409")    public String error409() {        return "error/409";    }    @RequestMapping(path = "/error/500")    public String error500() {        return "error/500";    }}

Spring 技术:异常的捕获和处理是由标有 @ControllerAdvice 注解的类处理,需要定义捕获的异常类型、如何处理(返回的 HTTP 状态码,返回的页面)。

package per.piers.onlineJudge.controller;import org.apache.ibatis.exceptions.PersistenceException;import org.springframework.http.HttpStatus;import org.springframework.security.authentication.BadCredentialsException;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseStatus;import per.piers.onlineJudge.Exception.CRUDException;import per.piers.onlineJudge.Exception.ExistenceException;import per.piers.onlineJudge.Exception.ExpiryException;import javax.mail.MessagingException;import java.io.IOException;import java.io.PrintWriter;import java.io.StringWriter;@ControllerAdvicepublic class GlobalExceptionHandler {    @ResponseStatus(value = HttpStatus.UNAUTHORIZED)    @ExceptionHandler(BadCredentialsException.class)    public String badCredentialsExceptionHandler(Exception e, Model model) {        model.addAttribute("exception", getExceptionMessage(e));        return "error/401";    }    @ResponseStatus(value = HttpStatus.FORBIDDEN)    @ExceptionHandler(value = {ExpiryException.class, IllegalArgumentException.class})    public String illegalStateExceptionHandler(Exception e, Model model) {        model.addAttribute("exception", getExceptionMessage(e));        return "error/403";    }    @ResponseStatus(value = HttpStatus.CONFLICT)    @ExceptionHandler(ExistenceException.class)    public String existenceExceptionHandler(Exception e, Model model) {        model.addAttribute("exception", getExceptionMessage(e));        return "error/409";    }    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)    @ExceptionHandler(value = {CRUDException.class, IOException.class, IllegalStateException.class, MessagingException.class, PersistenceException.class})    public String CRUDExceptionHandler(Exception e, Model model) {        model.addAttribute("exception", getExceptionMessage(e));        return "error/500";    }    public String getExceptionMessage(Exception e) {        StringWriter stringWriter = new StringWriter();        PrintWriter printWriter = new PrintWriter(stringWriter);        e.printStackTrace(printWriter);        return stringWriter.toString();    }}

 

转载于:https://www.cnblogs.com/Piers/p/6942430.html

你可能感兴趣的文章
CSS3 transform制作的漂亮的滚动式导航
查看>>
《小强升职记——时间管理故事书》读书笔记
查看>>
Alpha 冲刺(3/10)
查看>>
Kaldi中的Chain模型
查看>>
spring中的ResourceBundleMessageSource使用和测试示例
查看>>
css规范 - bem
查看>>
电梯调度程序的UI设计
查看>>
转自 zera php中extends和implements的区别
查看>>
Array.of使用实例
查看>>
【Luogu】P2498拯救小云公主(spfa)
查看>>
如何获取网站icon
查看>>
几种排序写法
查看>>
java 多线程的应用场景
查看>>
dell support
查看>>
转:Maven项目编译后classes文件中没有dao的xml文件以及没有resources中的配置文件的问题解决...
查看>>
MTK android 设置里 "关于手机" 信息参数修改
查看>>
单变量微积分笔记6——线性近似和二阶近似
查看>>
补几天前的读书笔记
查看>>
HDU 1829/POJ 2492 A Bug's Life
查看>>
CKplayer:视频推荐和分享插件设置
查看>>