因为课程需要我们做一个项目,没有要求是什么程序,我们小组暂定商议为一个安卓程序,又鉴于我没有学过安卓开发,又感受到后台开发的内容自己基本没有接触到过,所以自告奋勇来写后端的内容,这个教程主要参考了b站上的某个视频,发布视频的大佬关于整个项目的代码github在此
至此我们的前期思想准备工作已经完成了,总结一下,到这步,我们应该完成的有:
根据客户端的需求,我们应撰写需求报告
在这个示范中,我们客户端的需求仅仅是用户注册和登录功能,需求主要是:
1.用户注册要求,分配给新用户一个独一无二的id,用户自己填写的账户名要求不能重复,密码要求6位以上,用户注册的手机号为11位
2.用户登录,要求账号密码正确,即返回登录成功的状态码
根据上面的分析,显然我们只需要一张表记录下所有的客户的注册信息即可,首先我们建立一个名为bookseller的数据库,并建一张名为USER的表,里面的字段有:
注意我在建表的时候,属性字段用了 “ 表名_属性 ” 的写法,一定要遵循这个规则,有利于后面hibernate反向工程生成规范的类名。
打开MyEclipse,在项目栏右键new一个other,自己输入dy,选择dynamic web project,可能有时输入dy后发现没有这个选项,那么√一下下面的show all wizards就有了。
然后next,给自己的项目取个名字,我们这里叫bookseller,target runtime记得选到Tomcat
然后next next ,记得要勾选Generate web.xml deployment descriptor选项,然后finish就行了
到这里就新建了一个项目了。
项目结构一般分为四个包:
如何创建包呢?
在src文件夹右击new–>package,注意,package的name一般具有固定格式,即action的name是com.bookseller.action 如果学过计网这是容易理解的,代表的是服务器的一层层往下。
其他三个包也是类似的名称。
右键你刚建好的项目,移到configure facets,然后会有很多框架可以装,我们选到Struts2,
next,然后URL pattern,我们可以选*.action或者 */,而.do一般是servlet使用的,这是代表我们路由操作的一种正则格式匹配,在这里我们就选action作为示范;
再选next,默认核心包即可,点击finish完成。
这时候出现了一个Struts.xml 这是配置路由的文件
点击右上角的标志
选择database explorer;
进入页面后点击右键new,driver template选择MySQL,name自己取一个;
connection URL 的hostname是localhost,端口继续3306,dbname为我们上面创建的数据库bookseller,然后输入我们数据库的账号密码;
注意,下面的地方要求我们加入一个jar包,如果用MySQL是叫mysql-connector-java.jar,自己百度去下载(这里遇到一个坑,有些jar包加入后test发现连接不上,如果确认其他地方无误的话建议重下一个jar包使得driver class name 是 ‘com.mysql.jdbc.driver’)
然后test成功后,点击finish完成。
同样的方法,在configure facets里面找到install hibernate:
1.configuration folder放在src即可,configuration file name 直接放根目录下(即保持默认位置不用改动),sessionFactory class防在util package下,next
2. DBdriver选上面刚建好的数据库连接,next
3. finish就行了,问你是否前往hibernate视图,可以暂时不用,选no
4. 这时候我们打开hibernate.cf.xml,查看source源码
5. 注意一下,connection URL需要更改,防止中文乱码(xml文件中&的表示是&)
我们去百度搜下载一个gson.jar包,拷贝放入项目的webroot -> web-inf -> lib下,会自动配置到环境中,这个包是用于处理json文件。
到这里,其实我们的项目已经可以运行了,右击webroot下的index.jsp文件,run as MyEclipse server application,然后跑完后弹出页面,显示“this is my JSP page”,代表我们这个项目配置成功了,已经可以实现最基本的访问。
设计dao包;
实现action类;
配置路由;
我们现在回去看开发结构中4个基本的包:
发现我们的entity包里面的对象已经有了,util包里面也暂时有了hibernate工厂类,而action和dao包还没有内容,所以从这里入手。
一般根据entity来进行设计,每个entity对应一个dao,dao其实就是对entity对象进行增删改查的方法。
一般的设计规范是先设计一个xxxDao的interface,再用一个xxxDaoImpl的类来实现接口功能。
一般关于增删改查的操作都要用到hibernate工厂类中的session对象去操作,其中增删改三个操作要用到hibernate中的事务(Transaction对象)。
下面我们进行示范,针对user的实体对象,我们先在dao包内new一个名为userDao的interface(new–>other–>interface),因为我们只有登录和注册的功能,所以声明两个基本方法方法login和saveUser用来登录和注册,还声明了一个根据用户ID获得用户类数据的函数和一个根据用户account获得ID的函数:
package com.BookSeller.dao;
import com.BookSeller.entity.User;
public interface UserDao {
public User getUser(int userId);
public int getUserIdByUserAccount(String userAccount);
public boolean login(String userAccount,String userPassword);
public void saveUser(User user);
}
完成后我们再新建一个实体类userDaoImpl类,在new的时候要记得add interface“userDao”,用来实现interface中的函数:
package com.BookSeller.dao;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.BookSeller.entity.User;
import com.BookSeller.util.HibernateSessionFactory;
public class UserDaoImpl implements UserDao {
private Transaction transaction;
@Override
public boolean login(String userAccount, String userPassword) {
if(userAccount != null && userPassword != null)
{
Session session = HibernateSessionFactory.getSession();
String hql = "from User as a where a.userAccount= '"+ userAccount +"' and a.userPassword= '"+ userPassword +"' ";
Query query = (Query)session.createQuery(hql);
User user = (User)query.uniqueResult();
if(user != null)
{
HibernateSessionFactory.closeSession();
return true;
}
HibernateSessionFactory.closeSession();
}
return false;
}
@Override
public void saveUser(User user) {
// TODO Auto-generated method stub
Session session = HibernateSessionFactory.getSession();
try{
transaction = session.beginTransaction();
session.save(user);
transaction.commit();
}catch(Exception e){
transaction.rollback();
e.printStackTrace();
}finally{
HibernateSessionFactory.closeSession();
}
}
@Override
public User getUser(int userId) {
Session session = HibernateSessionFactory.getSession();
User user = (User)session.load(User.class, userId);
return user;
}
@Override
public int getUserIdByUserAccount(String userAccount) {
Session session = HibernateSessionFactory.getSession();
String hql = " from User as a where a.userAccount= '"+userAccount+"' ";
Query query = (Query)session.createQuery(hql);
User user = (User)query.uniqueResult();
if(user != null){
HibernateSessionFactory.closeSession();
return user.getUserId();
}
HibernateSessionFactory.closeSession();
return user.getUserId();
}
}
使用Javabean来接收参数;
必须实现返回值为string的execute()方法;
其实方法比较固定,有5行代码是必须有的:
ActionContext ctx = ActionContext.getContext();
HttpServletResponse response = (HttpServletResponse)ctx.get(ServletActionContext.HTTP_RESPONSE);
response.setContentType("text/json");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
这五行代码是把我们的response变成json文件的一个固定套路,首先拿到上下文对象,然后拿到response,然后设置一下response的属性,最后把response打印出来。
下面我们开始针对注册操作实现action类,首先考虑到我们需要用到jsonResponse的状态码回应,首先我们在util包里,新建一个JavaResponse的类,代码如下:
package com.BookSeller.util;
public class JsonResponse {
private int status;
private int userId;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
}
然后我们开始实现注册的action类,在action包里面新建class名为RegisterAction,
实现代码为:
package com.BookSeller.action;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.BookSeller.dao.UserDao;
import com.BookSeller.dao.UserDaoImpl;
import com.BookSeller.entity.User;
import com.BookSeller.util.JsonResponse;
import com.google.gson.Gson;
import com.opensymphony.xwork2.ActionContext;
public class RegisterAction {
private JsonResponse jsonResponse = new JsonResponse();
private String userAccount;
private String userPassword;
private String userPhone;
public String execute() throws IOException{
Gson gson = new Gson();
ActionContext ctx = ActionContext.getContext();
HttpServletResponse response = (HttpServletResponse)ctx.get(ServletActionContext.HTTP_RESPONSE);
response.setContentType("text/json");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
UserDao dao = new UserDaoImpl();
User user = new User();
user.setUserAccount(userAccount);
user.setUserPassword(userPassword);
user.setUserPhone(userPhone);
dao.saveUser(user);
jsonResponse.setStatus(200);
out.print(gson.toJson(jsonResponse));
return null;
}
public String getUserAccount() {
return userAccount;
}
public void setUserAccount(String userAccount) {
this.userAccount = userAccount;
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
public String getUserPhone() {
return userPhone;
}
public void setUserPhone(String userPhone) {
this.userPhone = userPhone;
}
}
到这里我们就已经完成了注册行为的action类,关于登录的action代码在此不做赘述,有代码需求的同学可以去看看博客最开始的github仓库,那么我们怎么样能够让一个HTTP请求调用到这个action类呢?
那就需要我们下面的工作了。
打开Struts.xml文件,这个路由文件的作用主要是把一个HTTP请求路由到一个具体的action类,写法也比较固定,先看示例
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<package name="default" extends="struts-default">
<action name="register" class="com.BookSeller.action.RegisterAction"></action>
<action name="login" class="com.BookSeller.action.LoginAction"></action>
</package>
</struts>
上面的package标签是固定的写法,后面的action标签大家应该一看就懂了,当我们发出服务器IP+register.action?userAccount=xxx&userPassword=xxx&userPhone=xxx的HTTP请求时,Struts配置就会路由调用这个对应的action类。
至此,我们的基本工作就完成了,可以来用上面的HTTP请求测试一下了。
首先提示大家一下,修改了代码之后,最好可以重启一下Tomcat,否则有可能Tomcat上部署的仍是之前的内容。
重启后,我们右击index.jsp,选择run as myeclipse server application,在web browser导航栏输入自己的请求:
可以看到返回了200,也就是我们前面设定的注册成功的状态码,我们打开数据库GUI工具查看之前创建的user表,发现,有一个新用户添加进来了:(我们注册的时候并没有返回userID,所以默认是0,并不是返回错误了)
神奇!
对于一个可以使用了的项目我们部署的方法有很多,比如:
1.租用阿里云,华为云等服务器,把自己的项目传到服务器上去,就可以随时随地访问;
2.用自己的电脑做服务器(不是特别推荐,因为需要将电脑24小时开机才可实现随时访问);
3.使用docker;
我在写这篇博客的时候自己也还没有完成这个项目,暂时没有到部署的那一步,所以在此不做详细展开了,后面如果觉得部署需要整理一下,会再专门写一篇博客的。
万字长文不易,感谢您的阅读!