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());
}
}
标签:username,03,String,gender,09,JAVAWebMVC,vip,password,public 来源: https://www.cnblogs.com/shenmimao/p/16651924.html