1.項目搭建
1.項目搭建完後,配置全站亂碼過濾器
GenericEncodingFilter.java:作用是根據請求方式,處理亂碼,同時設置返回類型
- post方式:手動轉碼
- get方法:自動轉碼
切記,僅僅複製GenericEncodingFilter.java是沒用的,還要去web.xml中進行配置,對所有請求進行過濾
<filter>
<filter-name>GenericEncodingFilter</filter-name>
<filter-class>cn.itcast.filter.GenericEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>GenericEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.採用通用BaseServlet
之前我們一個service中只有get和post方法,一個請求對應一個servlet,這就造成了servlet太多了
解決方法:我們希望將一個servlet管理相關一個對象的所有功能(註冊/登陸/校驗用戶名/使用一個UserServlet來解決)
首先將register.jsp的表單提交地址改爲
<form id="registForm" action="${root}/user?methodName=register" method="post" name="formUser"
實現/user對應的UserServlet
public class UserServlet extends HttpServlet {
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String methodName = request.getParameter("methodName");
if(methodName.equals("register")){
register(request,response);
}else if(methodName.equals("login")){
login(request,response);
}else{
throw new RuntimeException("當前請求的方法不存在!");
}
}
protected void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("register執行了");
}
protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("login執行了");
}
}
此時我們發現,如果這個servlet中需要處理的請求很多,則需要很多不用的方法,在service中也要寫很多if…else判斷,那有沒有可能就通過一段代碼就找到具體的方法呢?
答案是:反射
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String methodName = request.getParameter("methodName");
try {
Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this, request,response);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2.實現註冊功能
2.1 註冊分析
2.2 代碼實現
2.2.1 修改前端註冊頁面(register.jsp),採用baseServlet的方式向服務器發送請求
此時當我們在註冊頁面填寫好信息,提交後,就會發送如下請求
2.2.2 UserServlet實現
public class UserServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String methodName = request.getParameter("methodName");
try {
Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this, request,response);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//註冊
protected void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.獲取參數,校驗(前臺雖然已經有了校驗了,但是在後端也要進行校驗)
String email = request.getParameter("email");
if(StringUtils.isBlank(email)){
//用戶名爲空
request.setAttribute("msg", "用戶不能爲空");
request.getRequestDispatcher("/register.jsp").forward(request, response);
return;
}
String nickname = request.getParameter("nickname");
if(StringUtils.isBlank(nickname)){
//用戶名爲空
request.setAttribute("msg", "暱稱不能爲空");
request.getRequestDispatcher("/register.jsp").forward(request, response);
return;
}
String password = request.getParameter("password");
if(StringUtils.isBlank(password)){
//用戶名爲空
request.setAttribute("msg", "密碼不能爲空");
request.getRequestDispatcher("/register.jsp").forward(request, response);
return;
}
String confirm_password = request.getParameter("confirm_password");
if(StringUtils.isBlank(confirm_password)){
//用戶名爲空
request.setAttribute("msg", "確認密碼不能爲空");
request.getRequestDispatcher("/register.jsp").forward(request, response);
return;
}
String captcha = request.getParameter("captcha");
if(StringUtils.isBlank(confirm_password)){
//用戶名爲空
request.setAttribute("msg", "驗證碼不能爲空");
request.getRequestDispatcher("/register.jsp").forward(request, response);
return;
}
//2.判斷兩次輸入的密碼是否一致
if(!password.equals(confirm_password)){
request.setAttribute("msg", "兩次密碼不一致");
request.getRequestDispatcher("/register.jsp").forward(request, response);
return;
}
//3.驗證驗證碼
String code = (String) request.getSession().getAttribute("code");
if(!captcha.equals(code)){
request.setAttribute("msg", "驗證碼不一致");
request.getRequestDispatcher("/register.jsp").forward(request, response);
return;
}
//4.將數據封裝到User對象
User user = new User();
try {
BeanUtils.populate(user, request.getParameterMap());
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
UserService service = new UserServiceImpl();
int info = service.register(user);
if(info == 1){
//保存成功,跳轉到登錄頁面
response.sendRedirect(request.getContextPath()+"/login.jsp");
return;
}else if(info == -1){
//已經存在
request.setAttribute("msg", "用戶已經存在");
request.getRequestDispatcher("/register.jsp").forward(request, response);
return;
}else{
request.setAttribute("msg", "服務器忙!!!");
request.getRequestDispatcher("/register.jsp").forward(request, response);
return;
}
}
protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("login執行了");
}
}
業務邏輯:
1.首先是對前臺傳遞的參數進行非空校驗,前臺雖然已經有了校驗了,但是後臺必須再進行校驗,如果有一欄是空的,就直接將錯誤信息,保存到request中,返回到註冊頁面
2.判斷兩次輸入的密碼是否一致,不一致的話講錯誤信息返回到註冊界面
3.校驗驗證碼,驗證碼是由jsp頁面生成的(之前講過如果在servlet中生成驗證碼,jsp也是servlet),且在validatecode.jsp中,再生成驗證碼後,會將驗證碼的字符串存入session
所以我們只要通過session中的驗證碼和前臺提交的驗證碼做比較就可以了
4.將數據封裝到user對象中,調用業務層,執行註冊方法,有int類型的返回值
- 返回值1:保存用戶成功,重定向到登錄頁面
- 返回值-1:用戶已存在,將錯誤信息返回到註冊頁面
- 返回值2:表示在保存的過程中,出了異常了,返回一個服務器忙
注意:beanutils需要導入不少包,並不單單commons-beanutils-1.9.2.jar
2.2.3 UserService實現
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override
public int register(User user) {
try{
//1.校驗用戶名是否存在
User findByName = userDao.findByName(user.getEmail());
if(findByName != null){
//表示用戶已經存在,返回-1
return -1;
}else{
//不存在,設置角色,激活狀態,
user.setRole("user");
//設置狀態,-1是未激活,此處按理說是-1,然後通過郵件去把-1改爲1
user.setState(1);
//設置激活碼
String code = UUIDUtils.getUUID()+UUIDUtils.getUUID();
user.setCode(code);
//用戶密碼加密
user.setPassword(MD5Utils.getPassword(user.getPassword()));
userDao.register(user);
//發送激活郵件,用戶點擊鏈接後,才激活賬戶
//String path = "http://localhost:8080/estore/user?methodName=active&code="+code;
//String emailMsg = "恭喜你,註冊成功,請點擊下面的鏈接進行激活<a href='"+path+"'>"+path+"</a>";
//MailUtils.sendMail(user.getEmail(), "商城激活郵件", emailMsg);
return 1;
}
}catch(Exception e){
return 2;
}
}
}
1.通過郵件地址(用戶名)去校驗用戶是否存在,如果查到的對象不爲null,表示存在,此時只要返回-1
2.如果用戶不存在,表示可以註冊,我們首先設置用戶的角色(權限),激活狀態(剛註冊爲-1),激活碼,還有給密碼加密,之後我們通過dao層去註冊用戶
3.剛剛註冊的用戶,激活狀態還是-1,此時我們就通過郵件發送激活鏈接,發送到用戶留的郵件地址,當我們點擊鏈接後,修改code所對應的user的激活狀態爲1
注意點
1.用戶註冊是提供的密碼,一定要加密後再存入數據庫.因爲這種加密方式是單向的.我們之後登錄時,再用登錄密碼加密後去跟註冊時的加密密碼進行匹配
2.通過QueryRunner查找對象/集合,沒找到返回的是null
2.2.4 UserDao實現
public class UserDaoImpl implements UserDao {
private QueryRunner qr = new QueryRunner(DBUtils.getDataSource());
@Override
public User findByName(String email) {
String sql = "select * from user where email = ?";
try {
return qr.query(sql, new BeanHandler<User>(User.class),email);
} catch (SQLException e) {
throw new RuntimeException("查詢用戶失敗");
}
}
@Override
public void register(User user) {
String sql = "insert into user values (null,?,?,?,?,?,?)";
try {
qr.update(sql, user.getEmail(),user.getNickname(),user.getPassword()
,user.getRole(),user.getState(),user.getCode());
} catch (SQLException e) {
throw new RuntimeException("註冊用戶失敗");
}
}
}