Java教程

2022-09-03 第二小组 张晟源(JAVAWebMVC)

本文主要是介绍2022-09-03 第二小组 张晟源(JAVAWebMVC),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

JAVAWeb

一,MVC架构

是一种软件架构模式,把整个软件分为三层:Model,view,controller

Model:模型---获取数据,并处理,返回给 controller

  entity:数据库实体类 User --- user表

  service:业务控制层,其余的活都交给 service

  dao:数据模型层 --- 操作数据库,执行 sql

View:视图 --- 看得见的页面,渲染数据,页面

controller:控制器 --- nservlet,接请求,给响应

 

耦合度:代码之间的关联关系

为什么分层:降低耦合度

 

调用关系:

  View 层发起请求 -- Controller -- Service -- Dao -- Service -- Controller -- View

 

可以用一个 servlet 处理多个 post 请求:利用反射

可以定一个约定,必须提交到    /admin/xx.do

当前的servlet只接受 *.do 结尾的请求

写 *.do时,前面不能写  /

配置servlet映射时,* 和 / 不能同时出现,/* 除外

 

MVC 设计模式理念:一张表,一个 entity,一个servlet

 

二,MVC设计模式小例子

工程目录如下

1.View层编写

进行一个用户注册的界面,并指定接受请求并处理该页面的Servlet,View主要由就是jsp,html页面构成。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="register">
    <form>
        <p>
            账号:<input type="text" name="username" v-model="user.username" @blur="verifyUsername" placeholder="用户名在6-12位">
            <span>{{msg}}</span>
        </p>
        <p>
            密码:<input type="password" name="password" v-model="user.password">
        </p>
        <p>
            姓名:<input type="text" name="name" v-model="user.name">
        </p>
        <p>
            性别:<input type="radio" value="男" name="gender" v-model="user.gender"> 男
            <input type="radio" value="女" name="gender" v-model="user.gender"> 女
        </p>
        <p>
            头像:<input type="file" name="profile" ref="profile">
        </p>
        <p>
            <input type="button" value="提交" @click="registerData">
        </p>
    </form>
</div>
<script src="static/js/vue.js"></script>
<script src="static/js/axios.min.js"></script>
<script>
    const register = new Vue({
        el:"#register",
        data:{
            msg:"",
            user:{
                gender:'男'
            }
        },
        methods:{
            async verifyUsername() {
                if(this.user.username.length < 6 || this.user.username.length > 12){
                    this.msg = "用户名必须在6-12位";
                    return false;
                }
                //    定义一个标记
                let flag = false;
                //    在这个函数中,验证用户名
                //    发ajax请求到后台,验证用户名
                //    ajax是异步请求,ajax会单独开辟一个线程来自己走,和我们的主JS程序不在同一个线程内
                //    我们需要让我们的ajax和我们的主JS在同一个线程内
                //    通过async 和 await修饰符就把ajax改成了同步请求
                await axios.get("admin/checkUser.do?username=" + this.user.username).then(response=>{
                    // console.log(response.data);
                    this.msg = response.data.message;
                    if(response.data.code == '0'){
                        flag = false;
                    }
                    if(response.data.code == '1'){
                        flag = true;
                    }
                });
                // 返回值是一个Promise对象。是一个特殊的对象。3个属性
                return flag;
            },
            registerData(){
                // 这个result就是上面函数返回的Promise对象
                let result = this.verifyUsername();
                // ES6语法的“解构”,把上面函数的返回值拿到
                result.then(r => {
                    // 带有文件上传的数据提交
                    if(r) {
                    //    要求,如果上传的数据中包含了二进制数据(文件),需要使用formData,来封装数据
                        let formData = new FormData();
                        formData.append("username",this.user.username);
                        formData.append("password",this.user.password);
                        formData.append("name",this.user.name);
                        formData.append("gender",this.user.gender);
                    //    头像,文件怎么拼?
                    //    this.$refs.profile.files[0],获取对应的文件的二进制形式
                    //    $refs:代表设置了ref属性的表单元素
                    //    profile:找到ref属性为profile的表单元素
                    //    files[0]:找到ref属性为profile的第一个表单元素
                        formData.append("profile",this.$refs.profile.files[0]);
                    //    发请求
                    //    axios的完整写法
                        axios({
                            method:"post",
                            url:"admin/addVip.do",
                            data:formData,
                            // 请求头
                            /*
                            * 'content-Type':'multipart/form-data'
                            * 代表我要传输的数据以多部分的格式来传输。
                            * HTML要求提交文件:multipart/form-data
                            * 提交普通的数据:application/x-www-form-urlencoded
                            * */
                            headers:{
                                'content-Type':'multipart/form-data'
                            }
                        }).then(response => {
                           let data = response.data;
                           alert(data.message);
                           if(data.code == '1'){
                               location.href = "login.html";
                           }
                        })
                    }
                });
            }
        }
    });
</script>

</body>
</html>

2.Controller层的编写

Controller接受View层请求的Servlet

package com.jsoft.mvc.controller;


import com.alibaba.fastjson.JSON;
import com.jsoft.mvc.entity.Vip;
import com.jsoft.mvc.service.VipService;
import com.jsoft.mvc.service.impl.VipServiceImpl;
import com.jsoft.mvc.util.MessageUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDate;
import java.util.UUID;


