Maven实现登录案例

效果

本文按照我自己写代码的顺序来行文

视频无法观看?点我

maven+idea实现登录功能效果图

工具

  • jdk13.0.2
  • Maven 3.6.3
  • idea

src/main/java

  1. dao:保存实现访问数据库功能的文件
  2. domain:保存JavaBean文件
  3. service:service层
  4. servlet:servlet层
  5. utils:存放一些工具类

src/main/resources

  1. druid.properties:JDBC配置文件

src/main/webapp

  1. 存放html、css和js文件

src/test/java

  1. 主要测试了一下访问数据库的功能是否正常

代码分析

  1. 按照dao层service层servlet层的顺序

数据库层

CREATE DATABASE day0429;
USE day0429;
CREATE TABLE USER(
	id INT PRIMARY KEY AUTO_INCREMENT,
	username VARCHAR(32) NOT NULL,
	PASSWORD VARCHAR(32) NOT NULL
);

dao层

  1. UserDao接口

只有一个方法,根据从登录页面获取的用户名和密码查询数据库

User findByUsernameAndPassword(String username, String password);
  1. UserDaoImpl实现类
public class UserDaoImpl implements UserDao {

    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

    @Override
    public User findByUsernameAndPassword(String username, String password) {
        User user = null;
        // user查询失败后会抛异常并终止,try catch一下保证方法返回null
        try {
            String sql = "select * from user where username = ? and password = ?";
            user = template.queryForObject(sql,
                    new BeanPropertyRowMapper<User>(User.class), username, password);
        } catch (DataAccessException e) {}
        return user;
    }
}

domain层

  1. User类

简便起见,只有三个字段,实现注册功能的时候可以再扩充。
还需要生成getter、setter方法。
为了测试使用,生成toString方法。

private int id;
private String username;
private String password;
  1. ResultInfo.java

这个类的功能是在servlet中保存用户登录的信息,将来可以传递给js,js再写入html页面中

private boolean flag;
private Object data;
private String errorMsg;

service层

  1. UserService接口

只提供login的方法,由UserServiceImpl.java来实现其功能

User login(User user);
  1. UserServiceImpl.java

service层存在的意义就是,调用dao层一些基础的方法,来实现更复杂的功能,向servlet层提供更好的服务。
所以这里的login方法调用了dao层实现类的方法,完成查询功能。

private UserDao userDao = new UserDaoImpl();

    @Override
    public User login(User user) {
        return userDao.findByUsernameAndPassword(user.getUsername(), user.getPassword());
    }

servlet层

这里把servlet抽取出了BaseServlet,将来就让实现具体功能的servlet去继承它。

BaseServlet.java

public class BaseServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String uri = req.getRequestURI();
        String methodName = uri.substring(uri.lastIndexOf('/') + 1);
        try {
        	/* 
        	这里的this,是调用方法的对象,例如有一个路径为`/user/*`的
        	UserServlet继承了BaseServlet,在UserServlet中有一个login
        	方法,那么浏览器访问`/user/login`的时候,就会调用
        	BaseServlet的service方法
        	*/
            Method method = this.getClass().getMethod(methodName,
                    HttpServletRequest.class, HttpServletResponse.class);
            method.invoke(this, req, resp);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

	// writeValue是自定义的一个方法,用于把obj对象序列化为json,并返回给客户端
    public void writeValue(HttpServletResponse response, Object obj) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        response.setContentType("application/json;charset=utf-8");
        mapper.writeValue(response.getOutputStream(), obj);
    }

	// 功能同writeValue(),返回的是字符串形式的json
    public String writeValueAsString(Object obj) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.writeValueAsString(obj);
    }
}

UserServlet.java

// 只要访问路径末尾处含/user/的,都归它管😁
@WebServlet("/user/*")
public class UserServlet extends BaseServlet {

    private UserService service = new UserServiceImpl();

