在JavaWeb的开发中,经常要写很多功能,这些功能交由Servlet处理。如果一个功能写一个Servlet,那么文件杂乱,不好管理。因此可以把不同的Servlet集成到一个Servlet中,要用哪个直接调用类中的方法即可。
baseServlet重写了service方法。在HttpServlet中的service()方法有两个,service(HttpServletRequest req, HttpServletResponse resp)用于接受标准的http请求,根据不同的请求方式转到不同的doXXX(HttpServletRequest,HttpServletResponse)方法,这是受保护的方法(protected);service(ServletRequest req, ServletResponse res)是公共(public)方法,一般重写此方法,用于接收客户端请求并传递给service(HttpServletRequest req, HttpServletResponse resp)方法。
从代码中可以看到,在servlet默认情况下,无论是get还是post请求,都会先经过protected域的service()方法来处理,之后转向doGet()或者doPost()方法。而baseServlet重写了protected域的service方法,这里的方法就不会转向doXXX,而是直接执行重写后的service方法。
因此,baseServlet重写service后不用再写doGet()和doPost()方法。
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if (ifModifiedSince < lastModified) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
this.service(request, response);
} else {
throw new ServletException("non-HTTP request or response");
}
}
下面是重写的baseServlet:
-
获取请求的URI并提取出其中的method
request.getRequestURI()
uri.substring(uri.lastIndexOf('/')+1)
:得到请求链接‘/’后面的字段,可以人为设置为方法名。 -
利用反射灵活地调用其他servlet总类中的方法
this.getClass().getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class;
method.invoke(this,request,response);
/**baseServlet.java**/
package web.servlet;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class baseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("baseServlet的service方法被执行啦。。。");
String uri = request.getRequestURI();
System.out.println("请求uri:"+uri);
String methodName = uri.substring(uri.lastIndexOf('/') + 1);//这样就不会包含'/'
System.out.println("方法名称:"+methodName);
System.out.println(this);
try {
Method method = this.getClass().getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
method.setAccessible(true);
method.invoke(this,request,response);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 将传入的对象序列化为json,并返回客户端
* @param object
* @param response
* @throws IOException
*/
public void writeValue(Object object, HttpServletResponse response) throws IOException {
ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset:utf-8");
mapper.writeValue(response.getOutputStream(),object);
}
/**
* 将传入的对象序列化为json,返回
* @param object
* @return
* @throws IOException
*/
public String writeValueAsString(Object object) throws IOException {
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(object);
}
}
这样,可以写不同分类下的Servlet,让他们继承baseServlet即可,@WebServlet(“/user/*”)
可以让user/路径下的请求均重定向到userServlet中的方法来执行。
/**userServlet.java**/
@WebServlet("/user/*")
public class userServlet extends baseServlet {
private UserService service = new UserServiceImpl();
/* * 判断验证码是否正确* */
public void VerifyCheckCode(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
...
}
/* * 判断注册时的用户名是否已经存在* */
public void CheckUsername(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
...
}
/* * 用户注册* */
public void Register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
...
}
/* * 用户登录* */
public void Login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
Map<String, String[]> login_inf = request.getParameterMap();
User user = new User();
try {
BeanUtils.populate(user, login_inf);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
//判断用户名和密码是否正确
HttpSession session = request.getSession();
session.setAttribute("active", false);
User checkUser = service.login(login_inf.get("username")[0],
login_inf.get("password")[0]);
if (checkUser == null) {
request.setAttribute("loginError", "❌用户名或密码错误");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
if (checkUser != null && !"Y".equals(checkUser.getStatus())) {
request.setAttribute("loginError", "❌您尚未激活,请激活");
request.getRequestDispatcher("/login.jsp").forward(request, response);
} else if (checkUser != null && "Y".equals(checkUser.getStatus())){
session.setAttribute("CurrentUser", checkUser);
session.setAttribute("active", true);
request.getSession().removeAttribute("CHECKCODE_SERVER");
response.sendRedirect(request.getContextPath() + "/index.jsp");
}
}
/* * 退出登录* */
public void Exit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
...
}
/* * 用户激活* */
public void Active(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
...
}
/* * 创建验证码* */
public void CreateCheckCode(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
...
}
/* * 产生4位随机字符串* */
private String getCheckCode() {
...
}
}
比如,我在jsp中form提交表头这样写:<form id="loginForm" action="user/Login" method="post">
,提交后会因为反射机制自动指向userServlet下的Login方法。该方法里的写法和单独写一个Servlet是一样的。
这种方式还可以应用于网页的异步更新,比如可以写:
$(function () {
$("#check").blur(function () {
//检查验证码是否正确
let checkcode = $(this).val();
let span = $("#s_check");
$.get("user/VerifyCheckCode", {check: checkcode}, function (data) {
span.html(data.msg_check);
flag_check = data.msg_flag;
}
);
});
// alert(flag_check);
$("#loginForm").submit(function () {
return flag_check;//验证码正确则执行提交操作,否则停留在前端。
})
});
参考资料
https://blog.csdn.net/FantasySxan/article/details/80264250
https://blog.csdn.net/muyihuakai/article/details/5858792