我们先不解释什么叫MVC,针对项目中的问题,解决推进慢慢把项目改进发展成MVC来理解它。
无论是jsp中嵌入java代码,或者servlet内嵌html都会使代码混乱,不便分工合作和后期开发。我们现在让jsp只负责显示,而代码控制给servlet负责,就是处理请求交给servlet,这样我们就把项目的显示和控制分离开来。
以用户注册作为例子,首先要有页面register.jsp输入用户信息,因为jsp只负责显示,所以前面要有一个servlet(register.do)控制跳转到register.jsp页面,然后视图提交给另一个servlet(user_add.do)进行用户添加,再跳转到用户列表(user_list.jsp)页面,同样要用servlet(user_list.do)控制。(如果没有user_list.do,让user_add.do把user_list.do做的事给做了,除了职责不单一,还会有重复提交的隐患另作处理,如果不用服务器端跳转用客户端跳转,如果把jsp文件放在WEB-INF是找不到的),即
register.do--------forword()------>register.jsp------------submit()-------->user_add.do-------------redirect()------>user_list.do---------forword()------>user_list.jsp
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<servlet>
<servlet-name>UserRegister</servlet-name>
<servlet-class>com.yan.mvc.servlet.UserRegister</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserRegister</servlet-name>
<url-pattern>/register.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>UserAdd</servlet-name>
<servlet-class>com.yan.mvc.servlet.UserAdd</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserAdd</servlet-name>
<url-pattern>/user_add.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>UserList</servlet-name>
<servlet-class>com.yan.mvc.servlet.UserList</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserList</servlet-name>
<url-pattern>/user_list.do</url-pattern>
</servlet-mapping>
</web-app>
register.do
package com.yan.mvc.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class UserRegister extends HttpServlet {
private static final long serialVersionUID = 1L;
public UserRegister() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/user/register.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>Insert title here</title>
</head>
<body>
<form action="user_add.do" method="post">
<table align="center" width="500" border="1">
<tr><td>用户名称:</td><td><input type="text" name="name" value=""/>
</td>
</tr>
<tr><td>用户年龄:</td><td><input type="text" name="age" value=""/>
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="添加用户">
</td>
</tr>
</table>
</form>
</body>
</html>
user_add.do
package com.yan.mvc.servlet; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.yan.mvc.model.User; public class UserAdd extends HttpServlet { public UserAdd() { super(); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); String name=req.getParameter("name"); int age=Integer.parseInt(req.getParameter("age")); List<User> users=(List<User>)req.getSession().getServletContext().getAttribute("storeUsers"); if(users==null){ users=new ArrayList<User>(); } User u=new User(name,age); users.add(u); req.getSession().getServletContext().setAttribute("storeUsers", users); resp.sendRedirect("user_list.do"); } }
user_list.do
package com.yan.mvc.servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.yan.mvc.model.User;
public class UserList extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public UserList() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<User>users=(List<User>)request.getSession().getServletContext().getAttribute("storeUsers");
request.setAttribute("users", users);
request.getRequestDispatcher("/WEB-INF/user/user_list.jsp").forward(request, response);
}
}
user_list.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>Insert title here</title>
<style type="text/css">
table{
border-bottom:1px solid #000;
border-right:1px solid #000;
}
table td{
border-top:1px solid #000;
border-left:1px solid #000;
padding:5px;
}
</style>
</head>
<body>
<a href="register.do" >添加用户</a>
<table align="center" width="200" cellspacing="0" cellpadding="0">
<tr>
<td>用户名</td><td>年龄</td>
</tr>
<c:if test="${empty users }">
<tr><td colspan="2">没有用户信息</td></tr>
</c:if>
<c:if test="${not empty users}">
<c:forEach var="user" items="${users}">
<tr>
<td>${user.name}</td>
<td>
<c:choose>
<c:when test="${user.age gt 17 }">${user.age }</c:when>
<c:otherwise>未成年</c:otherwise>
</c:choose>
</td>
</tr>
</c:forEach>
</c:if>
</table>
</body>
----------------------------------------------------------------------------------------------------
可以发现这样虽然实现目的,将控制与视图显示分离开来,但明显一个jsp就有一个servlet,太多了,我们可以将它们进行合并成一个,可以使用传参的方式
user.do
package com.yan.mvc.servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.annotation.WebServlet;
import javax.jws.WebService;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.yan.mvc.model.User;
@WebServlet("/user.do")
public class UserServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public UserServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
//动态获取访问的是哪个操作
String method=request.getParameter("method");
if("add".equals(method)){
add(request,response);
}else if("list".equals(method)){
list(request,response);
}else if("register".equals(method)){
register(request,response);
}
}
protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name=req.getParameter("name");
int age=Integer.parseInt(req.getParameter("age"));
List<User> users=(List<User>)req.getSession().getServletContext().getAttribute("storeUsers");
if(users==null){
users=new ArrayList<User>();
}
User u=new User(name,age);
users.add(u);
req.getSession().getServletContext().setAttribute("storeUsers", users);
resp.sendRedirect("user.do?method=list");
}
protected void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<User>users=(List<User>)request.getSession().getServletContext().getAttribute("storeUsers");
request.setAttribute("users", users);
request.getRequestDispatcher("/WEB-INF/user/user_list.jsp").forward(request, response);
}
protected void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/user/register.jsp").forward(request, response);
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>Insert title here</title>
</head>
<body>
<form action="user.do?method=add" method="post">
<table align="center" width="500" border="1">
<tr><td>用户名称:</td><td><input type="text" name="name" value=""/>
</td>
</tr>
<tr><td>用户年龄:</td><td><input type="text" name="age" value=""/>
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="添加用户">
</td>
</tr>
</table>
</form>
</body>
</html>
<%@ 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>Insert title here</title>
<style type="text/css">
table{
border-bottom:1px solid #000;
border-right:1px solid #000;
}
table td{
border-top:1px solid #000;
border-left:1px solid #000;
padding:5px;
}
</style>
</head>
<body>
<a href="user.do?method=register" >添加用户</a>
<table align="center" width="200" cellspacing="0" cellpadding="0">
<tr>
<td>用户名</td><td>年龄</td>
</tr>
<c:if test="${empty users }">
<tr><td colspan="2">没有用户信息</td></tr>
</c:if>
<c:if test="${not empty users}">
<c:forEach var="user" items="${users}">
<tr>
<td>${user.name}</td>
<td>
<c:choose>
<c:when test="${user.age gt 17 }">${user.age }</c:when>
<c:otherwise>未成年</c:otherwise>
</c:choose>
</td>
</tr>
</c:forEach>
</c:if>
</table>
</body>
----------------------------------------------------------------------------------------------------
上面还有不足的地方,那就是如果操作很多,要写过多的if-else语句,怎么修改?第一时间想到了反射,根据参数自动选择要执行的方法
package com.yan.mvc.servlet;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.yan.mvc.model.User;
@WebServlet("/user.do")
public class UserServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public UserServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String method=request.getParameter("method");
try {
Method m=this.getClass().getMethod(method,HttpServletRequest.class,HttpServletResponse.class);
m.invoke(this, request,response);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name=req.getParameter("name");
int age=Integer.parseInt(req.getParameter("age"));
List<User> users=(List<User>)req.getSession().getServletContext().getAttribute("storeUsers");
if(users==null){
users=new ArrayList<User>();
}
User u=new User(name,age);
users.add(u);
req.getSession().getServletContext().setAttribute("storeUsers", users);
resp.sendRedirect("user.do?method=list");
}
@SuppressWarnings("unchecked")
public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<User>users=(List<User>)request.getSession().getServletContext().getAttribute("storeUsers");
request.setAttribute("users", users);
request.getRequestDispatcher("/WEB-INF/user/user_list.jsp").forward(request, response);
}
public void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/user/register.jsp").forward(request, response);
}
}
可以发现现在增加方法,不用再去修改doPost(),如果用的是if-else则要不断增加else if语句。(体验反射神奇之处,不用修改,根据参数去执行某个方法,死的东西活过来了)
其实反射的那部分代码是通用的,更好的改进方法是提取出来,创建一个BaseServlet,让UserServlet去继承它。
package com.yan.mvc.servlet;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String method=request.getParameter("method");
try {
Method m=this.getClass().getMethod(method,HttpServletRequest.class,HttpServletResponse.class);
m.invoke(this, request,response);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
package com.yan.mvc.servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.yan.mvc.model.User;
@WebServlet("/user.do")
public class UserServlet extends BaseServlet {
private static final long serialVersionUID = 1L;
@SuppressWarnings("unchecked")
public void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name=req.getParameter("name");
int age=Integer.parseInt(req.getParameter("age"));
List<User> users=(List<User>)req.getSession().getServletContext().getAttribute("storeUsers");
if(users==null){
users=new ArrayList<User>();
}
User u=new User(name,age);
users.add(u);
req.getSession().getServletContext().setAttribute("storeUsers", users);
resp.sendRedirect("user.do?method=list");
}
@SuppressWarnings("unchecked")
public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<User>users=(List<User>)request.getSession().getServletContext().getAttribute("storeUsers");
request.setAttribute("users", users);
request.getRequestDispatcher("/WEB-INF/user/user_list.jsp").forward(request, response);
}
public void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/user/register.jsp").forward(request, response);
}
}
这样一来真正通用,不仅是UserServlet,以后有什么AddressServlet、MessageServlet等等都可以去继承它,在这些servlet中我们只顾写需要的业务方法就好了(就好像UserServlet只要写add()、list()、register()这些方法,神奇!!!),
进一步把页面跳转代码给提取出来
package com.yan.mvc.servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.yan.mvc.model.User;
@WebServlet("/user.do")
public class UserServlet extends BaseServlet {
private static final long serialVersionUID = 1L;
@SuppressWarnings("unchecked")
public String add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name=req.getParameter("name");
int age=Integer.parseInt(req.getParameter("age"));
List<User> users=(List<User>)req.getSession().getServletContext().getAttribute("storeUsers");
if(users==null){
users=new ArrayList<User>();
}
User u=new User(name,age);
users.add(u);
req.getSession().getServletContext().setAttribute("storeUsers", users);
return "redirect:user.do?method=list";
// resp.sendRedirect("user.do?method=list");
}
@SuppressWarnings("unchecked")
public String list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<User>users=(List<User>)request.getSession().getServletContext().getAttribute("storeUsers");
request.setAttribute("users", users);
return "user/user_list.jsp";
// request.getRequestDispatcher("/WEB-INF/user/user_list.jsp").forward(request, response);
}
public String register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// request.getRequestDispatcher("/WEB-INF/user/register.jsp").forward(request, response);
return "user/register.jsp";
}
}
package com.yan.mvc.servlet; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class BaseServlet extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String method=request.getParameter("method"); try { Method m=this.getClass().getMethod(method,HttpServletRequest.class,HttpServletResponse.class); //获取要跳转到的页面
String rel=(String)m.invoke(this, request,response); String redirStr="redirect:";
//判断客户端跳转还是服务器端跳转 if(rel.startsWith(redirStr)){ response.sendRedirect(rel.substring(redirStr.length())); }else{ request.getRequestDispatcher("/WEB-INF/"+rel).forward(request, response); } } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }