14、用户注册登录案例

综合案例

实现用户注册、登录、列表显示的功能。符合MVC思想,使用javaee三层架构。如下图。

需要用到数据库驱动包以及BeanUtils包。就是这些commons-beanutils、commons-logging、mysql-connector-java

整个流程如下

0. 数据库连接工具类

package utils;

import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JDBCUtil {
    private static String driver;
    private static String url;
    private static String user;
    private static String password;

    // 静态代码块,随着类的加载而加载,只加载一次
    static {
        try {
            Properties prop = new Properties();
            
            
            // 下面这个是本机使用的就填写项目所在位置,但是我们是要部署到服务器的,所以获取WEB-INF/classes目录下的,注意要加"/"
            // InputStream is = new FileInputStream("/example/src/jdbc_setting.properties");
            InputStream is = JDBCUtil.class.getResourceAsStream("/jdbc_setting.properties");
            // load()接收InputStream,所以向上转型
            prop.load(is);

            driver = prop.getProperty("ClassName");
            url = prop.getProperty("url");
            user = prop.getProperty("user");
            password = prop.getProperty("password");
            Class.forName(driver);

            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(url, user, password);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("创建连接失败!");
        }
        return connection;
    }
    // 释放资源
    // 参数可能为空
    // 调用close要抛出异常,即使出现异常也能关闭
    public void close(Connection conn, Statement state, ResultSet result) {
        try {
            if (result != null) {          
                result.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (state != null) {
                state.close();
                }
            } catch (SQLException e) {
                    e.printStackTrace();
                } finally {
                     try {
                        if (conn != null) {
                            conn.close();
                        }
                    } catch (SQLException e) {
                        e.printStackTrace();
                }
            }
        }
    }
}

数据库配置文件

ClassName=com.mysql.jdbc.Driver
url=jdbc\:mysql\://localhost\:3306/example
user=root
password=admin

1. 用一个bean来封装注册用户的信息

package domain;

public class User {
    private int id;
    private String name;
    private String password;
    private String email;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", nameString=" + name + ", password=" + password + ", email=" + email + "]";
    }
    
    
}

2. 定义一个借口用来保存User

package dao;


import domain.User;

public interface UserDao {
    void save(User u);
    User getUserByName(String name);
}

2. 实现上述接口

主要实现了插入和查询功能

package dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import dao.UserDao;
import domain.User;
import utils.JDBCUtil;

public class UserDaoImple implements UserDao {