@WebServlet("*.do")
@MultipartConfig // 用来标记当前的servlet要接收多部分的数据格式,当前的servlet可以接收文件
public class VipController extends HttpServlet {

//    Controller调用service
    private VipService vipService = new VipServiceImpl();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 利用反射取到对应的方法名
        String servletPath = req.getServletPath();
        String methodName = servletPath.substring(1);
        methodName = methodName.substring(methodName.lastIndexOf("/") + 1,methodName.length() - 3);
        try {
            Method method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            method.invoke(this,req,resp);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    private void addVip(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        PrintWriter out = resp.getWriter();

        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String name = req.getParameter("name");
        String gender = req.getParameter("gender");
        Vip vip = new Vip(username,password,name,gender);

        // 处理文件上传
        Part part = req.getPart("profile");

        String fileName = part.getSubmittedFileName();
        InputStream inputStream = part.getInputStream();
        // 文件名,防止出现一样的名字
        fileName = UUID.randomUUID() + fileName;

        // 根据日期创建图片所放的位置
        LocalDate localDate = LocalDate.now();
        String prePath = "/" + localDate.getYear() + "/" + localDate.getMonthValue() + "/";
        File file = new File("E:/upload" + prePath);
        if(!file.exists()){
//            创建多级目录
            file.mkdirs();
        }
        fileName = prePath + fileName;

        OutputStream outputStream = new FileOutputStream("E:/upload/" + fileName);
        byte [] b = new byte[1024];
        int len;
        while((len = inputStream.read(b))!= -1){
            outputStream.write(b,0,len);
        }

//        在数据库中同步保存文件的路径,只保存文件名
        vip.setProfile(fileName);

        int i = vipService.register(vip);
        if(i > 0) {
            out.write(JSON.toJSONString(new MessageUtil(1,"注册成功,请登录!")));
        } else {
            out.write(JSON.toJSONString(new MessageUtil(0,"注册失败,请重新填写!")));
        }

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

3.Model层的编写

Model层在具体的编写中包括dao层和bean层还有service层。

(1)bean层的编写

package com.jsoft.mvc.entity;

import java.io.Serializable;

/*
*   和表对应的实体类,entity
*   要求:
*       1.类名和表名相同
*       2.类中的属性名和表中的字段名相同
*       3.类中只能有对应的set,get方法和需要用到的构造器,如果有需要,可以写toString。
*       4.序列化。实现序列化接口
* */
public class Vip implements Serializable {


    private static final long serialVersionUID = -2352642267221918764L;
    private Integer id;
    private String username;
    private String password;
    private String name;
    private String gender;
    private String profile;
    private String salt;

    public Vip() {}

    public Vip(String username, String password,String name ,String gender ) {
        this.username = username;
        this.password = password;
        this.name = name;
        this.gender = gender;
    }

    public Vip(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    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 getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getProfile() {
        return profile;
    }

    public void setProfile(String profile) {
        this.profile = profile;
    }

    @Override
    public String toString() {
        return "Vip{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", gender='" + gender + '\'' +
                ", name='" + name + '\'' +
                ", profile='" + profile + '\'' +
                ", salt='" + salt + '\'' +
                '}';
    }
}

(2)dao层负责与数据库交互

public interface VipDao {

    int save(Vip vip) throws Exception;

    Vip findUserByUsername(String username) throws Exception;

}

return后的方式是工程目录下util工具类的连接数据库的方法

public class VipDaoImpl extends DAOImpl<Vip> implements VipDao {
    @Override
    public int save(Vip vip) throws Exception {
        String sql = "insert into vip(username,password,name,gender,salt,profile) values(?,?,?,?,?,?)";
        return update(sql,vip.getUsername(),vip.getPassword(),vip.getName(),vip.getGender(),vip.getSalt(),vip.getProfile());
    }

    @Override
    public Vip findUserByUsername(String username) throws Exception {
        String sql = "select id,username,password,name,gender,profile,salt from vip where username = ? ";
        return get(sql,username);
    }
}

4.Service层的编写

public interface VipService {

//    注册的方法
    int register(Vip vip);

    boolean checkUserIsExists(String username);

    boolean login(Vip vip);

}
public class VipServiceImpl implements VipService {

    private VipDao dao = new VipDaoImpl();

    @Override
    public int register(Vip vip) {
//        注册的业务执行的就是保存的操作
        try {
//            密码的加密处理
            // 生成盐
            String salt = MD5Util.getSalt();
            // 对密码进行加密
            // 加密过后还要重新赋值给vip
            vip.setPassword(MD5Util.stringToMD5(vip.getPassword() + salt));
            vip.setSalt(salt);
            return dao.save(vip);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean checkUserIsExists(String username) {
        try {
            Vip vip = dao.findUserByUsername(username);
            /*
            *    如果根据用户名查到的vip是null,说明用户名可用,用户名在数据中是没有的
            *   如果返回值是true,则用户名可用
            * */
            return Objects.isNull(vip);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

对密码进行加密,使用MD5 + 盐的方式,利用工具类的 MD5Util (需要导包)

public class MD5Util {

    /*
        获取加密的盐
     */
    public static String getSalt(){
        String words = "qwertyuiopasdfghjklzxcvbnm,./;'[]=/*-+!@#$^&%*()<>?";
        StringBuilder strb = new StringBuilder();
        // 随机获取8个字符,当作盐
        for (int i = 0; i < 8; i++) {
            strb.append(words.charAt((int) Math.floor(Math.random() * words.length())));
        }
        return strb.toString();
    }

    /*
        MD5加密
        MD5 + 盐 加密
     */
    public static String stringToMD5(String str){
        return DigestUtils.md2Hex(str.getBytes());
    }
}

 

这篇关于2022-09-03 第二小组 张晟源(JAVAWebMVC)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!