MVC实例应用模式
完成:MVC模式在Java Web应用程序中的实例分析
结合六个基本质量属性
分析具体功能模块的MVC设计实现(例如登录、用户权限等功能模块)
在实际项目中的具体应用
或分析MVC设计模式在具体网站中的应用(需要列举实例)
首先了解一下MVC框架是什么
模型-视图-控制器(MVC)是一个众所周知的以设计界面应用程序为基础的。它主要通过分离模型、视图及控制器在应用程序中的角色将业务逻辑从界面中解耦。通常,模型负责封装应用程序数据在视图层展示。视图仅仅只是展示这些数据,不包含任何业务逻辑。控制器负责接收来自用户的请求,并调用后台服务(manager或者dao)来处理业务逻辑。处理后,后台业务层可能会返回了一些数据在视图层展示。控制器收集这些数据及准备模型在视图层展示。MVC模式的核心思想是将业务逻辑从界面中分离出来,允许它们单独改变而不会相互影响。
以下介绍MVC实例
Controller部分
LoginController.java
package com.flf.controller; import java.util.Date; import java.util.List; import javax.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired; 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.RequestParam; import org.springframework.web.servlet.ModelAndView; import com.flf.entity.Menu; import com.flf.entity.Role; import com.flf.entity.User; import com.flf.service.MenuService; import com.flf.service.UserService; import com.flf.util.Const; import com.flf.util.RightsHelper; import com.flf.util.Tools; @Controller public class LoginController { @Autowired private UserService userService; @Autowired private MenuService menuService; /** * 访问登录页 * @return */ @RequestMapping(value="/login",method=RequestMethod.GET) public String loginGet(){ return "login"; } /** * 请求登录,验证用户 * @param session * @param loginname * @param password * @param code * @return */ @RequestMapping(value="/login",method=RequestMethod.POST) public ModelAndView loginPost(HttpSession session,@RequestParam String loginname,@RequestParam String password,@RequestParam String code){ String sessionCode = (String)session.getAttribute(Const.SESSION_SECURITY_CODE); ModelAndView mv = new ModelAndView(); String errInfo = ""; if(Tools.notEmpty(sessionCode) && sessionCode.equalsIgnoreCase(code)){ User user = userService.getUserByNameAndPwd(loginname, password); if(user!=null){ user.setLastLogin(new Date()); userService.updateLastLogin(user); session.setAttribute(Const.SESSION_USER, user); session.removeAttribute(Const.SESSION_SECURITY_CODE); }else{ errInfo = "用户名或密码有误!"; } }else{ errInfo = "验证码输入有误!"; } if(Tools.isEmpty(errInfo)){ mv.setViewName("redirect:index.html"); }else{ mv.addObject("errInfo", errInfo); mv.addObject("loginname",loginname); mv.addObject("password",password); mv.setViewName("login"); } return mv; } /** * 访问系统首页 * @param session * @param model * @return */ @RequestMapping(value="/index") public String index(HttpSession session,Model model){ User user = (User)session.getAttribute(Const.SESSION_USER); user = userService.getUserAndRoleById(user.getUserId()); Role role = user.getRole(); String roleRights = role!=null ? role.getRights() : ""; String userRights = user.getRights(); //避免每次拦截用户操作时查询数据库,以下将用户所属角色权限、用户权限限都存入session session.setAttribute(Const.SESSION_ROLE_RIGHTS, roleRights); //将角色权限存入session session.setAttribute(Const.SESSION_USER_RIGHTS, userRights); //将用户权限存入session List<Menu> menuList = menuService.listAllMenu(); if(Tools.notEmpty(userRights) || Tools.notEmpty(roleRights)){ for(Menu menu : menuList){ menu.setHasMenu(RightsHelper.testRights(userRights, menu.getMenuId()) || RightsHelper.testRights(roleRights, menu.getMenuId())); if(menu.isHasMenu()){ List<Menu> subMenuList = menu.getSubMenu(); for(Menu sub : subMenuList){ sub.setHasMenu(RightsHelper.testRights(userRights, sub.getMenuId()) || RightsHelper.testRights(roleRights, sub.getMenuId())); } } } } model.addAttribute("user", user); model.addAttribute("menuList", menuList); return "index"; } /** * 进入首页后的默认页面 * @return */ @RequestMapping(value="/default") public String defaultPage(){ return "default"; } /** * 用户注销 * @param session * @return */ @RequestMapping(value="/logout") public String logout(HttpSession session){ session.removeAttribute(Const.SESSION_USER); session.removeAttribute(Const.SESSION_ROLE_RIGHTS); session.removeAttribute(Const.SESSION_USER_RIGHTS); return "login"; } }
View部分
Login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>XXX管理系统</title> <style type="text/css"> body{margin-left: 0px;margin-top: 0px;margin-right: 0px;margin-bottom: 0px;background-color: #1B3142;} .header{100%;height:41px;background: url(images/login-top-bg.gif) repeat-x;} .center{100%;height:532px;background: url(images/login_bg.jpg) repeat-x;} .login_right{float:right;50%;height:100%;background: url(images/login-wel.gif) bottom no-repeat;} .login_left{float:right;295px;height:100%;background: url(images/login-content-bg.gif) no-repeat;} .login_title{margin-left:35px;font-family: Arial, Helvetica, sans-serif;font-size: 14px;height:36px;line-height: 36px;color: #666666;font-weight: bold;} .login_info{margin-left:35px;font-family: Arial, Helvetica, sans-serif;font-size: 12px;height:36px;line-height: 36px;color: #333333;} .login_input{150px;height:20px;margin-left:30px;border:1px solid #7F9DB9;vertical-align: middle;} .login_code{70px;height:20px;margin-left:30px;border:1px solid #7F9DB9;vertical-align: middle;} .btn{60px;height:25px;border-0px;background-image: url(images/btn-bg2.gif);letter-spacing: 3px;margin-right:70px;cursor: pointer;} .login_info img{vertical-align: middle;cursor: pointer;} .errInfo{display:none;color:red;} .logo{100%;height:68px;background: url(images/logo2.png) no-repeat;_background:none;_filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/logo2.png';)} .left_txt{font-family: Arial, Helvetica, sans-serif;font-size: 12px;line-height: 25px;color: #666666;} .bottom{100%;height:auto;text-align:center;font-family: Arial, Helvetica, sans-serif;font-size: 10px;color: #ABCAD3;text-decoration: none;line-height: 20px;} </style> <script type="text/javascript" src="js/jquery-1.5.1.min.js"></script> </head> <body> <div style="100%;height:645px;position: absolute;top:50%;left:50%;margin-top:-320px;margin-left:-50%;"> <div class="header"></div> <div class="center"> <div class="login_right"> <div style="100%;height:auto;margin-top:150px;"> <form action="login.html" method="post" name="loginForm" onsubmit="check();"> <div class="login_title"> 管理员登录 </div> <div class="login_info"> <label>用户名:</label><input type="text" name="loginname" id="loginname" class="login_input" value="${loginname }"/> <span id="nameerr" class="errInfo"></span> </div> <div class="login_info"> <label>密 码:</label><input type="password" name="password" id="password" class="login_input" value="${password }"/> <span id="pwderr" class="errInfo"></span> </div> <div class="login_info"> <label>验证码:</label><input type="text" name="code" id="code" class="login_code"/> <img id="codeImg" alt="点击更换" title="点击更换" src=""/> <span id="codeerr" class="errInfo"></span> </div> <div class="login_info"> <input type="submit" name="loginBtn" value="登录" class="btn"/> <input type="reset" name="cancelBtn" value="取消" class="btn"/> </div> </form> </div> </div> <div class="login_left"> <div style="100%;height:auto;margin-top:150px;"> <div class="logo"></div> <div class="left_txt"> </div> </div> </div> </div> <div class="bottom"> </div> </div> <script type="text/javascript"> var errInfo = "${errInfo}"; $(document).ready(function(){ changeCode(); $("#codeImg").bind("click",changeCode); if(errInfo!=""){ if(errInfo.indexOf("验证码")>-1){ $("#codeerr").show(); $("#codeerr").html(errInfo); $("#code").focus(); }else{ $("#nameerr").show(); $("#nameerr").html(errInfo); } } $("#loginname").focus(); }); function genTimestamp(){ var time = new Date(); return time.getTime(); } function changeCode(){ $("#codeImg").attr("src","code.html?t="+genTimestamp()); } function resetErr(){ $("#nameerr").hide(); $("#nameerr").html(""); $("#pwderr").hide(); $("#pwderr").html(""); $("#codeerr").hide(); $("#codeerr").html(""); } function check(){ resetErr(); if($("#loginname").val()==""){ $("#nameerr").show(); $("#nameerr").html("用户名不得为空!"); $("#loginname").focus(); return false; } if($("#password").val()==""){ $("#pwderr").show(); $("#pwderr").html("密码不得为空!"); $("#password").focus(); return false; } if($("#code").val()==""){ $("#codeerr").show(); $("#codeerr").html("验证码不得为空!"); $("#code").focus(); return false; } return true; } </script> </body> </html>
Model
user.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.flf.mapper.UserMapper"> <sql id="userColumns">loginname,username,password,rights,status,role_id</sql> <resultMap type="User" id="userAndRoleResultMap"> <id column="user_id" property="userId"/> <result column="loginname" property="loginname"/> <result column="username" property="username"/> <result column="password" property="password"/> <result column="user_rights" property="rights"/> <result column="status" property="status"/> <result column="last_login" property="lastLogin"/> <association property="role" column="role_id" javaType="Role"> <id column="role_id" property="roleId"/> <result column="role_name" property="roleName"/> <result column="role_rights" property="rights"/> </association> </resultMap> <resultMap type="User" id="userResultMap"> <id column="user_id" property="userId"/> <result column="loginname" property="loginname"/> <result column="username" property="username"/> <result column="password" property="password"/> <result column="rights" property="rights"/> <result column="status" property="status"/> <result column="role_id" property="roleId"/> </resultMap> <select id="listAllUser" resultMap="userAndRoleResultMap"> select u.user_id,u.username,u.loginname,u.password,r.role_id,r.role_name ,u.last_login from tb_user u left join tb_role r on u.role_id=r.role_id where u.status=0 </select> <select id="listPageUser" parameterType="User" resultMap="userAndRoleResultMap"> select u.user_id,u.username,u.loginname,u.password,r.role_id,r.role_name ,u.last_login from tb_user u left join tb_role r on u.role_id=r.role_id where u.status=0 <if test="loginname!=null and loginname!=''"> and u.loginname like "%"#{loginname}"%" </if> <if test="roleId!=null and roleId!=0"> and u.role_id=#{roleId} </if> <if test="lastLoginStart!=null"> and u.last_login>=#{lastLoginStart} </if> <if test="lastLoginEnd!=null"> and u.last_login<=#{lastLoginEnd} </if> </select> <select id="getUserInfo" parameterType="User" resultMap="userResultMap"> select * from tb_user where 1=1 <if test="loginname!=null and password!=null"> and loginname = #{loginname} and password=#{password} </if> <if test="userId!=null and userId>0"> and user_id = #{userId} </if> </select> <select id="getUserById" parameterType="int" resultMap="userResultMap"> select * from tb_user u where u.user_id = #{userId} </select> <select id="getUserAndRoleById" parameterType="int" resultMap="userAndRoleResultMap"> select u.user_id,u.username,u.rights as user_rights,u.loginname,u.password,r.role_id,r.role_name,r.rights as role_rights from tb_user u left join tb_role r on u.role_id=r.role_id where u.status=0 and u.user_id=#{userId} </select> <select id="getCountByName" parameterType="User" resultType="int"> select count(user_id) from tb_user where loginname=#{loginname} </select> <select id="getCount" parameterType="User" resultType="int"> select count(user_id) from tb_user where status=0 <if test="loginname!=null and loginname!=''"> and loginname like "%"#{loginname}"%" </if> <if test="roleId!=null and roleId!=0"> and role_id=#{roleId} </if> <if test="lastLoginStart!=null"> and last_login>=#{lastLoginStart} </if> <if test="lastLoginEnd!=null"> and last_login<=#{lastLoginEnd} </if> </select> <insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="userId"> insert tb_user (<include refid="userColumns"/>) values (#{loginname},#{username},#{password},#{rights},0,#{roleId}) </insert> <update id="updateUser" parameterType="User"> update tb_user set loginname=#{loginname}, username=#{username},password=#{password}, rights=#{rights}, status=#{status}, role_id=#{roleId}, last_login=#{lastLogin} where user_id=#{userId} </update> <update id="updateLastLogin" parameterType="User"> update tb_user set last_login=#{lastLogin} where user_id=#{userId} </update> <update id="updateUserBaseInfo" parameterType="User"> update tb_user set loginname=#{loginname}, username=#{username}, role_id=#{roleId} <if test="password!=null and password!=''">,password=#{password} </if> where user_id=#{userId} </update> <update id="updateUserRights" parameterType="User"> update tb_user set rights=#{rights} where user_id=#{userId} </update> <delete id="deleteUser" parameterType="int"> delete from tb_user where user_id=#{userId} </delete> </mapper>
在本实例中,还通过MyExceptionResolver.java检测异常,提高了系统的可用性,代码如下
package com.flf.resolver; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; //可用性 public class MyExceptionResolver implements HandlerExceptionResolver{ public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // TODO Auto-generated method stub System.out.println("==============异常开始============="); ex.printStackTrace(); System.out.println("==============异常结束============="); ModelAndView mv = new ModelAndView("error"); mv.addObject("exception", ex.toString().replaceAll(" ", "<br/>")); return mv; } }
与此同时通过登录的权限控制提高了系统的安全性