    @Override
    public void save(User u) {
        // 1. 获得连接
        Connection connection = JDBCUtil.getConnection();
        // 2. 准备sql语句
        String sql =  "INSERT INTO "+
                "`example`.`t_user` (`name`, `password`, `email`) "+
                            "VALUES "+
                              "(?, ?, ?);";
        
        // 3. 获得PreparedStatement对象,可防止sql注入
        PreparedStatement preStatement = null;
        try {
            // 先运送sql语句过去预编译
            preStatement = connection.prepareStatement(sql);
            // 4. 设置传送的参数,第一个参数是列数,从1开始
            preStatement.setString(1,  u.getName());
            preStatement.setString(2, u.getPassword());
            preStatement.setString(3, u.getEmail());
            //5. 执行sql
            int result = preStatement.executeUpdate();
            
            // 上面只对一行作用了,添加成功肯定是一行。若 != 1说明没有添加成功
            if(result != 1 ){
                throw new RuntimeException("保存用户失败!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 6. 关闭资源
            JDBCUtil.close(connection, preStatement, null);
        }
    }

    @Override
    public User getUserByName(String name) {
        User user = null;
        // 1. 获得连接
        Connection connection = JDBCUtil.getConnection();
        // 2. 写sql语句
        String sql = "SELECT * FROM t_user WHERE name = ?";
        // 3. 获得PreparedStatement
        PreparedStatement preparedStatement = null;
        try {
            preparedStatement = connection.prepareStatement(sql);
            // 4. 设置参数
            preparedStatement.setString(1, name);
            // 5. 执行查询
            ResultSet set =  preparedStatement.executeQuery();
            
            // 因为用户名唯一,结果集里只有一条,直接用if就好,可以不用while
            // 6. 将结果集封装到User
            if (set.next()) {
                user = new User();
                 user.setId(set.getInt("id"));
                user.setName(set.getString("name"));
                user.setPassword(set.getString("password"));
                user.setEmail(set.getString("email"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("查询用户失败");
        } finally {
            // 7. 关闭连接,返回User
            JDBCUtil.close(connection, preparedStatement, null);
        }
        return user;
    }

}

4. 用户注册

package service;

import dao.UserDao;
import dao.impl.UserDaoImple;
import domain.User;

public class UserService {
    
    private UserDao  userDao = new UserDaoImple();
    
    public void regist(User u) {
        // 检查用户名是否存在
        User exitsUser = userDao.getUserByName(u.getName());
        // 用户名已经被使用
        if (exitsUser != null) {
            throw new RuntimeException("用户名已经存在!");
        } else {
            // 如果这个名字没有使用,则保存
            userDao.save(u);
        }
    }   
}

5. 检查用户名和密码

package utils;

import java.util.HashMap;
import java.util.Map;

import domain.User;

public class CheckUtils {
    public static Map<String, String> checkUser(User u) {
        Map<String, String> map = new HashMap<>();
        // 验证用户名不为空,"".equals(u.getName())更好。,u.getName().equals("")如果u.getName()为null则不能调用.equals();
        if (u.getName() == null || "".equals(u.getName().trim())) {
            map.put("name", "用户名不能为空!");
        }
        // 验证密码不为空
        if (u.getPassword() == null || "".equals(u.getPassword().trim())) {
            map.put("password", "密码不能为空!");
        }
        return map;
    }
}

6. 注册的servlet

package web;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;

import domain.User;
import service.UserService;
import utils.CheckUtils;

@WebServlet("/RegistServlet")
public class RegistServlet extends HttpServlet {
    
    private UserService us= new UserService(); 
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //1 封装参数到User对象
        User user = new User();
        try {
            // 表单参数封装到user
            BeanUtils.populate(user, request.getParameterMap());
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //  检查有没有错误
        Map<String, String> errors = CheckUtils.checkUser(user);
        // 如果有错误
        if (! errors.isEmpty()) {
            request.setAttribute("errors", errors);
            // 注意是转发而不是重定向,转发过去是一次请求,还是刚才jsp页面。才能收到错误信息。
            // 如果是重定向,重新加载jsp不会收到错误信息
            request.getRequestDispatcher("/regist.jsp").forward(request, response);
            return;
        }
        // 3. 调用Service保存
        try {
            // regist方法里面throw了很多异常,要捕获
            us.regist(user);
            // 4 根据结果,跳转到对应页面,失败就转发到注册页面
        } catch (Exception e) {
            e.printStackTrace();
            request.setAttribute("error", e.getMessage());
            request.getRequestDispatcher("/regist.jsp").forward(request, response);
            return;
        }
        // 成功重定向到登录页面。request.getContextPath()获得项目名/example
        response.sendRedirect(request.getContextPath()+"/login.jsp");
        
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

7. 注册界面和登录界面

注册

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'regist.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>
  
  <body>
    <form action="/example/RegistServlet" method="post" name="form1">
        <table border="1" width="30%" >
        <tr>
            <th colspan="2" align="center" >
                 用户注册
            </th>
        </tr>
        <tr>
            <td>用户名:</td>
            <td><input type="text" name="name" /><font color="red" >${requestScope.errors.name }</font></td>
        </tr>
        
        <tr>
            <td>密码:</td>
            <td><input type="password" name="password" /><font color="red" >${requestScope.errors.password }</font></td>
        </tr>
        
        <tr>
            <td>邮箱:</td>
            <td><input type="text" name="email" /><font color="red" ></font></td>
        </tr>
        <tr>
            <td colspan="2" align="center" >
                <input type="submit" value="注册" />
            </td>
        </tr>
    </table>
</form>
<font color="red">${requestScope.error }</font>
  </body>
</html>

登录

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'login.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>
  
  <body>
    <form action="/example/LoginServlet" method="post" name="form2">
        <table border="1" width="30%" >
        <tr>
            <th colspan="2" align="center" >
                 用户登录
            </th>
        </tr>
        <tr>
            <td>用户名:</td>
            <td><input type="text" name="name" /><font color="red" >${requestScope.errors.name }</font></td>
        </tr>
        
        <tr>
            <td>密码:</td>
            <td><input type="password" name="password" /><font color="red" >${requestScope.errors.password }</font></td>
        </tr>
             
        <tr>
            <td colspan="2" align="center" >
                <input type="submit" value="登录" />
            </td>
        </tr>
    </table>
</form>
<font color="red">${requestScope.error }</font>
  </body>
</html>

8. 用户登录

UserService新增用户登录方法

    // 用户登录
    public User login(User u){
        //1 根据用户名,调用dao获得User对象
        User existU = userDao.getUserByName(u.getName());
      // 为空说明还没注册
        if(existU==null){
            //没获得到=> 用户名不存在=> 抛出异常
            throw new RuntimeException("用户名不存在!");
        }
        //2 和数据库的账户密码比对密码是否一致
        if(!existU.getPassword().equals(u.getPassword())){
            //不一致=>密码不正确=>抛出异常
            throw new RuntimeException("密码不正确!");
        }
        //3 能执行到这儿说明已经注册且登录成功。返回的是数据库中User对象
        return existU;
    }

LoginServlet

package web;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;

import domain.User;
import service.UserService;
import utils.CheckUtils;

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    
    private UserService us = new UserService();
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 避免乱码
        request.setCharacterEncoding("UTF-8");
        User u = new User();
        try {
            BeanUtils.populate(u, request.getParameterMap());
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // 2.非空校验
    Map<String,String> errors = CheckUtils.checkUser(u);
        if(errors.size()>0){
            request.setAttribute("errors", errors);
            request.getRequestDispatcher("/login.jsp").forward(request, response);
            return;
        }
        // 3.调用Service
        User existU = null;
        try {
            existU= us.login(u);
        } catch (Exception e) {
            e.printStackTrace();
            request.setAttribute("error", e.getMessage());
            request.getRequestDispatcher("/login.jsp").forward(request, response);
            return;
        }
        // 4.向session中加入登录标识, 登录用session可以保持用户的状态,不掉线
        request.getSession().setAttribute("user", existU);
        // 5.重定向到列表显示servlet
        response.sendRedirect(request.getContextPath()+"/ListServlet");
    }
  
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

休息一下,看下request.getRequestDispatcherresponse.sendRedirect为什么一个是request的方法,一个是response的方法?

  • 转发是向服务器请求,然后服务器内部进行转发操作,因为是请求所以用request
  • 重定向是浏览器的动作,响应新的页面给用户。所以用的是response

9. 登录后显示用户数据列表

UserDao里新增接口方法

List<User> getAllUsers();

同时UserDaoImple去实现

@Override
    public List<User> getAllUsers() {
        List<User> users = new ArrayList<>();
        // 1. 获得连接
        Connection connection = JDBCUtil.getConnection();
        // 2. 写sql语句
        String sql = "SELECT * FROM t_user";
        // 3. 获得PreparedStatement
        PreparedStatement preparedStatement = null;
        try {
            preparedStatement = connection.prepareStatement(sql);
            ResultSet set = preparedStatement.executeQuery();

            // 因为用户名唯一,结果集里只有一条,直接用if就好,可以不用while
            // 6. 将结果集封装到User
            while (set.next()) {
                User user = new User();
                user.setId(set.getInt("id"));
                user.setName(set.getString("name"));
                user.setPassword(set.getString("password"));
                user.setEmail(set.getString("email"));
                users.add(user);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("查询用户列表失败");
        } finally {
            // 7. 关闭连接,返回User
            JDBCUtil.close(connection, preparedStatement, null);
        }
        return users;
    }

登录成功后的列表显示需要使用servlet从数据库取得用户数据,然后转发到list.jsp显示

package web;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import domain.User;
import service.UserService;

@WebServlet("/ListServlet")
public class ListServlet extends HttpServlet {

    private UserService userService = new UserService();

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 1. 校验用户是否已经登录
        User user = (User) request.getSession().getAttribute("user");
        // 如果用户下线了, 重定向到登录界面。这里就不是转发了。因为login里面无需接收诸如错误等信息
        if (user == null) {
//          response.sendRedirect(request.getContextPath()+"/login.jsp");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
            return;
        }
        // 调用Service获取所有用户
        List<User> userList = userService.getAllUsers();
        // 转发到jsp显示, 设置属性方便forEach遍历
        request.setAttribute("list", userList);
        request.getRequestDispatcher("WEB-INF/page/list.jsp").forward(request, response);;
        return;
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

lsit.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'list.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>
  
  <body>
    <h1>用户列表</h1>
        <div>欢迎回来!${sessionScope.user.name}</div> <br>
        <a href="/example/LoginoutServlet">退出登录</a>
        <table border="1">
            <tr>
                <th>id</th>
                <th>用户名</th>
                <th>邮箱</th>
            </tr>
            <c:forEach items="${requestScope.list}" var="user" >
                <tr>
                    <td>${pageScope.user.id }</td>
                    <td>${pageScope.user.name }</td>
                    <td>${pageScope.user.email }</td>
                </tr>
            </c:forEach>
        </table>
  </body>
</html>

10. 用户退出登录

  1. 销毁当前的session
  2. 重定向到登录界面

在list.jsp中加入一句

<a href="/example/LoginoutServlet">退出登录</a>

新增一个LoginoutServlet,用户点击上面的超链接后,跳转到这个servlet

package web;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/LoginoutServlet")
public class LoginoutServlet extends HttpServlet {
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 销毁session
        request.getSession().invalidate();
        // 重定向到登录页面让其他用户进行登录
        response.sendRedirect(request.getContextPath() + "/login.jsp");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

至此,小案例完成。

题外话,lsit.jsp为什么不放在WebRoot下?

  • 放在根目录下,用户可以直接输入地址访问。而这时我们登录后才可以看到的界面。所以不能暴露出来让用户直接跳过登录步骤。
  • 就算是放在根目录下,因为没有servlet传过来的userList属性。数据也是空的,毫无意义。

看下截图

用户没有输入账号和密码时

用户注册一个已经存在的用户名时

账号和密码不对应时

成功登录时候


by @sunhaiyu

2017.4.12

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,296评论 18 399
  • 一. Java基础部分.................................................
    wy_sure阅读 3,731评论 0 11
  • 这部分主要是与Java Web和Web Service相关的面试题。 96、阐述Servlet和CGI的区别? 答...
    杂货铺老板阅读 1,344评论 0 10
  • 如果想要在LinearLayout中设置居中,需要用到gravity android:gravity: take...
    STFocus阅读 6,202评论 0 0