为您推荐:
精华内容
最热下载
问答
  • 5星
    19.23MB qq_29777207 2020-12-08 20:23:01
  • 之前一直没时间回复大家,抱歉,现在已经把Demo放在Github上面了... 欢迎star ... 一、主要内容 ... 以手机登录为例,实现与数据库交互。 分成两个项目:前端(android 简易界面),后端(数据库操作) 二、开...

    之前一直没时间回复大家,抱歉,现在已经把Demo放在Github上面了。

    欢迎star

    https://github.com/Tianweidadada/LoginDemoReposity

     

    一、主要内容

        以手机登录为例,实现与数据库交互。

                    

            分成两个项目:前端(android 简易界面),后端(数据库操作)

     

    二、开发工具

        android studio 3.1, eclipse(支持web),Mysql数据库, android手机(one plus 3)

     

     

     

    三、安装Mysql

                  

        1 自行下载安装,并在cmd窗口测试是否成功。

        2下载Navicat (一种可视化工具帮助建立数据库,表等操作)

        3下载mysql-connector-java-5.1.45(版本不一定一样,这是连接数据库的同一接口)

    四、下载并配置Tomcat

        1到apche官网下载 : apache-tomcat-8.5.28 

        2

     

    五、搭建web服务器

     

        1建立web工程:

                在eclipse下新建工程Dynamic Web Project(建立过程网上很多)

        2把之前下载的mysql-connector-java-5.1.45放在工程的WebContent->WEB-INF->lib下面

        并把这个包:mysql-connector-java-5.1.45-bin.jar 加入到路径中(右键BuildPath->configur )

     

     

    此外 当我只加了这么一个路径时候发现还是报错:

     java连接mysql :No Suitable Driver Found For Jdbc 

    之后我又添加到了一个路径:在上面快捷工具栏(图标那里)找见 Run Configuritions 把刚才的jar包再次添加这样就解决了这个错误(如果直接加入jar包后没有问题就最好了)

        

    3、控制台下找到Servers 

    下面有Tomcat v8.5 右键打开 找到Properties 进入

     

     

        

       打开Properties后是这样

     

     

    注意到 Switch Location

    这里把路径设置为你下载好的Tomcat 目录

     

     

    之后在项目下面看Servers多出了下面的一行

    并选择右侧红线圈住的那个选项 保存设置

    (这里做了这么多是为了使用自己的Tomcat ,系统也自带了Tomcat 插件,不过我还是喜欢用自己下载的)

     

     

    最后、在Java Resource下面 新建servlet(右键 选择建立servlet  其中 servlet名字 就默认设置为/UserServlet)

     

    服务器基本搭建完成了,可以输入 http://localhost:8080/LoginDemo/UserServlet 检验一下

    其中LoginDemo改为你的项目名称,UserServlet为刚才建立的servlet名

     

     

    六、后端代码实现:

     

     

    1、连接数据库(数据库与表自行建立)这里使用我的数据库名为logindemo

    这里连接的都是固定的操作,只是数据库名字,账号,密码不一样罢了

    package com.zhangwei.util;
    
    /**
     * Created by zhangwei on 2018/3/8.
     */
    
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class DBUtil{
        private static Connection conn;
        private static final String URL = "jdbc:mysql://127.0.0.1:3306/logindemo";//数据库名字改为你的
        private static final String USERNAME = "root";//改为你的
        private static final String PASSWORD = "123";//改为你的
        static{
            try{
                Class.forName("com.mysql.jdbc.Driver");
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
        public static Connection getConn(){
            try{
                conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            return conn;
        }
        public static void closeConn(){
            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
    
            }
        }
    
    }
    
    

     

    2、数据库操作处理登录验证

    package com.zhangwei.dao;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import com.zhangwei.entity.UserInfo;
    import com.zhangwei.util.DBUtil;
    
    public class UserDAO {
    	
    	public boolean queryUser(UserInfo userinfo){
    		Connection conn = DBUtil.getConn();
    		String sql="select * from t_user where username=? and password=?";
    		
    		try {
    			PreparedStatement ps = conn.prepareStatement(sql);
    			ps.setString(1, userinfo.getUsername());
    			ps.setString(2, userinfo.getPassword());
    			ResultSet rs = ps.executeQuery();
    			if(rs.next()){
    				return true;
    			}else{
    				return false;
    			}
    		} catch (SQLException e) {
    			e.printStackTrace();
    			return false;
    		}finally{
    			DBUtil.closeConn();
    		}
    		
    	}
    }
    

     

     

    3、在Java Resource下面 新建servlet(右键 选择建立servlet  其中 servlet名字 就默认设置为/UserServlet)

    package com.zhangwei.servlet;
    
    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;
    
    import com.zhangwei.service.UserService;
    
    /**
     * Servlet implementation class UserServlet
     */
    @WebServlet("/UserServlet")
    public class UserServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
    	UserService userService = new UserService();
    	
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		this.doPost(request, response);
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		request.setCharacterEncoding("utf-8");
    		response.setCharacterEncoding("utf-8");
    		response.setContentType("text/plain;charset = utf-8");
    		response.setHeader("Content-type", "text/html;charset=utf-8");
    		String username = request.getParameter("username");
    		String password = request.getParameter("password");
    		if(userService.login(username, password)) {
    			response.getOutputStream().write(("登录成功...\n用户: " + username + "\n密码: " + password).getBytes("utf-8"));
    		}
    		else {
    			response.getOutputStream().write(("登录失败...\n请检查用户名和密码是否正确").getBytes("utf-8"));
    		}
    	}
    
    }
    

     

    这里的UserService用于查询操作

     

    package com.zhangwei.service;
    
    import com.zhangwei.dao.UserDAO;
    import com.zhangwei.entity.UserInfo;
    
    public class UserService {
    	
    	UserDAO userDAO = new UserDAO();
    	public boolean login(String username, String password) {
    		UserInfo userInfo = new UserInfo();
    		userInfo.setUsername(username);
    		userInfo.setPassword(password);
    		return userDAO.queryUser(userInfo);
    	}
    	
    }
    

     

    七、android 端操作

     

     

    1简单的界面 用于反馈

     

    package com.zhangwei.logindemo;
    
    import android.os.Build;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.zhangwei.logindemo.service.LoginService;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener{
        private Button sendRequest;
        private TextView showResponse;
        private EditText etUsername;
        private EditText etPassword;
      //  private EditText etResult;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
    
        }
        private void initView(){
            sendRequest = (Button)findViewById(R.id.send_request);
            showResponse = (TextView) findViewById(R.id.tv_show_response);
            etUsername = (EditText)findViewById(R.id.et_username);
            etPassword = (EditText)findViewById(R.id.et_password);
            sendRequest.setOnClickListener(this);
        }
        @Override
        public void onClick(View v){
            switch (v.getId()){
                case R.id.send_request:
                    Toast.makeText(this,"正在提交请求",Toast.LENGTH_LONG).show();
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            String username = etUsername.getText().toString();
                            String password = etPassword.getText().toString();
                            //final String response = LoginService.loginByGet(username,password);
                            final String  response = LoginService.loginByPost(username,password);
                            if(response != null){
                                showResponse(response);
                            }else{
                                showResponse("请求失败....");
                            }
    
                        }
                    }).start();
            }
        }
    
        private void showResponse(final  String response){
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    showResponse.setText(response);
                }
            });
        }
    }
    

     

    2、android 发送服务器请求

     

    package com.zhangwei.logindemo.service;
    
    /**
     * Created by zhangwei on 2018/3/10.
     */
    
    import com.zhangwei.logindemo.Util.StreamTools;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.ProtocolException;
    import java.net.URL;
    import java.net.URLEncoder;
    /*该类演示了四种方法提交数据到服务器,并将服务器解析后的数据以字符串的形式返回*/
    public class LoginService {
        /**
         *
         * @param username
         * @param password
         * @return
         */
        public static String loginByGet(String username,String password){
            try {
                //提交数据到服务器
                //拼装路径
                String path = "http://192.168.19.115:8080/LoginDemo/UserServlet?username="
                        + URLEncoder.encode(username,"UTF-8") + "&password=" + URLEncoder.encode(password,"UTF-8");
                URL url = new URL(path);
    
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();//打开连接
    
                conn.setRequestMethod("GET");//设置请求方式为get
    
                conn.setConnectTimeout(5000);//设置连接超时时间为5秒
    
                int code = conn.getResponseCode();//获得请求码
                if(code == 200){
                    InputStream is = conn.getInputStream();
                    String text = StreamTools.readInputStream(is);
                    return text;
                }else{
                    return null;
                }
    //            return null;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
    
    //这里提交的路径一定要写准确,填写你当前所在局域网的ip + 项目名 + Servlet Url
        public static String loginByPost(String username,String password){
            try {
                String path = "http://192.168.19.115:8080/LoginDemo/UserServlet";
                URL url = new URL(path);
                HttpURLConnection conn =  (HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(8000);
                conn.setReadTimeout(8000);
                conn.setRequestMethod("POST");
                String data = "username="+URLEncoder.encode(username)+"&password="
                        +URLEncoder.encode(password);
                System.out.println(data);
                conn.setRequestProperty("Content=Type", "application/x-wwww-form-urlencoded");
                conn.setRequestProperty("Content-length", data.length()+"");
                conn.setDoOutput(true);
                OutputStream os = conn.getOutputStream();
                os.write(data.getBytes());
                int code = conn.getResponseCode();
                if (code == 200) {
                    InputStream is = conn.getInputStream();
                    String text = StreamTools.readInputStream(is);
                    return text;
                }else {
                    return null;
                }
    
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.out.println("111111");
            } catch (ProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    
    
    }
    
    
    

     

    1、不能使用翻墙软件,因为此时ip在国外。

    2、需要手机与电脑连接同一局域网(wifi热点就可以)

     

     

    3、关闭防火墙(不关闭也可以,但是需要配置入栈规则,让8080端口可以被访问),索性还是直接关了防火墙(关后如果没反应重启一下)

    4、需要在AndroidManifest.xml里面添加网络权限

     

     

    以上几点很重要,必不可少,我就是在这上面吃了大亏。

     

    八、在eclipse下启动服务器 右键项目 下面找到  Run  as ->Run on server 

    然后 切换到Android studio 把app运行到手机上

     

     

    展开全文
    Tianweidadada 2018-03-11 17:03:26
  • 9.18MB fbw668859 2018-07-09 20:16:56
  • 开发一个app后台数据库交互,基于mysql+jdbc,没有使用DBUtils或jdbc框架,纯粹底层jdbc实现. 2.开发环境 系统 : win10 IDE : Android Studio 3.5.1,IntelliJ IDEA 2019.02 DBMS : Mysql 8.0....

    2022.01.08 更新

    已更新新版本博客,更新内容与原文章相比有点多,因此新开了一篇博客,请戳这里

    1 背景

    开发一个App与后台数据库交互,基于MySQL+原生JDBC+Tomcat,没有使用DBUtilsJDBC框架,纯粹底层JDBC实现。

    这几天踩了很多坑,希望能帮助读者少踩坑。

    2 开发环境

    • Windows10
    • 服务器CentOS 7
    • Android Studio 3.5.1
    • IntelliJ IDEA 2019.02
    • MySQL 8.0.17
    • Tomcat 9.0.26

    3 准备环境

    主要是安装MySQLTomcat,已经安装的可以略过。

    3.1 安装MySQL

    这个是目前比较新的MySQL版本。

    服务器系统是CentOS

    其他系统安装看这里:

    CentOS使用yum安装即可。

    3.1.1 下载并安装MySQL

    sudo yum localinstall https://repo.mysql.com//mysql80-community-release-el7-1.noarch.rpm
    sudo yum install mysql-community-server
    

    3.1.2 启动服务并查看初始化密码

    sudo service mysqld start
    sudo grep 'temporary password' /var/log/mysqld.log
    

    3.1.3 修改密码

    首先使用root登录:

    mysql -u root -p
    

    输入上一步看到的密码,接着使用alter修改密码:

    alter mysql.user 'root'@'localhost' identified by 'password';
    

    注意新版本的MySQL不能使用太弱的密码,比如:

    在这里插入图片描述
    出现这种提示的话则说明密码太弱了,请使用一个更高强度的密码。

    3.1.4 允许外部访问

    use mysql;
    update user set host='%' where user='root';
    

    这个可以根据自己的需要去修改,host='%'表明允许所有的ip登录,也可以设置特定的ip,若使用host='%'的话建议新建一个用户配置相应的权限。

    3.1.5 配置防火墙(可选)

    一般来说需要在对应的云厂商的防火墙配置中开启响应端口,如图:

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    其中授权对象可以根据自己的需要更改,0.0.0.0/0表示允许所有的ip

    3.2 安装Tomcat

    3.2.1 下载并上传到服务器

    先去官网下载,下载后上传文件到服务器:

    在这里插入图片描述

    在这里插入图片描述

    笔者使用的是scp命令,使用不熟练的可以戳这里看看

    scp apache-tomcat-xxxx.tar.gz username@xx.xx.xx.xx:/
    

    改成自己的用户名和ip

    3.2.2 解压

    ssh连接到服务器,接着移动到/usr/local并解压:

    mkdir /usr/local/tomcat
    mv apache-tomcat-xxxx.tar.gz /usr/local/tomcat
    tar -xzvf apache-tomcat-xxx.tar.gz
    

    3.2.3 修改默认端口(可选)

    修改conf/server.xml文件,一般只需修改

    <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
    

    中的8080端口,修改这个端口即可。

    需要的话自行更改。

    3.2.4 启动

    运行bin目录下的startup.sh:

    cd bin
    ./startup.sh
    

    3.2.5 测试

    浏览器输入:

    服务器IP:端口
    

    若出现:

    在这里插入图片描述

    则表示成功。

    3.2.6 开机启动(可选)

    建议配置开机启动,修改/etc/rc.local文件,添加:

    sh /usr/local/tomcat/bin/startup.sh
    

    这个根据自己的Tomcat安装路径修改,指定bin下的startup.sh

    4 建库建表

    创建用户表,这里简化操作就不创建新用户不授权了。

    这是一个在本地用root登录的示例,请根据实际情况创建并授权用户。

    4.1 用户表

    CREATE DATABASE userinfo;
    USE userinfo;
    CREATE TABLE user
    (
        id          INT     NOT NULL    PRIMARY KEY   AUTO_INCREMENT,
        name        CHAR(30)    NULL,
        password    CHAR(30)    NULL
    );
    

    4.2 导入

    mysql -u root -p < user.sql
    

    在这里插入图片描述

    这样准备工作就做好了,下面正式开始进行敲代码阶段。

    5 后端部分

    5.1 创建项目

    选择Web Application:
    在这里插入图片描述

    在这里插入图片描述

    5.2 添加依赖库

    创建一个叫lib的目录:
    在这里插入图片描述

    添加两个JAR包(文末提供下载链接):

    • mysql-connector-java-8.0.17.jar
    • javax.servlet-api-4.0.1.jar

    在这里插入图片描述

    打开Project Structure

    在这里插入图片描述

    Modules --> + --> JARs or directories

    在这里插入图片描述

    选择刚才新建的lib下的两个JAR包:

    在这里插入图片描述

    勾选并apply

    在这里插入图片描述

    5.3 创建包与类

    总共4个包:

    • com.servlet:用于处理来自前端的请求,包含SignUp.javaSignIn.java
    • com.util:主要功能是数据库连接,包含DBUtils.java
    • com.entity:实体类,包含User.java
    • com.dao:操作用户类的类,包含UserDao.java

    在这里插入图片描述

    5.4 DBUtils

    连接数据库的类,纯粹的底层JDBC实现,注意驱动版本

    public class DBUtils {
    
        private static Connection connection = null;
        public static Connection getConnection()
        {
            try {
                Class.forName("com.mysql.cj.jdbc.Driver");
                String url = "jdbc:mysql://127.0.0.1:3306/数据库名字";
                String usename = "账号";
                String password = "密码";
                connection = DriverManager.getConnection(url,usename,password);
            }
            catch (Exception e)
            {
                e.printStackTrace();
                return null;
            }
            return connection;
        }
    
        public static void closeConnection()
        {
            if(connection != null)
            {
                try {
                    connection.close();
                }
                catch (SQLException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
    

    主要就是获取连接与关闭连接两个函数。

    String url = "jdbc:mysql://127.0.0.1:3306/数据库名字";
    String usename = "账号";
    String password = "密码";
    

    这几行根据自己的用户名,密码,服务器ip和库名修改。

    注意,MySQL 8.0以上使用的注册驱动的语句是:

    Class.forName("com.mysql.cj.jdbc.Driver");
    

    旧版的是:

    Class.forName("com.mysql.jdbc.Driver");
    

    5.5 User

    User类比较简单,就是就三个字段与Getter+Setter

    public class User {
        private int id;
        private String name;
        private String password;
        //三个Getter与三个Setter
        //...
    }
    

    5.6 UserDao

    public class UserDao {
        public boolean query(User user)
        {
            Connection connection = DBUtils.getConnection();
            String sql = "select * from user where name = ? and password = ?";
            try {
                PreparedStatement preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setString(1,user.getName());
                preparedStatement.setString(2,user.getPassword());
                ResultSet resultSet = preparedStatement.executeQuery();
                return resultSet.next();
            }
            catch (SQLException e)
            {
                e.printStackTrace();
                return false;
            }
            finally {
                DBUtils.closeConnection();
            }
        }
    
        public boolean add(User user)
        {
            Connection connection = DBUtils.getConnection();
            String sql = "insert into user(name,password) values(?,?)";
            try {
                PreparedStatement preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setString(1,user.getName());
                preparedStatement.setString(2,user.getPassword());
                preparedStatement.executeUpdate();
                return preparedStatement.getUpdateCount() != 0;
            }
            catch (SQLException e)
            {
                e.printStackTrace();
                return false;
            }
            finally {
                DBUtils.closeConnection();
            }
        }
    }
    

    主要就是查询与添加操作,查询操作中存在该用户就返回true,否则返回false

    添加操作中使用executeUpdate()getUpdateCount() != 0

    注意不能直接使用

    return preparedStatement.execute();
    

    去代替

    preparedStatement.executeUpdate();
    return preparedStatement.getUpdateCount() != 0;
    

    咋一看好像没有什么问题,那天晚上笔者测试的时候问题可大了,Android那边显示注册失败,但是数据库这边的却insert进去了。。。

    啊这。。。

    好吧,还是函数的问题。

    • 一般来说select使用executeQuery(),executeQuery()返回ResultSet,表示结果集,保存了select语句的执行结果,配合next()使用
    • delete,insert,update使用executeUpdate(),executeUpdate()返回的是一个整数,表示受影响的行数,即delete,insert,update修改的行数,对于dropcreate操作返回0
    • createdrop使用execute(),execute()的返回值是这样的,如果第一个结果是ResultSet对象,则返回true,如果第一个结果是更新计数或者没有结果则返回false

    所以在这个例子中

    return preparedStatement.execute();
    

    肯定返回false,所以才会数据库这边insert进去,但前端显示注册失败(这个问题笔者找了是真的久。。。)

    5.7 SignIn+SignUp

    servlet包中:

    • SingIn类用于处理登录,调用JDBC查看数据库是否有对应的用户
    • SignUp类用于处理注册,把User添加到数据库中

    SignIn.java如下:

    @WebServlet("/SignIn")
    public class SingIn extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException,ServletException
        {
            this.doPost(httpServletRequest,httpServletResponse);
        }
    
        @Override
        protected void doPost(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws IOException, ServletException
        {
            httpServletRequest.setCharacterEncoding("utf-8");
            httpServletResponse.setCharacterEncoding("utf-8");
            httpServletResponse.setContentType("text/plain;charset=utf-8");//设置相应类型为html,编码为utf-8
    
            String name = httpServletRequest.getParameter("name");
            String password = httpServletRequest.getParameter("password");
    
            UserDao userDao = new UserDao();
            User user = new User();
            user.setName(name);
            user.setPassword(password);
    
            if(!userDao.query(user))//若查询失败
            {
                httpServletResponse.sendError(204,"query failed.");//设置204错误码与出错信息
            }
        }
    }
    
    

    首先是@WebServlet注解,表示这是一个名字叫SignInServlet,可用于实现ServletURL的映射,如果不在这里添加这个注解,则需要在WEB-INF目录下的web.xml添加一个<servlet-mapping>

    @WebServlet("/SignIn")
    

    接着设置响应类型与编码:

    httpServletResponse.setContentType("text/plain;charset=utf-8");//设置相应类型为html,编码为utf-8
    

    HttpServletRequest.getParameter(String name)方法表示根据name获取相应的参数:

    String name = httpServletRequest.getParameter("name");
    String password = httpServletRequest.getParameter("password");
    

    下面是SignUp.java

    @WebServlet("/SignUp")
    public class SignUp extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws IOException,ServletException
        {
            this.doPost(httpServletRequest,httpServletResponse);
        }
    
        @Override
        protected void doPost(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws IOException,ServletException
        {
            httpServletRequest.setCharacterEncoding("utf-8");
            httpServletResponse.setCharacterEncoding("utf-8");//设定编码防止中文乱码
            httpServletResponse.setContentType("text/plain;charset=utf-8");//设置相应类型为html,编码为utf-8
    
            String name = httpServletRequest.getParameter("name");//根据name获取参数
            String password = httpServletRequest.getParameter("password");//根据password获取参数
    
            UserDao userDao = new UserDao();
            User user = new User();
            user.setName(name);
            user.setPassword(password);
    
            if(!userDao.add(user)) //若添加失败
            {
                httpServletResponse.sendError(204,"add failed.");//设置204错误码与出错信息
            }
        }
    }
    

    5.8 添加Servletweb.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        <servlet>
            <servlet-name>SignIn</servlet-name>
            <servlet-class>com.servlet.SingIn</servlet-class>
        </servlet>
    
        <servlet>
            <servlet-name>SignUp</servlet-name>
            <servlet-class>com.servlet.SignUp</servlet-class>
        </servlet>
    </web-app>
    

    要把刚才创建的Servlet添加进web.xml,在<servlet>中添加子元素<servlet-name><servlet-class>

    • <servlet-name>Servlet的名字,建议与类名一致
    • <servlet-class>Servlet类的位置

    如果在Servlet类中没有添加@WebServlet("/xxxx")注解,则需要在web.xml中添加:

    <servlet-mapping>
    	<servlet-name>SignIn</servlet-name>
    	<url-pattern>/SignIn</url-pattern>
    </servlet-mapping>
    

    其中<servlet-name><servlet>中的子元素<servlet-name>中的值一致,<url-pattern>是访问的路径。

    5.9 Hello.html测试文件

    最后添加一个叫Hello.html的测试文件。

    <!DOCTYPE html>
        <head>
            <meta charset="utf-8">
            <title>Welcome</title>
        </head>
        <body>
            Hello web.
        </body>
    </html>
    

    6 打包发布

    笔者用的IDEAEclipse的打包请看这里

    6.1 Project Structure->Artifacts->Web Application:Archive

    在这里插入图片描述

    在这里插入图片描述

    6.2 创建目录并添加模块

    修改名字,并创建WEB-INF目录与子目录classes

    在这里插入图片描述

    选中classes,添加Module Output,选择自己的web项目:

    在这里插入图片描述

    6.3 添加依赖库与其他文件

    添加JAR包,选中lib目录后添加JAR包文件:

    在这里插入图片描述

    接着添加Hello.htmlweb.xmlweb.xml需要在WEB-INF目录里,Hello.htmlWEB-INF外面:

    在这里插入图片描述

    6.4 打包

    Build->Build Artifacts
    在这里插入图片描述

    在这里插入图片描述

    6.5 上传测试

    打包好的WAR文件上传到服务器Tomcatwebapps目录下:

    scp ***.war username@xxx.xxx.xxx.xxx:/usr/local/tomcat/webapps
    

    注意改成自己的webapps目录。

    Tomcat启动后,在浏览器输入

    服务器IP:端口/项目/Hello.html
    

    笔者为了方便就在本地测试了:

    在这里插入图片描述

    7 Android

    7.1 新建工程

    在这里插入图片描述

    在这里插入图片描述

    7.2 MainActivity.java

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Button signin = (Button) findViewById(R.id.signin);
            signin.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String name = ((EditText) findViewById(R.id.etname)).getText().toString();
                    String password = ((EditText) findViewById(R.id.etpassword)).getText().toString();
                    if (UserService.signIn(name, password))
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
                            }
                        });
                    else {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                }
            });
    
    
            Button signup = (Button) findViewById(R.id.signup);
            signup.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String name = ((EditText) findViewById(R.id.etname)).getText().toString();
                    String password = ((EditText) findViewById(R.id.etpassword)).getText().toString();
                    if (UserService.signUp(name, password))
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "注册成功", Toast.LENGTH_SHORT).show();
                            }
                        });
                    else {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "注册失败", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                }
            });
        }
    }
    

    两个简单的Button绑定事件,然后设置两个Toast提示信息。

    7.3 UserService.java

    public class UserService {
        public static boolean signIn(String name, String password) {
            MyThread myThread = new MyThread("http://本机内网IP:8080/cx/SignIn",name,password);
            try
            {
                myThread.start();
                myThread.join();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
    
            return myThread.getResult();
        }
    
        public static boolean signUp(String name, String password) {
            MyThread myThread = new MyThread("http://本机内网IP:8080/cx/SignUp",name,password);
            try
            {
                myThread.start();
                myThread.join();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            return myThread.getResult();
        }
    }
    
    class MyThread extends Thread
    {
        private String path;
        private String name;
        private String password;
        private boolean result = false;
    
        public MyThread(String path,String name,String password)
        {
            this.path = path;
            this.name = name;
            this.password = password;
        }
        @Override
        public void run()
        {
            try {
                URL url = new URL(path);
                HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                httpURLConnection.setConnectTimeout(8000);//设置连接超时时间
                httpURLConnection.setReadTimeout(8000);//设置读取超时时间
                httpURLConnection.setRequestMethod("POST");//设置请求方法,post
    
                String data = "name=" + URLEncoder.encode(name, "utf-8") + "&password=" + URLEncoder.encode(password, "utf-8");//设置数据
                httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");//设置响应类型
                httpURLConnection.setRequestProperty("Content-Length", data.length() + "");//设置内容长度
                httpURLConnection.setDoOutput(true);//允许输出
                OutputStream outputStream = httpURLConnection.getOutputStream();
                outputStream.write(data.getBytes("utf-8"));//写入数据
                result = (httpURLConnection.getResponseCode() == 200);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public boolean getResult()
        {
            return result;
        }
    }
    
    MyThread myThread = new MyThread("http://内网IP:8080/cx/SignUp",name,password);
    MyThread myThread = new MyThread("http://内网IP:8080/cx/SignIn",name,password);
    

    这两行换成自己的ip,内网ip的话可以用ipconfigifconfig查看,修改了默认端口的话也把端口一起改了。

    路径的话就是:

    端口/web项目名/Servlet

    web项目名是再打成WAR包时设置的,Servlet名在web.xml中的<servlet>的子元素<servlet-name>设置,与源码中的@WebServlet()注解一致。

    另外一个要注意的就是线程问题,需要新开一个线程进行HTTP的连接。

    7.4 activity_main.xml

    前端页面部分很简单,就两个按钮,用于验证功能。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:orientation="vertical"
        >
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="用户名"
                />
            <EditText
                android:layout_width="300dp"
                android:layout_height="60dp"
                android:id="@+id/etname"
                />
        </LinearLayout>
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="密码"
                />
            <EditText
                android:layout_width="300dp"
                android:layout_height="60dp"
                android:id="@+id/etpassword"
                />
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <Button
                android:layout_width="120dp"
                android:layout_height="60dp"
                android:text="注册"
                android:id="@+id/signup"
                />
            <Button
                android:layout_width="120dp"
                android:layout_height="60dp"
                android:text="登录"
                android:id="@+id/signin"
                />
        </LinearLayout>
    </LinearLayout>
    

    8 测试

    8.1 注册测试

    随便输入用户名与密码:

    在这里插入图片描述

    查看数据库:

    在这里插入图片描述

    8.2 登录测试

    在这里插入图片描述

    9 注意事项

    9.1 数据库用户名与密码

    数据库的用户名和密码一定要设置正确,要不然会像下图一样抛出异常:

    在这里插入图片描述

    在加载驱动错误时也可能会出现这个错误,因此要确保打成WAR包时lib目录正确且JAR包版本正确。

    还有就是由于这个是JDBC的底层实现,注意手写的SQL语句不能错。

    千万千万别像笔者这样:

    在这里插入图片描述

    9.2 网络权限问题

    需要在AndroidManifest.xml添加网络权限:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    

    9.3 安全组/防火墙问题

    因为如果是现在的云服务器一般都使用安全组而不是直接使用防火墙配置安全设置,所以如果没法访问请到云服务器上面对应的安全组配置中开放端口,默认是8080端口,一般是允许所有ip通过,源ip配置为0.0.0.0/0,比如:

    在这里插入图片描述

    如果设置了安全组通过了,还是不能访问,可能是服务器防火墙的问题,可以查看iptablesCentOS8使用firewalld)是否开启:

    systemctl status iptables
    

    开启的话可以选择关闭:

    systemctl stop iptables
    

    若不关闭,可以添加端口规则,修改/etc/sysconfig/iptables

    vim /etc/sysconfig/iptables
    

    添加

    -A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
    -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
    

    重启iptables

    systemctl restart iptables
    

    9.4 HTTP注意事项

    由于从Android P开始,默认要求使用加密连接,也就是要使用HTTPS,所以会禁止使用HTTP连接。

    使用HTTP连接时会出现以下异常:

    W/System.err: java.io.IOException: Cleartext HTTP traffic to **** not permitted
    java.net.UnknownServiceException: CLEARTEXT communication ** not permitted by network security policy
    

    两种解决办法:

    • 使用HTTPS
    • 修改默认的AndroidManifest.xml使其允许HTTP连接

    res下新建一个文件夹xml,创建一个叫network_security_config.xml的文件,文件内容如下

    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
        <base-config cleartextTrafficPermitted="true" />
    </network-security-config>
    

    然后在AndroidMainfest.xml中加入:

    <application
     android:networkSecurityConfig="@xml/network_security_config"
    />
    

    即可。

    如果上面的方法不行,可以试一下直接在AndroidManifest.xml直接加入一句:

    <application 
    android:usesCleartextTraffic="true"
    />
    

    9.5 线程问题

    Android 4.0开始,联网不能在主线程操作,万一网络不好就会卡死,所以有关联网的操作都需要新开一个线程,不能在主线程操作。

    9.6 AVD问题

    在这里插入图片描述

    这个问题笔者找了很久,HTTP连接没问题,服务器没问题,数据库没问题,前端代码没问题,然后去了StackOverflow,发现是AVD的问题。。。

    在这里插入图片描述

    简单来说就是卸载了APP再重启AVD,居然成功了。。。

    9.8 404

    根据评论反映(这里同时感谢评论的各位)会出现404问题,出现404的主要原因就是访问路径的不正确,这里分三种情况进行说明。

    9.8.1 本地IDEA中访问

    IDEA运行项目后,可以使用postman进行测试,访问路径:

    http://localhost:8080/SignIn
    

    即可,因为此时还没有打包,所以不需要加上打包的项目名。

    9.8.2 本地Tomcat访问

    打包后会有一个叫xxx.war的打包文件,比如叫demo.war,那么使用postman测试的路径就要变为

    http://localhost:8080/demo/SignIn
    

    因为Tomcat会自动把demo.war解包,运行Tomcat后会在webapps下会有一个叫demo的文件夹,里面就是打包后的文件,此时的路径需要以demo为基准,因此SignIn前需要加上demo

    9.8.3 部署到服务器的Tomcat

    部署到服务器后与本地Tomcat是基本一样的,只是把对应的locahost改成对应的域名或者公网ip即可,比如:

    http://www.example.com:8080/demo/SignIn
    http://111.111.111.111:8080/demo/SignIn
    

    10 源码与JAR

    10.1 JAR

    这里搜索下载。

    10.2 源码

    11 最后

    首先感谢读者能看到末尾,笔者也确实花了不少时间写这篇文章,但是,总会有不对或让读者疑惑的地方,希望读者有疑问或者其他什么问题可以私信笔者或在评论中指出,感激不尽。

    12 参考网站

    展开全文
    qq_27525611 2019-10-11 00:57:15
  • 具体使用python的DB-API,这一章里介绍如何编写代码MYSQL数据库技术交互,这里使用一个通用的数据库API,名为DB-API。 7.1基于数据库web应用 之前我们把日志数据存放在一个文本文件中,无法得知第六章最开始的...

    7使用数据库

    具体使用python的DB-API,这一章里介绍如何编写代码与MYSQL数据库技术交互,这里使用一个通用的数据库API,名为DB-API。

    7.1基于数据库的web应用

    之前我们把日志数据存放在一个文本文件中,无法得知第六章最开始的请求:已经响应了多少个请求?最常用的字母列表是什么?请求来自哪个IP地址?哪个浏览器用的最多?

    现使用mysql数据库存放日志数据:

    1. 安装mysql服务器。
    2. 为Python安装一个mysql数据库驱动程序。
    3. 为web应用创建数据库和表。
    4. 创建代码来处理这个web应用的数据库和表。

    任务1:安装mysql服务器。

    网站:http://dev.mysql.com/downloads/mysql/

    千万不要选择最新版本的8.0.12我整了一下午的教训,grant按照正常方式创建用户会一直报语法错误。

    问了老师说可能是版本的原因,建议下载5.6版,雷区我已经踩了

    即使你没有用过mysql,不过没关系,我也接触较少(我主要对oracle了解多一些)

    下载之后发现是一个zip文件,这是我的解压路径:

    D:\mysql\mysql-5.6.41-winx64

    安装步骤:https://blog.csdn.net/u012896719/article/details/80428493

    安装完成之后mysql -uroot -p新密码(我的密码是112233)

    就进入了mysql>  quit退出

    任务2:为Python安装一个mysql数据库驱动程序。

    python解释器对于数据库提供了一个标准数据库API(应用编程接口),称为DB-API,可以用来处理基于SQL的数据库,还需要一个用来连接DB-API的驱动程序——oracle提供了一个MYSQL-Connector/python驱动。下来手动安装这个驱动,访问https://dev.mysql.com/downloads/connector/python/

    在这个页面选择之前的版本最少是2.1.3,将下拉选项改为Platform Independent(平台独立):

     

    下载之后解压,然后使用管理员打开cmd切换到这个目录下输入

    py -3 setup.py install

    看到下图的路径说明成功:

     

    任务3:为web应用创建数据库和表

    登录mysql:

    mysql -u root -p112233

    创建一个数据库存储日志数据:

    create database vsearchlogDB;

    下来专门为web应用创建一个数据库用户的ID和口令,以便在于mysql交互时使用,而不是一直使用根用户root。

    grant all on vsearchlogDB.* to 'vsearch' identified by '112233';

    退出:quit

     

    创建一个表,字段:短语,字母,IP地址,浏览器以及结果值,还需要每个请求的唯一ID和记录消息的时间戳。

    用vsearch用户登录数据库

    mysql -u vsearch -p 112233

    我遇到了一个问题,登录不上去,报错error 1045 access denied for user

    所以分享一个解决的方案

    https://www.cnblogs.com/summertime-wu/p/7466160.html

     

    使用创建的数据库

    use vsearchlogdb

    创建表

    create table log(

    id int auto_increment primary key,

    ts timestamp default current_timestamp,

    phrase varchar(128) not null,

    letters varchar(32) not null,

    ip varchar(16) not null,

    browser_string varchar(256) not null,

    results varchar(64) not null);

    查看表的结构

    desc log;

     

    为了让日志的记录自动加入到这个表中,而不是我们输入insert命令一行一行的插入数据,需要在Python和SQL进行交互,相应的用到DB-API更多知识。

    DB-API

    使用它的好处是可以轻松替换驱动程序/数据库组合,而只对Python代码进行非常小的改动。

     

    步骤1:定义连接属性

    连接到mysql需要三个信息:

      l 运行mysql服务器的计算机主机的IP地址/主机名;

      l 用户ID和口令;

      l 这个用户想要交互的数据库名。

    驱动程序允许将这些链接属性放在一个Python字典中,下来在>>>窗口进行测试

    dbconfig = { 'host': '127.0.0.1',

          'user': 'vsearch',

           'password': '112233',

          'database':'vsearchlogdb', }

     

    步骤2:导入数据库驱动程序

    >>> import mysql.connector

    导入之后就可以使用mysql特定的驱动程序了

     

    步骤3:建立与服务器的一个连接

    >>> conn = mysql.connector.connect(**dbconfig)

    **告诉connect函数用一个变量提供了一个参数字典,在connect函数中使用这些参数来建立连接。

     

    步骤4:打开一个游标

    把游标理解为数据库中的文件句柄。

    >>> cursor = conn.cursor()

     

    步骤5:完成SQL查询

    首先向mysql请求连接数据库的表名,将show tables查询赋至_SQL变量(变量名可以使用别的),然后调用cursor.execute函数,并传入_SQL作为参数:

    >>> _SQL = """show tables"""

    >>> cursor.execute(_SQL)

    执行后SQL查询会发送到SQL服务器执行这个查询,不过不会立即显示,请求才会得到结果。

    可以使用下列三个方法获得请求结果:

    •    cursor.fetchone获取一行结果。
    •    cursor.fetchmany获取指定的任意行结果。
    •    cursor.fetchall获取所有数据行结果。

     

    >>> res = cursor.fetchall()

    >>> res

    [('log',)]

    这个结果是数据库中的表log(只有这一个表),作为元组去显示()。

    换一个SQL语句查询desc log:

     

    得到结果中的各行:

     

    python允许在查询串中放置“数据占位符”,用%s指定

     

    数据库系统会缓存insert,之后再一次应用全部的insert,所以有可能现在使用select查询不到数据。需要commit提交,使用conn.commit

     

    数据已经插入

     

    步骤6:关闭游标和连接

    >>> cursor.close()

    True

    >>> conn.close()

    任务4:创建代码处理web应用的数据库和表

    调整web应用的代码,让它把web请求的数据记录到mysql数据库系统中。

     

    def log_request(req: 'falsk请求', res: str) -> None:
    	dbconfig = { 'host': '127.0.0.1',
    				'user': 'vsearch',
    			 	'password': '112233',
    		 		'database':'vsearchlogdb', }
    	import mysql.connector
    	conn = mysql.connector.connect(**dbconfig)
    	cursor = conn.cursor()
    	_SQL = """ insert into log 
    			(phrase, letters, ip, browser_string, results)
    	 		values 
    	 		(%s, %s, %s, %s, %s)"""
    	cursor.execute(_SQL, (req.form['phrase'], 
    						  req.form['letters'], 
    						  req.remote_addr, 
    						  req.user_agent.browser, 
    						  res, ))
    	conn.commit()
    	cursor.close()
    	conn.close()

    测试新的代码

    py -3 vsearch_for_web.py

    打开浏览器输入http://127.0.0.1:5000像之前一样测试

    不过这次/viewlog不能查看最新的日志记录,现在的数据在数据库中。

     

    窗口的大小在菜单栏右键属性中调整。

     

    这一部分的内容已经完成了,不过别忘了函数view_the_log,后面会更新这个函数让它从数据库的log表中获取数据,而不是从文件中获取。

    转载于:https://www.cnblogs.com/sebastiane-root/p/9566494.html

    展开全文
    weixin_30294021 2018-08-31 16:23:00
  • 362KB weixin_38641339 2021-01-09 22:19:58
  • 以往的开发方式:小程序必须要绑定至少一个合法安全域名,且该域名必须...前端是不能直接与数据库交互的。但是!腾讯今年推出了腾讯云开发。简单的理解,就是现在云开发可以直接在小程序里编写数据库交互代码,直接...

    以往的开发方式:

    小程序必须要绑定至少一个合法安全域名,且该域名必须是使用ssl证书的,也就是要以https协议。小程序正式上线后,只能跟合法安全域名内的域名进行信息互通。如果请求没有配置过的域名,会被微信屏蔽。

    而对于数据库的交互,就必须要在合法安全域名下的服务器来进行。前端是不能直接与数据库交互的。

    但是!腾讯今年推出了腾讯云开发。

    简单的理解,就是现在云开发可以直接在小程序里编写数据库交互代码,直接在小程序端与数据库交互。

    基础版的免费配额,可以享受:5GB储存空间,CDN流量,2GB的数据库。如果这个配置不够用,那么就可以考虑加预算升级了。个人创业尝试的使用。

    任何人都可以注册申请。申请步骤: 先以个人或企业申请小程序,获取到appID,将appID填入到“微信开发者工具中”。新建云开发项目,在开发工具的左上角找到“云开发”按钮,即可根据步骤申请免费空间。

    云开发用到的数据库属于json数据库,使用起来跟mongoDB非常相似。编写云函数其实跟nodejs是一样的,也可以安装npm的库,开发效率非常高。

    所有的云开发请求,都会在控制面板的NetWork中查看,其中包括该调用所请求的环境 ID。

    云开发可以避免了传统开发时对服务器的运维工作,其实数过来还是挺划算的,节省了人力和服务器成本。而且也不需要提供域名,不需要备案域名。解决了很多上线前的麻烦。

    同时,腾讯还推出了配套使用的cms系统。完全免费且一键部署后台管理页面,无需额外开发,只需要配置数据的类型和参数名,即可生成可用的后台管理系统。

    若有小程序的定制需求,可以联系火猫网络:火猫网络-高端定制小程序/网站​firecat-web.com4fbe95fe8f971f108acc1599234e00b7.png

    展开全文
    weixin_32371243 2021-01-19 00:57:04
  • baidu_36583119 2018-01-06 18:04:53
  • weixin_30362743 2021-02-12 01:26:52
  • 102.68MB weixin_42118701 2021-03-17 15:16:27
  • 779KB weixin_38738977 2021-01-27 09:41:49
  • 281KB weixin_42135773 2021-05-27 19:40:28
  • aikongmeng 2013-12-20 14:51:46
  • 336KB u010550381 2013-05-03 15:24:21
  • leemu0822 2017-05-04 11:22:21
  • wodetiankong516 2012-08-09 10:28:28
  • Darlingqiang 2019-03-19 20:56:34
  • erlian1992 2016-07-09 21:45:20
  • m0_37510446 2019-05-09 14:35:25
  • kangkanglhb88008 2018-11-24 17:37:47
  • webyzx 2017-04-16 11:39:35
  • xi_2130 2016-06-15 20:50:50
  • barenk 2017-04-18 13:02:25
  • baidu_25343343 2016-11-02 09:47:18
  • Teacher_du 2018-12-13 16:25:12
  • Rongbo_J 2016-01-07 20:33:43
  • dingguanyi 2018-07-03 10:11:21
  • g695144224 2016-04-02 23:20:27

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 203,809
精华内容 81,523
关键字:

web服务器与数据库交互

友情链接: MATLAB-mathwork.rar