目录
为什么要优化Servlet
每多出一个JSP,都要编写一个与之相关的Servlet,当页面多起来与之Servlet就会很多。一个简单的web项目就会有很多的Servlet会使项目变臃肿。
所以为了减少Servlet数量,抽取出一个父类BaseServlet来继承HttpServlet,然后其他的UserServlet,FileServlet,IndexServlet都继承BaseServlet,然后再BaseServlet中的service方法中去进行方法分发,通过反射动态的去获取调用相关的方法。如下:
package com.blb.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF8");
resp.setCharacterEncoding("UTF8");//设置请求响应的编码为UTF-8
String uri = req.getRequestURI(); // 访问的Uri为/user/....
String method = uri.substring(uri.lastIndexOf("/") + 1);//截取访问路径的url最后的字段就是需要去访问的方法名,就是获取user/后面得字段
Class<? extends BaseServlet> aClass = this.getClass(); //通过反射创建对象,谁调用就创建他的Class对象
try {
//获取对应的方法
Method declaredMethod = aClass.getDeclaredMethod(method,HttpServletRequest.class,HttpServletResponse.class);
declaredMethod.invoke(this,req,resp); //这里的this就是谁调用这个方法,就是谁
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
如何优化?
根据不同的操作来编写BaseServlet的子类,例如:这里的登录,注册,登出,新增用户,修改用户,删除用户都是跟用户相关的,所以写一个UserServlet来继承BaseServlet,配置UserServlet的("/user/*")。然后将用户操作的全部当方法卸载UserServlet里面。每当访问到/user/...是都会动态的获取最后的字段然后再去BaseServlet里面去调service方法,在通过反射调用相对应的方法完成操作。文件的上传与下载则是放在FileServlet下面是改造完的UserServlet:
package com.blb.servlet;
import com.blb.entity.User;
import com.blb.service.IUserService;
import com.blb.service.impl.IUserServiceImpl;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/user/*")
public class UserServlet extends BaseServlet{
IUserService iUserService = new IUserServiceImpl();
/**
* 新增用户
* @param req
* @param resp
*/
public void add(HttpServletRequest req, HttpServletResponse resp){
String name = req.getParameter("name");
String pwd = req.getParameter("pwd");
try {
iUserService.register(name,pwd);
resp.sendRedirect("/index");
} catch (Exception e) {
// e.printStackTrace();
req.setAttribute("msg",e.getMessage());
}
}
/**
* 删除用户
* @param req
* @param resp
*/
public void deleteServlet(HttpServletRequest req, HttpServletResponse resp){
String id = req.getParameter("id");
try {
iUserService.delete(Integer.parseInt(id));
resp.sendRedirect("/index");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 注册用户
* @param req
* @param resp
*/
public void register(HttpServletRequest req, HttpServletResponse resp){
String name = req.getParameter("name"); //获取页面提交过来的账号密码
String pwd = req.getParameter("pwd");
try {
iUserService.register(name,pwd);
resp.sendRedirect("login.jsp"); //注册成功就跳转到登录页面
} catch (Exception e) { //注册失败就提示
req.setAttribute("msg",e.getMessage());
}
}
/**
* 修改用户
* @param req
* @param resp
*/
public void update(HttpServletRequest req, HttpServletResponse resp){
String id = req.getParameter("id");
String name = req.getParameter("name");
String pwd = req.getParameter("pwd"); //获取update页面提交的数据
try {
iUserService.update(Integer.parseInt(id),name,pwd); //再根据提交的数据修改数据库中的值
resp.sendRedirect("/index"); //修改完之后跳转到index
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 登录
* @param req
* @param resp
*/
public void login(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
req.setCharacterEncoding("UTF8");
resp.setCharacterEncoding("UTF8");
resp.setContentType("text/html; charset=UTF8");
String name = req.getParameter("name");
String pwd = req.getParameter("password");
String check = req.getParameter("check");
try {
User user = iUserService.login(name, pwd);
ServletContext servletContext = req.getServletContext();
//七天免登陆
//1.获取session对象
HttpSession session = req.getSession();
if ("on".equals(check)){
//2.设置session最大存在时间
session.setMaxInactiveInterval(60*60*24*7);
//3.创建cookie对象key=JSESSIONID ,value=session.getId()
Cookie cookie = new Cookie("JSESSIONID", session.getId());
//4.设置cookie的最大存在时间
cookie.setMaxAge(60*60*24*7);
//4.设置path,即web下的而所有页面都能使用(所有应用共享cookie)
cookie.setPath("/");
//4.添加到Cookie
resp.addCookie(cookie);
}else{
session.setMaxInactiveInterval(60*30);
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(-1); //cookie会在会话结束时销毁(默认值)
cookie.setPath("/");
resp.addCookie(cookie);
}
//回话T出
if (servletContext.getAttribute(name)!=null){
HttpSession httpsession = (HttpSession)servletContext.getAttribute(name);//干掉上一个session
httpsession.invalidate();
servletContext.removeAttribute(name);
}
servletContext.setAttribute("name",session); //将自己的session放进去
req.getSession().setAttribute("user",user);
resp.sendRedirect("/index");
} catch (Exception e) {
e.printStackTrace();
//登陆失败像request作用域中存放错误信息
req.setAttribute("msg",e.getMessage());
//然后跳转到登录界面继续登录
req.getRequestDispatcher("login.jsp").forward(req,resp);
}
}
public void logout(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String name = req.getParameter("name");
req.getSession().invalidate(); //干掉session
ServletContext servletContext = req.getServletContext();
servletContext.removeAttribute(name); //移除
resp.sendRedirect("/login.jsp");
}
}
同理,文件的上传与下载也是这样改造:
package com.blb.servlet;
import com.blb.entity.User;
import com.blb.service.IUserService;
import com.blb.service.impl.IUserServiceImpl;
import com.blb.utils.IOUtils;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.*;
import java.net.URLEncoder;
@MultipartConfig
@WebServlet("/file/*")
public class FileServlet extends BaseServlet{
IUserService iUserService = new IUserServiceImpl();
/**
* 上传文件
* @param req
* @param resp
* @throws IOException
* @throws ServletException
*/
public void upload(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
Part part = req.getPart("file");
User user = (User) req.getSession().getAttribute("user");
File file = new File("F:/upload/" + user.getName() + "/");
if (!file.exists()){file.mkdirs();}
String fileName = part.getSubmittedFileName();
InputStream is = part.getInputStream();
FileOutputStream os = new FileOutputStream(file.getPath()+"/"+ fileName);
IOUtils.upload(is, os);
resp.sendRedirect("/index");
}
/**
* 显示文件
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
public void down(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
User user = (User) req.getSession().getAttribute("user");
String[] list = new File("F:/upload/" +user.getName()+"/").list();
req.getSession().setAttribute("filename",list);
resp.sendRedirect("/download.jsp");
}
/**
* 下载文件
* @param req
* @param resp
* @throws IOException
*/
public void download(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//获取文件名
String filename = req.getParameter("name");
//获取当前对象
User user = (User) req.getSession().getAttribute("user");
//构建输入输出流对象
FileInputStream is = new FileInputStream("F:/upload/" +user.getName()+"/"+ filename);
//获取文件大小
int len = is.available();
ServletOutputStream os = resp.getOutputStream();
//告诉浏览器文件类型是二进制
resp.setContentType("application/octet-stream");
//告诉浏览器文件名
resp.setHeader("content-disposition","attachment;filename="+ URLEncoder.encode(filename,"utf-8"));
//告诉浏览器文件大小
resp.setContentLength(len);
IOUtils.upload(is,os);
}
/**
* 显示图片
* @param req
* @param resp
* @throws IOException
*/
public void showImg(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//获取文件名
String imgName = req.getParameter("img");
User user = (User) req.getSession().getAttribute("user");
//构建输入输出流对象
FileInputStream is = new FileInputStream("F:/upload/img/"+ imgName);
ServletOutputStream os = resp.getOutputStream();
resp.setContentType("image/jpg");
IOUtils.upload(is,os);
}
/**
* 上传头像
* @param req
* @param resp
* @throws IOException
* @throws ServletException
*/
public void uploadImg(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
Part part = req.getPart("img");
User user = (User)req.getSession().getAttribute("user");
String submittedFileName = part.getSubmittedFileName();
InputStream is = part.getInputStream();
FileOutputStream os = new FileOutputStream("F:/upload/img/"+ submittedFileName);
IOUtils.upload(is, os);
iUserService.uploadImg(user.getId(),part.getSubmittedFileName());
resp.sendRedirect("/index");
}
}
这样改造完之后,servlet的数量少了很多。也满足了代码的高内聚低耦合的原则。