	/* 
		根据用户输入的用户名和密码,封装为一个User对象,
		将来把这个对象传递给service层的login方法,
		查询数据库中有无此用户
	*/
    private User preProcessUser(HttpServletRequest request) {
        Map<String, String[]> map = request.getParameterMap();

        User user = new User();

        try {
            BeanUtils.populate(user, map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return user;
    }

	// 用于完成登录验证的工作,把返回的消息序列化为json返回给客户端
    public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        User user = preProcessUser(request);
        User u = service.login(user);
        ResultInfo info;
        if (u == null) {
            info = new ResultInfo(false, "用户名或密码错误");
        } else {
            info = new ResultInfo(true);
            HttpSession session = request.getSession();
            session.setAttribute("user", u);
        }
        writeValue(response, info);
    }

    public void getUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        User user = (User) request.getSession().getAttribute("user");
        writeValue(response, user);
    }

}

工具类

JDBCUtils.java,此处不再赘述,会附上源代码文件

视图层

这一层简单介绍一下html、css和js文件。

index.html

由于本文主题是登录案例,故index.html就直接作为登录页面了。
wrap盒子作为父盒子,是为了方便使用伸缩盒子。

<div class="wrap">
        <div class="title" id="title">Welcome</div>
        <form action="" method="post" id="login-form">
            <input type="text"name="username" id="username" placeholder="登录" >
            <input type="password" name="password" id="password" placeholder="密码">
            <input type="button" value="立即登录" id="login-btn">
        </form>
        <div class="help">
            <a href="#">忘记密码</a>
            <i></i>
            <a href="#">立即注册</a>
        </div>
    </div>

index.css

使用了less+rem布局,利用flex.js进行媒体查询。由于flex.js是把整个页面划分为10份,所以html的根字号是psd图宽度除以10。只适配了移动端,在PC端显示有问题。

以下贴出的是由less生成的css代码,less的被我手残删了。。

  • 分享一个做rem适配小技巧:
    • 先做pc端的页面,用像素表示。
    • 在less文件的开头给出html的根字号,以宽640px的psd图为例,html根字号就是:@size: 640px / 10;
    • 再选中所有的px,把它替换为rem / @size;@size那里的640px不要替换单位哦。
html {
  height: 100%;
}
body {
  height: 100%;
  /* 
  	背景渐变的本质是用渐变色模拟一张背景图像,
  	故应该用background-image,此处用了background简写
  */
  background: linear-gradient(135deg, #6cc9b6, #3878ca) no-repeat;
}
.wrap,
form {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.title {
  padding: 4.5625rem 0 1.890625rem;
  font-size: 1.40625rem;
  color: #fff;
}
form input {
  width: 7.5rem;
  height: 1.25rem;
  padding-left: 0.46875rem;
  box-sizing: border-box;
  margin-bottom: 0.53125rem;
  background-color: transparent;
  border: 0.015625rem solid #fff;
  border-radius: 0.625rem;
  font-size: 0.40625rem;
  color: #fff;
}
form input::placeholder {
  color: rgba(255, 255, 255, 0.5);
}
form input[type="button"] {
  padding-left: 0;
  background-color: #56b3f5;
  font-size: 0.5rem;
  border: 0 none;
}
.help {
  display: flex;
  justify-content: space-between;
  position: relative;
  width: 3.4375rem;
  height: 0.390625rem;
}
.help a {
  text-align: center;
  font-size: 0.3125rem;
  color: rgba(255, 255, 255, 0.5);
}
.help i {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 0.015625rem;
  height: 0.3125rem;
  background-color: #fff;
}

index.js

$.get()$.post()是jQuery提供的实现ajax的函数,故不要忘记导入jQuery

$(function () {

    $("#login-btn").click(function () {
        $.post("user/login", $("#login-form").serialize(), function (data) {
            if (data.flag) {
                location.href = "index_ok.html";
            } else {
                $("#title").html(data.errorMsg);
                // 若登录失败,则调整字体大小。因为我的错误提示字数较多
                $("#title").css("font-size", "1rem");
            }
        });
    });
});

pom.xml配置

这个怎么可能少得了~😜

其它都是常规配置,我这里只讲一下tomcat7-maven-plugin的配置

<plugin>
   <groupId>org.apache.tomcat.maven</groupId>
   <artifactId>tomcat7-maven-plugin</artifactId>
   <version>2.2</version>
   <configuration>
   <!-- 配置Tomcat9 -->
     <server>tomcat9</server>
     <update>true</update>
   </configuration>
 </plugin>

总结

这个案例还是蛮简单的,不过它对业务代码层次的划分还是让我觉得很有学习意义的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值