天天看點

關于BaseServlet

BaseServlet 是項目中所有servlet的父類,作用是為了讓一個servlet可以同時處理多個請求,因為我們之前比如說完成對于商品的增删改查的時候,每一個需求就要建立一個servlet,這樣會顯得很臃腫,是以就用到BaseServlet;采用的是反射的技術

步驟 :1. 寫一個BaseServlet繼承HttpServlet;

   2.重寫service方法

package com.qf.web.servlet;
 
 
import java.io.IOException;
import java.lang.reflect.Method;
 
 
import javax.management.RuntimeErrorException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
 
public class BaseServlet extends HttpServlet {
 
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
// 1.擷取表單中的路徑後面帶的參數method=方法名中的方法名
String m = request.getParameter("method");
 
// 如果擷取的路徑後面沒有帶method這個參數的話,就預設跳轉到首頁,具體原因請看後面的解釋
if (m == null || m.trim().isEmpty()) {
 
m = "index";// 把名稱定為index,然後在這個類中寫一個index方法;所有繼承這個類的servlet都可以重寫這個方法;
 
}
 
/*
* this為目前調用這個方法的類,即這個BaseServlet的子類,而不是指這個BaserServlet;誰調用誰就是這個this
*
* this.getClass()獲得目前這個類的對象 getMethod(方法名,後面的HttpServletRequest.class,
* 
* HttpServletResponse.class是固定參數,固定寫法);
*/
 
 
// 獲得方法對象
Method method = this.getClass().getMethod(m, HttpServletRequest.class, HttpServletResponse.class);
 
// 調用這個請求後處理的方法傳回的字元串,指的是要轉發還是重定向的路徑(在子類servlet傳回的)
String text = (String) method.invoke(this, request, response);
 
//如果傳回字元串為null,說明沒有要求我做轉發還是重定向,是以我什麼都不用做
if(text==null||text.trim().isEmpty()) {
return;
}
 
//字元串.contains("子字元串")  字元串是否包含該子字元串 
if(!text.contains(":")) {
 
//比如傳回的是"/index.jsp"
 
//如果不包含,說明沒規定要轉發還是重定向,是以預設轉發;記得一定要寫forward
request.getRequestDispatcher(text).forward(request, response);
 
}else {
 
//比如text傳回的是 "f:/index.jsp"  或 "r:"+request.getContextPath()+"/index.jsp"
 
int index=text.indexOf(":");//如果有包含的話擷取:在這個字元串中第一次出現的索引
 
//從0下标開始截取到:的前一個下标為止,(包前不包後) 擷取标志f/r
String bz = text.substring(0, index);//從字元串的0下标開始截取到指定的索引(包前不包後)
 
//從冒号的下标1+1為2的下标擷取路徑  /index.jsp 
String path = text.substring(index+1);//從指定索引開始截取字元串,直到末尾
 
//如果标志是f的話,就是要轉發
if (bz.equalsIgnoreCase("f")) {//忽略大小寫,比如F/f
 
request.getRequestDispatcher(path).forward(request, response);//一直忘了寫forward
 
//如果标志是r的話,就是要重定向
}else if (bz.equalsIgnoreCase("r")) {
 
response.sendRedirect(path);
 
}else {//這個else可以不寫的
 
throw new RuntimeException("您的指令有誤");
}
 
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 
 
}
 
//在BaseServlet中寫index方法,那麼繼承他的所有servlet都可以重寫該方法;
//這裡主要是為了上面的第一個if語句預設跳轉到首頁準備的
 
public String index(HttpServletRequest request,HttpServletResponse response) {
 
return null;
}
 
 
}      

3.以前我們在jsp頁面的時候隻要直接寫跳轉的路徑即可,比如

<form action="${pageContext.request.contextPath() } / loginServlet "></form>      

然後在寫個loginServlet完成使用者登入操作就可以了,但是注冊的時候我們還得寫個注冊的servlet,

