新建一张表:
File—>New—>New Module—>java Enterprise
建立后,因为需要与Mysql数据库连接,所以需要导入jar包。在WEB-INF下建立lib目录,存放jar包
lib下放入mysql-connector-java-5.1.6.jar,将它Add as Library,选为模块jar包即可
domain:实体类;servlet:控制层;dao:接口层;service:服务层;util:工具层;可建立test,当作测试层
实体类的名字尽量与数据库中表明一致。由于要持久化,对于实体层,一般去实现一个串行化接口
import java.io.Serializable;
public class Users implements Serializable {
private int uid;
private String username;
private String password;
private String gender;
private String email;
private String birthday;
public Users() {
}
public Users(int uid, String username, String password, String gender, String email, String birthday) {
this.uid = uid;
this.username = username;
this.password = password;
this.gender = gender;
this.email = email;
this.birthday = birthday;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Users{" +
"uid=" + uid +
", username='" + username + '\'' +
", password='" + password + '\'' +
", gender='" + gender + '\'' +
", email='" + email + '\'' +
", birthday='" + birthday + '\'' +
'}';
}
}
因为需要对数据库进行操作,将DBUtils.java放入util目录下,需要导入commons-dbcp2-2.7.0.jar、commons-logging-1.2.jar、commons-pool2-2.7.0.jar在lib目录下。继续以模块jar包使用
在DBUtils.java中,有
DBUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
//是要取得src目录下的jdbc.properties
所以在src目录下建立属性文档jdbc.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
username=root
password=XXXX #数据库密码
initialSize=20
Test:
public class Test {
public static void main(String[] args) {
Connection conn;
try{
conn=DBUtils.getConnection();
if (conn!=null){
System.out.println("Mysql连接成功");
}else{
System.out.println("Mysql连接失败");
}
}catch (Exception ex){
ex.printStackTrace();
}
}
}
//连接成功
在Mysql中手动建立一个用户
在dao目录下写用户的业务逻辑接口:UserDao
public interface UserDao {
//用户登录
public Users login(String username,String password);
//用户注册
public Users reg(Users users+);
}
在Dao下建立子包impl,写实现类UserDaoimpl
public class UsersDaoimpl implements UserDao {
@Override
public Users login(String username, String password) {
Connection conn; //连接对象
ResultSet rs; //数据集合
List args = new ArrayList(); //数据集
String sql = "SELECT * FROM users WHERE username=? AND password=?"; //执行语句
Users loginUser = null;
try {
conn = DBUtils.getConnection();
args.add(username);
args.add(password);
rs = DBUtils.myExecuteQuery(sql,args);
if (rs.next()){ //说明登陆成功,用户资料返回
loginUser = new Users();
loginUser.setUid(rs.getInt("uid"));
loginUser.setUsername(rs.getString("username"));
loginUser.setPassword(rs.getString("password"));
loginUser.setGender(rs.getString("gender"));
loginUser.setEmail(rs.getString("email"));
loginUser.setBirthday(rs.getString("birthday"));
}
return loginUser;
}catch (Exception ex){
ex.printStackTrace();
return null;
}
}
@Override
public Users reg(Users users) {
return null;
}
}
进行登录测试:
public class Test {
public static void main(String[] args) {
//测试用户登录
Users loginUser = null;
UserDao userDao = new UsersDaoimpl();
loginUser = userDao.login("小宋","123456");
if (loginUser!=null){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
}
}
@Override
public Users reg(Users users) {
Connection conn; //连接对象
List args = new ArrayList(); //数据集
String sql = "INSERT INTO users(username,password,gender,email,birthday) VALUES (?,?,?,?,?)"; //执行语句
Users regUser = null;
int result;
try {
conn = DBUtils.getConnection();
DBUtils.startTransaction();//开启事务
args.add(users.getUsername());
args.add(users.getPassword());
args.add(users.getGender());
args.add(users.getEmail());
args.add(users.getBirthday());
result = DBUtils.myExecuteUpdate(sql,args);
if (result>0){ //说明登陆成功,用户资料返回
//获得新生成的编号!
ResultSet temp = DBUtils.pstm.getGeneratedKeys();
temp.next();
int uid = temp.getInt(1);
regUser= queryUserByUid(uid);
}
DBUtils.commit(); //提交事务
DBUtils.endTransaction();
return regUser;
}catch (Exception ex){
ex.printStackTrace();
DBUtils.rollback();
DBUtils.endTransaction();
return null;
}
}
@Override
public Users queryUserByUid(int uid) {
Connection conn; //连接对象
ResultSet rs; //数据集
List args = new ArrayList();
String sql = "select * from users where uid=?";
Users user = null;
try{
conn = DBUtils.getConnection();
args.add(uid);
rs = DBUtils.myExecuteQuery(sql,args);
if(rs.next()){ //说明就登录成功了。用户资料返回
user = new Users();
user.setUid(rs.getInt("uid"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setGender(rs.getString("gender"));
user.setEmail(rs.getString("email"));
user.setBirthday(rs.getString("birthday"));
}
return user;
}catch(Exception ex){
ex.printStackTrace();
return null;
}
}
进行测试:
Users regUser = new Users();
regUser.setUsername("xiaoshen");
regUser.setPassword("123123");
regUser.setGender("nv");
regUser.setEmail("[email protected]");
regUser.setBirthday("2020-2-2");
UserDao userDao = new UsersDaoimpl();
Users regUser1 = userDao.reg(regUser);
System.out.println(regUser1);
//输出
//Users{uid=3, username='xiaoshen', password='123123', gender='nv', email='[email protected]', birthday='2020-2-2'}
在service目录下建立UsersService接口,里面的写法与UsersDao中一样,然后写接口的实现类
public class UsersServiceimpl implements UsersService {
private UserDao userDao = new UsersDaoimpl();//相当于又分了一个层
@Override
public Users login(String username, String password) {
return userDao.login(username,password);
}
@Override
public Users reg(Users users) {
return userDao.reg(users);
}
@Override
public Users queryUserByUid(int uid) {
return userDao.queryUserByUid(uid);
}
}
@WebServlet(name = "UsersServlet",value = "UsersServlet")
public class UsersServlet extends HttpServlet {
//需要用一个参数来判断用户做的是什么操作
private String action;
private UsersService usersService = new UsersServiceimpl();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if(request.getParameter("action")!=null){
this.action=request.getParameter("action");
switch (this.action){
case "login":
login(request,response);
break;
case "reg":
reg(request,response);
break;
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
//执行登录动作
private void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
Users loginUser =null;
loginUser = usersService.login(request.getParameter("username"),request.getParameter("password"));
if (loginUser!=null){
System.out.println("登陆成功");
}else{
System.out.println("登陆失败");
}
}
//执行注册动作
private void reg(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
Users user = new Users();
user.setUsername(request.getParameter("username"));
user.setPassword(request.getParameter("password"));
user.setGender(request.getParameter("gender"));
user.setEmail(request.getParameter("email"));
user.setBirthday(request.getParameter("birthday"));
Users regUser = null;
regUser=usersService.reg(user);
if(regUser!=null){
System.out.println("注册成功");
System.out.println(regUser);
}else{
System.out.println("注册失败");
}
}
}
其中,还需加上一个过滤器Filter,防止中文乱码
@WebFilter(description = "EncodingFilter",value="/*",initParams ={@WebInitParam(name="encoding",value="utf-8")}) // 凡是过滤器一般都是 /* ,过滤所有的请求
public class EncodingFilter implements Filter {
private String encoding;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.encoding = filterConfig.getInitParameter("encoding");
}
//过滤器过滤的是请求,什么样的请求呢?各种各样请求,只有是请求,就被过滤以下。能理解吗?
//过滤器在过滤器请求的时候,一定会执行doFilter这个方法
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//请求使用utf-8
servletRequest.setCharacterEncoding(this.encoding);
//响应也使用utf-8
servletResponse.setCharacterEncoding(this.encoding);
//不会有中文乱码
filterChain.doFilter(servletRequest,servletResponse); //千万不要忘了写,过滤器链条,继续向后过滤
}
@Override
public void destroy() {
}
}
配置Jetty服务器,启动,测试接口
在IDEA控制台上输出:登陆成功
在web目录下进行创建jsp页面
登录页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
用户登录
用户登录
主页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
系统主页面
欢迎您:${sessionScope.loginUser.username}
注册页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
用户注册
用户注册
若登成功,需要在Users Servlet中进行修改:
if (loginUser!=null){
System.out.println("登陆成功");
//把登录成功的用户存到session中
request.getSession().setAttribute("loginUser",loginUser);
response.sendRedirect(request.getContextPath()+"/main.jsp");
}else{
System.out.println("登陆失败");
}
若注册成功,也在Users Servlet中进行修改:
if(regUser!=null){
System.out.println("注册成功");
System.out.println(regUser);
//页面跳转到登陆页面
response.sendRedirect(request.getContextPath()+"/login.jsp");
}else{
System.out.println("注册失败");
}
进行登录测试:
正确登陆后:
进行注册测试:
发现已经注册成功,注册页面会跳转到登录页面
整个程序体现出一个分层结构,MVC设计模式
整个流程图:
每一个层之后的代码修改,对其他层影响不大。体现出高内聚,低耦合的思想
如何分层问题:
视图层:jsp/html,建议使用html
控制层:servlet/controller
接口层
接口实现层
服务层
服务实现层
工具层
过滤层
…
知识点1:为什么有session,cookie?
Web开发使用的协议是HTTP。
HTTP超文本传输协议,存在先天不足,是无状态,简单说就是协议有健忘症
所以为了解决无状态的问题,引入了两种解决机制:
都是要保存用户状态的
知识点2:会话和请求的区别
会话指的是一个时间段,客户端和服务器交互的一个时间段,称为一个会话
请求,客户端请求服务器的资源,称为请求。
在做上面的小栗子中,jar包也称作依赖,是我们手动自己去导入,而且在以后的工作中,尤其团队工作中,每个人所用依赖版本不一致,存在许多问题,这时就涉及到一个工具,Maven。Maven作为一个常用构建和管理各种项目的工具。
具体的Maven安装,创建项目在之前的博客里有写,这里就不再重复。
补充点:
Maven的功能:
依赖管理(jar包)、模块管理(父子模块)、插件管理(GAV来指定插件)、部署管理(在lifecycle中的方法)
Spring 是最受欢迎的企业级 Java 应用程序开发框架,数以百万的来自世界各地的开发人员使用 Spring 框架来创建性能好、易于测试、可重用的代码。
如何复制一份maven项目?
1、将文件夹中的mavendemo模块在文件夹中显示,并拷贝,复制一份,改名字为Springdemo。注意,文件夹内的XX.iml文件名也要和外面所改的名字一致,进入POM.xml文件中,再将开头的GAV中的artifactId也改为Springdemo,最将下面name 处的名字也改为Springdemo。
2、开始在IDEA中进行导入,File–》New–》Module from Existing Sources–》选择自己刚才改名字的文件夹下的POM.xml—》对Search for projects recursively打勾—》Next—》Next—》导入进来—》在Edit Configuration里配置Springdemo的部署
建立Spring项目:
新建一个工作空间—》选择Empty 项目—》选择新建的Spring_course文件夹—》finish—》将项目SDK(1.8)与项目语言等级(8)进行配置—》apply
File—》New—》Module from Existing Sources–》后面步骤与上面复制maven项目第二步后面一致
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>4.3.18.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>4.3.18.RELEASEversion>
dependency>
在项目main的Java目录下建立文件夹domain
domain中创建学生类
public class Students implements Cloneable,Serializable{
private int sid; //学号
private String sname; //姓名
private String gender; //性别
private String birthday; //出生日期
private String major; //专业
//一定要保留这个默认的无参数的构造方法,否则spring也无法实例化。
public Students() {
}
public Students(int sid, String sname, String gender, String birthday, String major) {
this.sid = sid;
this.sname = sname;
this.gender = gender;
this.birthday = birthday;
this.major = major;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Students{" +
"sid=" + sid +
", sname='" + sname + '\'' +
", gender='" + gender + '\'' +
", birthday='" + birthday + '\'' +
", major='" + major + '\'' +
'}';
}
}
再创建一个test文件夹,写测试类
/*
* Java中创建对象的方式有几种啊?
* 1.new :地球人都知道。
* 2.clone
* 3.反射
* 4.对象反序列化
* -----------------------------------------------
* 1.如何创建对象?
* 使用new。
* Spring也不使用new来创建对象,使用ioc容器来注入的。
* */
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="s3" class="com.xbky.domain.Students">
<property name="sid" value="400"/>
<property name="sname" value="小宋"/>
<property name="gender" value="男"/>
<property name="birthday" value="2001-2-20"/>
<property name="major" value="喜剧"/>
bean>
beans>
public class IocDemo2 {
public static void main(String[] args) {
//使用了spring ioc 容器注入了一个对象。没有使用new.内部也是通过反射+xml文档的解析来实现的。
ApplicationContext context1 = new ClassPathXmlApplicationContext("applicationContext.xml");
Students s2 = (Students) context.getBean("s3");
System.out.println(s2);
}
}
//打印:
//Students{sid=400, sname='小宋', gender='男', birthday='2001-2-20', major='喜剧'}
小结:SpringIOC 内部实现原理就是Xml解析+反射,注意,属性的初始化就是通过调用setxxx来实现的,对象的创建通过调用默认的无参构造方法去实现的,所以要求这个类必须要保留默认无参构造的方法!
什么是IOC容器?
xml中的< beans>…< beans>就是容器
Spring 最认同的技术是控制反转的**依赖注入(DI)**模式。控制反转(IoC)是一个通用的概念,它可以用许多不同的方式去表达,依赖注入仅仅是控制反转的一个具体的例子。
当编写一个复杂的 Java 应用程序时,应用程序类应该尽可能的独立于其他的 Java 类来增加这些类可重用可能性,当进行单元测试时,可以使它们独立于其他类进行测试。依赖注入(或者有时被称为配线)有助于将这些类粘合在一起,并且在同一时间让它们保持独立。
到底什么是依赖注入?让我们将这两个词分开来看一看。这里将依赖关系部分转化为两个类之间的关联。例如,类 A 依赖于类 B。现在,让我们看一看第二部分,注入。所有这一切都意味着类 B 将通过 IoC 被注入到类 A 中。
依赖注入可以以向构造函数传递参数的方式发生,或者通过使用 setter 方法 post-construction。
Spring 框架的一个关键组件是面向方面的程序设计(AOP)框架。一个程序中跨越多个点的功能被称为横切关注点,这些横切关注点在概念上独立于应用程序的业务逻辑。有各种各样常见的很好的关于方面的例子,比如日志记录、声明性事务、安全性,和缓存等等。
在 OOP 中模块化的关键单元是类,而在 AOP 中模块化的关键单元是方面。AOP 帮助你将横切关注点从它们所影响的对象中分离出来,然而依赖注入帮助你将你的应用程序对象从彼此中分离出来。
Spring 框架的 AOP 模块提供了面向方面的程序设计实现,可以定义诸如方法拦截器和切入点等,从而使实现功能的代码彻底的解耦出来。
1.Java创建对象有哪四种方式?
用new语句创建对象,这是最常用的创建对象的方式。
运用反射手段,调用Java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
调用对象的clone()方法。
运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法.
2.什么是maven?maven的核心功能有哪些?
Maven是基于项目对象模型(POM project object model),可以通过一小段描述信息(配置)来管理项目的构建,报告和文档的软件项目管理工具,通俗讲,就是通过pom.xml文件的配置获取jar包,而不用手动去添加jar包。
Maven的功能:依赖管理(jar包)、模块管理(父子模块)、插件管理(GAV来指定插件)、部署管理(在lifecycle中的方法)
3.什么是MVC?说说分层的好处。
MVC 即 Model、View、Controller :模型、视图、控制器。MVC 要实现的目标是将软件用户界面和业务逻辑分离以使代码可扩展性、可复用性、可维护性、灵活性加强。MVC流程如下:
1、Web浏览器发送HTTP请求到服务端,然后被Controller(Servlet)获取并进行处理(例如参数解析、请求转发)
2、Controller(Servlet)调用核心业务逻辑——Model部分,获得结果
3、Controller(Servlet)将逻辑处理结果交给View(JSP),动态输出HTML内容
4、动态生成的HTML内容返回到浏览器显示
分层好处:
分工明确(开发人员可以只关注整个结构中的其中某一层):使用MVC可以把数据库开发,程序业务逻辑开发,页面开发分开,每一层都具有相同的特征,方便以后的代码维护。它使程序员(Java开发人员)集中精力于业务逻辑,界面程序员(HTML和JSP开发人员)集中精力于表现形式上。
松耦合(可以降低层与层之间的依赖):视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码,同样,一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可。因为模型与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。
复用性高(利于各层逻辑的复用):像多个视图能够共享一个模型,不论你视图层是用flash界面或是wap界面,用一个模型就能处理他们。将数据和业务规则从表示层分开,就可以最大化从用代码。
有利于标准化(有利于通过工程化、工具化产生管理程序代码);
4.Spring的两大核心技术是什么?
5.什么是IOC/DI?
Inversion of Control, 控制反转:将对在自身对象中的一个内置对象的控制反转,反转后不再由自己本身的对象进行控制这个内置对象的创建,而是由第三方系统去控制这个内置对象的创建。
Dependency Injection, 依赖注入:自身对象中的内置对象是通过注入的方式进行创建。
6.谈谈面向对象编程与面向接口编程的区别。
7.什么是反射?说说反射是如何应用到spring框架上。
主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
Spring 中的 IOC 的底层实现原理就是反射机制,Spring 的容器会帮我们创建实例,该容器中使用的方法就是反射,通过解析 xml 文件,获取到 id 属性和 class 属性里面的内容,利用反射原理创建配置文件里类的实例对象,存入到 Spring 的 bean 容器中。
8.说说java 解析xml有哪些技术?
XML的解析方式分为四种:1、DOM解析;2、SAX解析;3、JDOM解析;4、DOM4J解析。其中前两种属于基础方法,是官方提供的平台无关的解析方式;后两种属于扩展方法,它们是在基础的方法上扩展出来的,只适用于java平台。
9.抽象类与接口的区别。
10.谈谈表单的同步提交与异步提交的区别。
同步强调的是顺序性,谁先谁后;异步则不存在这种顺序性。