优化Servlet
优化servlet:与用户有关的servlet放到一起(与用户有关的:注册、登录、退出),像service一样,与用户有关的service放到UserService中,这样便于管理。
减少servlet的数量,现在是一个功能一个servlet,将其优化为一个模块一个servlet。相当于数据库中一张表一个servlet,在servlet中提供不同的方法,完成用户的请求。
(1)
写一个BaseServlet继承HttpServlet来完成方法的分发。
再让其他的Servlet继承BaseServlet。
在BaseServlet中的service()方法中完成方法的分发。
BaseServlet:
@WebServlet("/BaseServlet")
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//完成方法的分发
//1.获取请求路径
String url=request.getRequestURI(); //返回的是 /travel/user/add等
System.out.println("请求url:"+url); // /travel/user/add
//2.获取方法名称
String methodName=url.substring(url.lastIndexOf('/')+1);
System.out.println("方法名称:"+methodName);
//3.获取方法对象Method
//this:谁调用我?我代表谁
System.out.println(this); //UserServlet的对象
try {
//getDeclaredMethod方法是忽略访问权限修饰符,获取方法,包括私有的方法都可以获取到
Method method=this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
//4.执行方法
//暴力反射(在获取getDeclaredMethod方法之前需要先暴力反射,可以执行访问权限修饰符不是public的方法了,哪怕是私有的也可以访问到)
method.setAccessible(true);
method.invoke(this, request,response);
} catch (NoSuchMethodException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
问题:由于UserServlet中方法的权限修饰符是protected,所以需要用getDeclaredMethod方法和暴力反射来忽略权限修饰符,可以执行访问权限修饰符不是public的方法了,哪怕是私有的也可以访问到。
但是最好的方法不是像以上那样解决,最好将权限修饰符改成public ,将getDeclaredMethod方法改成getMethod方法,注释掉暴力反射。
@WebServlet("/BaseServlet")
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//完成方法的分发
//1.获取请求路径
String url=request.getRequestURI(); //返回的是 /travel/user/add等
System.out.println("请求url:"+url); // /travel/user/add
//2.获取方法名称
String methodName=url.substring(url.lastIndexOf('/')+1);
System.out.println("方法名称:"+methodName);
//3.获取方法对象Method
//this:谁调用我?我代表谁
System.out.println(this); //UserServlet的对象
try {
//获取方法
Method method=this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
//4.执行方法
//暴力反射(在获取getDeclaredMethod方法之前需要先暴力反射,可以执行访问权限修饰符不是public的方法了,哪怕是私有的也可以访问到)
//method.setAccessible(true);
method.invoke(this, request,response);
} catch (NoSuchMethodException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
UserServlet:
@WebServlet("/user/*")
public class UserServlet extends BaseServlet {
public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
public void find(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
注:@WebServlet("/user/*")而不是@WebServlet("/user")
(2)
将其他与用户相关的servlet整合到UserServlet中,就是将其他Servlet中的代码粘到UserServlet相应的方法中去:
UserServlet:
@WebServlet("/user/*")
public class UserServlet extends BaseServlet {
private UserService service=new UserServiceImpl();
/*
* 注册功能,对应RegistServlet
*/
public void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//response.getWriter().append("Served at: ").append(request.getContextPath());
//不用在处理编码问题了,因为写了一个处理编码的filter(过滤器)
//验证校验
String check=request.getParameter("check");
//从session获取验证码
HttpSession session=request.getSession();
String check_server=(String)session.getAttribute("CHECKCODE_SERVER");
session.removeAttribute("CHECKCODE_SERVER"); //为了保证验证码只能使用一次
//比较
if(check_server==null|| !check_server.equalsIgnoreCase(check)) {
//验证码错误
ResultInfo info=new ResultInfo();
info.setFlag(false);
info.setErrorMsg("验证码错误");
//将info对象序列化json
ObjectMapper mapper=new ObjectMapper();
String json=mapper.writeValueAsString(info);
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);
return;
}
//1.获取数据
System.out.println("2处");
Map<String, String[]> map = request.getParameterMap();
//2.封装数据
User user=new User();
try {
BeanUtils.populate(user, map);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//3.调用service完成注册
//UserService service=new UserServiceImpl();
System.out.println("1处");
boolean flag=service.regist(user);
ResultInfo info=new ResultInfo(); //自定义的后端返回前端结果的对象
//4.响应结果
if(flag) {
//注册成功
info.setFlag(true);
}else {
//注册失败
info.setFlag(false);
info.setErrorMsg("注册失败!");
}
//将info对象转成json
ObjectMapper mapper=new ObjectMapper();
String json = mapper.writeValueAsString(info);
//将json数据写回客户端,使用response的输出流
//设置content-type
response.setContentType("application/json;charaset=utf-8");
response.getWriter().write(json);
}
/*
* 登陆功能,对应LoginServlet
*/
public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//response.getWriter().append("Served at: ").append(request.getContextPath());
//1.获取用户名和密码,虽然只有两个数据,也可以封装成map集合
Map<String, String[]> map = request.getParameterMap();
//2.封装成User对象
User user=new User();
try {
BeanUtils.populate(user, map);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//3.调用Service查询
//UserService service=new UserServiceImpl();
User u=service.login(user);
//都使用json进行响应
ResultInfo info=new ResultInfo();
//4.判断用户对象是否为null
if(u==null) {
//用户名或密码错误
info.setFlag(false);
info.setErrorMsg("用户名或密码错误");
}
//5.判断用户是否激活
if(u!=null && !"Y".equals(u.getStatus())) {
//用户尚未激活
info.setFlag(false);
info.setErrorMsg("您尚未激活,请激活");
}
//6.判断登录成功
if(u!=null && "Y".equals(u.getStatus())) {
//登录成功
info.setFlag(true);
}
//响应数据
ObjectMapper mapper=new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(), info);
}
/*
* 查询单个对象,对应findUserServlet
*/
public void findOne(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
//response.getWriter().append("Served at: ").append(request.getContextPath());
//从session中获取登录用户,之前已经将user存入session了
Object user=request.getSession().getAttribute("user");
//将user写回客户端
ObjectMapper mapper=new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(), user);
}
/*
* 退出功能,对应exitServlet
*/
public void exit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
// TODO Auto-generated method stub
//response.getWriter().append("Served at: ").append(request.getContextPath());
//1.销毁session
request.getSession().invalidate();
//2.跳转到登录页面
response.sendRedirect(request.getContextPath()+"/login.html");
}
/*
* 激活功能,对应activeServlet
*/
public void active(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
//1.获取激活码
String code=request.getParameter("code");
//判断激活码是否存在
if(code!=null) {
//2.调用service完成激活
//UserService service=new UserServiceImpl();
boolean flag=service.active(code);
//3.判断标记,响应不同的信息
String msg=null;
if(flag) {
//激活成功
msg="激活成功,请<a href='login.html'>登录</a>";
}else {
//激活失败
msg="激活失败,请联系管理员";
}
response.setContentType("text/html;charset=utf-8");
response.getWriter().write(msg);
}
}
}
之后在将html等中涉及Servlet路径的地方改成user/方法名。
比如login.html中
之前:
<script>
$(function(){
//1.给登录按钮绑定单击事件
$("#btn_sub").click(function(){
//2.发送ajax请求,提交表单数据
$.post("LoginServlet",$("#loginForm").serialize(),function(data){
//data:{flag:false,errorMsg:''}
if(data.flag){
//登录成功
location.href="index.html";
}else{
//登陆失败
$("#errorMsg").html(data.errorMsg);
}
})
})
});
</script>
将路径中的“LoginServlet”改成“user/login”:
<script>
$(function(){
//1.给登录按钮绑定单击事件
$("#btn_sub").click(function(){
//2.发送ajax请求,提交表单数据
$.post("user/login",$("#loginForm").serialize(),function(data){
//data:{flag:false,errorMsg:''}
if(data.flag){
//登录成功
location.href="index.html";
}else{
//登陆失败
$("#errorMsg").html(data.errorMsg);
}
})
})
});
</script>