登出又是一個servlet,這樣就會很麻煩,很臃腫. 是以我們以後隻要把路徑改為:

<form action="${pageContext.request.contextPath() } / userServlet ? method=login">      

 記得跟上method=方法名

4.然後我們隻要寫一個userServlet,裡面收入關于使用者登入/注冊/登出等有關的方法即可;以注冊為例.(注意點: 方法中的參數固定為HttpServletRequest,HttpServletResponse)

在index.jsp頁面中有個注冊的按鈕(其他代碼省略)

<form action="${pageContext.request.contextPath() } / user?method=registUI " method="post">
<input  type="submit" value="注冊">
</form>
      

 其實我們平時都是直接跳轉到注冊的jsp的.但是現在不那麼做了,說是因為這樣會不安全.是以我們也是跳轉到路徑為/user的UserServlet中的registUI方法中.在這裡面完成跳轉到jsp頁面;

以下為路徑/user的UserServlet的代碼;

public class UserServlet extends BaseServlet {
public String registUI(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
return "/jsp/register.jsp";//這個沒有寫 f:還是 r:字首的話,在上面的BaseServlet中是預設按轉發處理的;
}      

這裡面還有一個關于使用者注冊的方法

public String  register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
 
//封裝資料
User user=new User();
   try {
            //因為我資料庫裡有個使用者id,而這個id不是使用者在注冊的時候自己填的,而是背景自動生成的,是以我們需要這這裡設定一下随機生成 id; 
 
 
              user.setUid(UUID.randomUUID().toString().replace("-", "").toUpperCase());
 
 
//code是激活碼,使用者注冊後要通過郵箱激活碼激活;這個也是随機生成的
 
 
     user.setCode(UUID.randomUUID().toString().replace("-", "").toUpperCase());
 
 
//對使用者密碼進行加密處理,用到的是md5算法加密,具體代碼見下面
 
 
             user.setPassword(MD5Utils.md5(user.getPassword()));
 
 
  //因為注冊頁面有個生日選項,在user這個javabean中,資料類型為Date(一般建議為string類型,就不需要轉換了)
            ConvertUtils.register(new DateLocaleConverter(), Date.class);//這個是BeanUtils提供的方法,這一行的代碼是固定的,無須改動
 
BeanUtils.populate(user, request.getParameterMap());
 
 
//調用業務邏輯
UserService us=new UserServiceImpl();
us.add(user);
 
 
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 
   return "r:"+request.getContextPath()+"/success.jsp";//傳回要BaseServlet做重定向處理
 
 
 
 
}      

中間省略user實體類, UserService及其實作類, UserDao的代碼,直接上連庫代碼,即UserDaoImpl中的操作

public class UserDaoImpl implements UserDao {
 
 
@Override
public void add(User user) throws Exception {
 //c3p0Utils是自己寫的資料池操作
          QueryRunner qr=new QueryRunner(C3P0Utils.getDatasource());
          
          //向資料庫裡插入資料(預編譯寫法)
 String sql="insert into users values(?,?,?,?,?,?,?,?,?,?)";
 
 //寫入實際參數
 qr.update(sql, user.getUid(),user.getUsername(),user.getPassword(),user.getName(),user.getEmail(),user.getTelephone(),user.getBirthday(),user.getSex(),user.getState(),user.getCode());
 
 
}
 
 
}      

最下面是對于md5算法的代碼

public class MD5Utils {
 
public static String md5(String plainText) {
byte[] secretBytes = null;
try {
secretBytes = MessageDigest.getInstance("md5").digest(plainText.getBytes());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("找不到md5算法");
}
String md5code = new BigInteger(1, secretBytes).toString(16);
for (int i = 0; i < 32 - md5code.length(); i++) {
md5code = "0" + md5code;
}
return md5code;
}
 
 
}      

參考資料:

https://blog.csdn.net/cyuc0425/article/details/79171711

https://blog.csdn.net/wn084/article/details/79009322