注意:本項(xiàng)目前端頁(yè)面基于Vue.js框架編寫(xiě),后端服務(wù)基于Spring Boot框架編寫(xiě)乡洼。
傳送門(mén):vue實(shí)現(xiàn)教改系統(tǒng)的相關(guān)需求實(shí)現(xiàn)(前端)
1.操作數(shù)據(jù)庫(kù)
- 第一步:在yml文件中配置數(shù)據(jù)庫(kù)信息
spring:
# 配置數(shù)據(jù)庫(kù)連接信息
datasource:
username: education
password: 123456
url: jdbc:mysql://ip地址:端口號(hào)/education
driver-class-name: com.mysql.jdbc.Driver
# Spring Boot項(xiàng)目啟動(dòng)時(shí)加載數(shù)據(jù)庫(kù)文價(jià)
schema:
- classpath:sql/SD_Scholar.sql
# SD_Scholar.sql 在與 applicaton.yml 同一目錄下的 sql 目錄中僚纷,下面將會(huì)創(chuàng)建 SD_Scholar.sql
# mybatis 相關(guān)配置
mybatis:
configuration:
map-underscore-to-camel-case: true
- 第二步,創(chuàng)建數(shù)據(jù)庫(kù)文件
-- 這里列出的是一個(gè)非常簡(jiǎn)單的數(shù)據(jù)庫(kù)創(chuàng)建實(shí)例
-- alter table SD_Scholar AUTO_INCREMENT=1;
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for SD_Scholar
----------------------------
DROP TABLE IF EXISTS `SD_Scholar`;
CREATE TABLE `SD_Scholar` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`number` CHAR (15) DEFAULT NULL,
`password` VARCHAR (32) NOT NULL,
`identity` INT DEFAULT NULL,
`isDelete` INT(2) DEFAULT "0",
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
注意:第一次加載萬(wàn)數(shù)據(jù)庫(kù)之后脾还,即可在 yml 文件中將
- classpath:sql/SD_Scholar.sql
選項(xiàng)注釋掉性锭,以免重復(fù)創(chuàng)建
- 第三步:創(chuàng)建訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的 DAO
import com.lnpu.demo.bean.*;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Component;
import java.util.List;
@Mapper
@Component(value = "userMapper")
public interface UserMapper {
@Insert("INSERT INTO SD_Scholar(number,password,identity) VALUES(#{number},#{password},#{identity})")
public void insertUser(User user);
@Select("SELECT * FROM SD_Scholar WHERE number=#{number}")
public List<User> findUser(String number);
@Update("UPDATE SD_Scholar SET password=#{password} WHERE number=#{number}")
public void update(@Param("number") String number,
@Param("password") String password);
}
現(xiàn)在數(shù)據(jù)庫(kù)操作工作基本已經(jīng)完成,用戶(hù)只需要在對(duì)應(yīng)的 Service 文件中通過(guò)
@Autowired
自動(dòng)注入即可進(jìn)行數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)
2.配置啟動(dòng)端口以及 https 配置
# yml文件
# 設(shè)置端口信息以及配置https文件及其信息
server:
port: 8081
ssl:
key-store: classpath:1343113_www.xztywss.top.pfx
key-store-password: .abCde1fG
key-store-type: PKCS12
# 上述屬性值需要根據(jù)自己的情況進(jìn)行填寫(xiě)
# 1343113_www.xztywss.top.pfx 文件與 applicaton.yml 文件在同一目錄下
3.文件上傳功能
傳送門(mén)前端頁(yè)面
public ResultObject insertProject(HttpServletRequest request, MultipartFile file) {
// 設(shè)置 request 編碼格式
try {
request.setCharacterEncoding("UTF-8");
} catch (UnsupportedEncodingException e) {
return new ResultObject("other");
}
String number = request.getParameter("number");
// 這里只給出文件上傳邏輯涉兽,不包含其他信息的處理
// 先處理上傳的文件
if(!file.isEmpty()) {
String fileName = file.getOriginalFilename();
String path = null;
String type = fileName.indexOf(".") != -1 ? fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()) : null;
if (type != null) {
if ("ZIP".equals(type.toUpperCase())||"RAR".equals(type.toUpperCase())) {
// 時(shí)間戳
String timeStamp = String.valueOf(System.currentTimeMillis());
// 自定義的文件名稱(chēng)
String trueFileName = number + "_" + timeStamp + "_" + fileName;
// 項(xiàng)目在容器中實(shí)際發(fā)布運(yùn)行的根路徑
String realPath = request.getSession().getServletContext().getRealPath("/");
// 設(shè)置存放文件的路徑
path = "G:/workspace/fileSystem/Project_File/" + trueFileName;
File dest = new File(path);
//判斷文件父目錄是否存在
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdir();
}
try {
file.transferTo(dest);
} catch (IOException e) {
return new ResultObject("other");
}
project.setFileName(trueFileName);
}else {
return new ResultObject("format");
}
}else {
return new ResultObject("format");
}
}else {
return new ResultObject("empty");
}
return new ResultObject("success");
}
- 同時(shí)要注意招驴,Spring Boot 內(nèi)嵌的 Tomcat 默認(rèn)允許的最大的文件大小為 1MB,單次上傳最大為 10MB枷畏,如要修改别厘,需在 yml 文件中進(jìn)行配置
spring:
# 設(shè)置文件傳輸限制
http:
multipart:
enabled: true
max-file-size: 20MB
max-request-size: 100MB
4.跨域處理
// 加上注解 @CrossOrigin 即可解決跨域請(qǐng)求問(wèn)題
@CrossOrigin
@RestController
public class TestController {
@RequestMapping("/hello")
public String hello() {
return "Hello World!";
}
}
5.返回結(jié)果結(jié)構(gòu)化
- 想要使前后端交互更加高效,就需要設(shè)計(jì)一個(gè)固定格式的返回對(duì)象
ResultObject
拥诡,需要傳遞的數(shù)據(jù)可以存儲(chǔ)在對(duì)象里触趴。
public class ResultObject {
// 后臺(tái)返回碼
private int code;
// 后臺(tái)返回消息
private String msg;
// 結(jié)果
private Object result;
// 構(gòu)造函數(shù)
public ResultObject() {
super();
// TODO Auto-generated constructor stub
}
// 構(gòu)造函數(shù)
public ResultObject(int code, String msg, Object result) {
super();
this.code = code;
this.msg = msg;
this.result = result;
}
// 后臺(tái)處理成功時(shí)使用的構(gòu)造函數(shù)
public ResultObject(Object result) {
super();
this.code = 0;
this.msg = "success";
this.result = result;
}
// 屬性的setter、getter方法
// 此處省略...渴肉,請(qǐng)自行補(bǔ)全冗懦。
@Override
public String toString() {
return "ResultObject [code=" + code + ", msg=" + msg + ", result=" + result + "]";
}
}
- 在返回結(jié)果時(shí)使用
ResultObject
import com.lnpu.demo.bean.ResultObject;
@RestController
public class UserController {
@PostMapping("/test")
public ResultObject test(HttpServletRequest request, HttpServletResponse response) {
return new ResultObject(404, "false", "null");
}
}
6.Session進(jìn)行用戶(hù)狀態(tài)檢測(cè)
- 第一步:首先需要封裝一個(gè)存儲(chǔ)
Session
的容器
import javax.servlet.http.HttpSession;
import java.util.HashMap;
public class MySessionContext {
private static MySessionContext instance;
private HashMap<String, HttpSession> mymap;
private MySessionContext() {
mymap = new HashMap<String, HttpSession>();
}
public static MySessionContext getInstance() {
if (instance == null) {
instance = new MySessionContext();
}
return instance;
}
public synchronized void AddSession(HttpSession session) {
if (session != null) {
mymap.put(session.getId(), session);
}
}
public synchronized void DelSession(HttpSession session) {
if (session != null) {
mymap.remove(session.getId());
}
}
public synchronized HttpSession getSession(String session_id) {
if (session_id == null) return null;
return (HttpSession) mymap.get(session_id);
}
public synchronized boolean containsSession(String session_id) {
if (session_id == null) return false;
return mymap.containsKey(session_id);
}
}
- 第二步:創(chuàng)建一個(gè) Session 監(jiān)聽(tīng)器
import com.lnpu.demo.context.MySessionContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class SessionListener implements HttpSessionListener {
private MySessionContext myc = MySessionContext.getInstance();
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
myc.AddSession(httpSessionEvent.getSession());
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
myc.DelSession(session);
}
}
- 第三步:配置監(jiān)聽(tīng)器
import com.lnpu.demo.Listener.SessionListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 標(biāo)識(shí)本類(lèi)為配置類(lèi)
@Configuration
public class ListenerConfig {
@Bean
public SessionListener init() {
return new SessionListener();
}
}
- 第四步:操作 Session
// 需要引入的包
import com.lnpu.demo.context.MySessionContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
// 引入 session 容器
MySessionContext myc = MySessionContext.getInstance();
public void login(HttpServletRequest request) {
// 創(chuàng)建一個(gè)新的 session
HttpSession session = request.getSession();
// 獲取 sessionid
String sessionId = session.getId();
// 通過(guò) sessionId 獲取 session
session = myc.getSession(sessionId);
// 向 session 中添加信息
session.setAttribute("user", user);
// 設(shè)置 session 有效時(shí)間: 86400s,即一個(gè)工作日仇祭。
session.setMaxInactiveInterval(86400);
// 從 session 中獲取信息
User user = (User)session.getAttribute("user");
}
7.Base64 加密解密
// 導(dǎo)入
import java.util.Base64;
// 加密
Base64.Encoder encoder = Base64.getEncoder();
byte[] name= encoder.encode(name.getBytes());
// 解密
Base64.Decoder decoder = Base64.getDecoder();
decoder.decode(name);
8.跨域攔截器
- 第一步:實(shí)現(xiàn)攔截器
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class SessionInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
/*
* 注意:當(dāng)Access-Control-Allow-Credentials設(shè)置為ture時(shí)披蕉,Access-Control-Allow-Origin不能設(shè)置為*
* */
//支持跨域請(qǐng)求
response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", "*");
//是否支持cookie跨域
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "Authorization,Origin, X-Requested-With, Content-Type, Accept,Access-Token");//Origin, X-Requested-With, Content-Type, Accept,Access-Token
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
- 第二步:配置攔截器
import com.lnpu.demo.interceptor.SessionInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
//標(biāo)識(shí)為配置類(lèi)
@Configuration
public class InterpectorConfig extends WebMvcConfigurationSupport {
@Autowired
private SessionInterceptor sessionInterceptor;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(sessionInterceptor).addPathPatterns("/user/*");
registry.addInterceptor(sessionInterceptor).addPathPatterns("/project/*");
super.addInterceptors(registry);
}
}
* Linux系統(tǒng)查詢(xún)與結(jié)束指定進(jìn)程
// 查詢(xún)進(jìn)程
netstat -lnp|grep 8080
// 結(jié)束進(jìn)程
kill -9 進(jìn)程id
當(dāng)程序在Linux服務(wù)器上部署時(shí),需從防火墻中打開(kāi)指定的端口號(hào)才能訪(fǎng)問(wèn)到(博主是在阿里云的Linux服務(wù)器上部署的乌奇,需要在服務(wù)器上打開(kāi)端口没讲,并在寶塔面板中放行端口)。