项目实训博客 : 项目后端架构 , 项目的四端交互(前端 ,后端 ,模型端 ,数据库)的开发和维护 , 项目功能总览
作为项目的后端和前端交互功能主要开发者,我需要对项目的四端交互进行开发和维护.
总览:
整体项目结构如图所示:
前后端的交互:
前端封装了request.js :
方便前端向后端发送请求,它可以自请求发送前对请求做一些处理,比如统一加token,对请求参数统一加密,也可以在接受response后自动进行一些处理.
import axios from 'axios'
const request = axios.create({
baseURL: 'http://localhost:9090', // 这里是全局统一加上了 '/api' 前缀,也就是说所有接口都会加上'/api'前缀在,页面里面写接口的时候就不要加 '/api'了,否则会出现2个'/api',类似 '/api/api/user'这样的报错,切记!!!
timeout: 60000
})
// request 拦截器
// 可以自请求发送前对请求做一些处理
// 比如统一加token,对请求参数统一加密
request.interceptors.request.use(config => {
//config.headers['Content-Type'] = 'application/json;charset=utf-8';
if (!(config.data instanceof FormData)) {
config.headers['Content-Type'] = 'application/json;charset=utf-8';
}
// 设置请求头
let jwtToken = localStorage.getItem('jwtToken');
if (jwtToken) {
config.headers['jwtToken'] = jwtToken;
}
return config
}, error => {
return Promise.reject(error)
});
// response 拦截器
// 可以在接口响应后统一处理结果
request.interceptors.response.use(
response => {
let res = response.data;
// 如果是返回的文件
if (response.config.responseType === 'blob') {
return res
}
// 兼容服务端返回的字符串数据
if (typeof res === 'string') {
res = res ? JSON.parse(res) : res
}
return res;
},
error => {
console.log('err' + error) // for debug
return Promise.reject(error)
}
)
export default request
前端的jwt会被储存在浏览器的内存中登录不同的用户会被清除.
后端设置了拦截器:
webconfig:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许跨域访问的路径
.allowedOrigins("http://localhost:8080", "http://127.0.0.1:8080") // 允许跨域访问的源
.allowedMethods("GET", "POST", "PUT", "DELETE","INSERT") // 允许的HTTP方法
.allowedHeaders("*") // 允许的请求头
.allowCredentials(true) // 是否允许发送cookie
.maxAge(3600); // 预检请求的缓存时间
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册拦截器 并制定拦截的路径资源 /**为拦截所有资源 不拦截那些资源
registry.addInterceptor(loginCheckInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/login","/register");
}
}
InterceptorRegistry:
@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
//目标方法资源运行之前执行,true为放行,false为不放行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//System.out.println("preHandle运行了");
//获取请求的url
String url = request.getRequestURI().toString();
//判断url中是否包含login(config文件中已经实现了这一点,其实可以删掉)
if (url.contains("login") || url.contains("register")) {
//登录操作直接放行
return true;
}
//获取令牌(token)
String jwt = request.getHeader("jwtToken");
System.out.println("令牌校验获取到的jwt:" + jwt);
//判断令牌是否存在,如果不存在,返回错误结果(未登录)
if (jwt == null) {
//log.info("请求头token为空,返回未登录的信息");
Result error = Result.error(Constants.CODE_401,"NOT_LOGIN");
//手动将对象转换为json
String notLogin = JSONObject.toJSONString(error);
//返回错误信息
response.getWriter().write(notLogin);
return false;
}
//如果jwt存在,则校验jwt
try {
JwtUtils.parseJWT(jwt);
} catch (Exception e) {//jwt令牌解析失败
e.printStackTrace();
//log.info("解析令牌失败返回未登录的错误信息");
Result error = Result.error("NOT_LOGIN");
//手动将对象转换为json
String notLogin = JSONObject.toJSONString(error);
//返回错误信息
response.getWriter().write(notLogin);
return false;
}
//令牌解析成功
//放行资源(重要的一部)
return true;
}
}
两个组合起来可以拦截除了登录注册以外的所有请求,拦截下来会校验jwt令牌,校验通过才会直接放行.
后端统一返回结果Result:
package com.example.demo.common;
public class Result {
private Integer code;//响应码,1 代表成功; 0 代表失败
private String msg; //响应信息 描述字符串
private Object data; //返回的数据
public Result() {
}
public Result(Integer code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
//增删改 成功响应
public static Result success(){
return new Result(200,"success",null);
}
//查询 成功响应
public static Result success(Object data){
return new Result(200,"success",data);
}
public static Result success(String msg){
return new Result(200,msg,null);
}
public static Result success(Integer code,String msg,Object data){
return new Result(code,msg,data);
}
//失败响应
public static Result error(String msg){
return new Result(Constants.CODE_500,msg,null);
}
public static Result error(Integer code,String msg){
return new Result(code,msg,null);
}
public static Result error(Integer code,String msg,Object data){
return new Result(code,msg,data);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String toString() {
return "Result{code = " + code + ", msg = " + msg + ", data = " + data + "}";
}
}
后端的所有返回结果都会被封装进这个类中,方便前端使用.
后端与模型端的交互:
使用了java的HttpClient库:
以下是其中一个方法的示例:
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> data = new HashMap<>();
data.put("conversation_id",conversation_id);
data.put("instruction", content);
data.put("max_turns", "10");
String jsonBody = mapper.writeValueAsString(data);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:7860/chat"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
// 发送请求并处理响应
HttpClient client = HttpClient.newHttpClient();
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status code: " + response.statusCode());
System.out.println("Response body: " + response.body());
模型端会提供fastAPI生成的文档,以供后端使用;
后端与数据库的交互:
在 application.properties
中配置 MongoDB 连接参数:
spring.data.mongodb.uri=mongodb://localhost:27017/test
通过service层和repository层来进行交互
项目整体功能总览:
登录注册功能:
首页:
法律文书摘要生成:
其中星号和下载按钮是收藏功能和下载pdf功能
法律文书摘要收藏功能:

可点开查看详情和删除,查看详情可进一步打印成pdf
法律预测功能:

可打印为pdf
法律问答功能:
支持显示历史记录:
同是还可以清空历史记录:
感想:
通过这次创新实训,我们学到了很多东西,如mongodb的使用,模型的训练,模型的微调,fastAPI等等,了解到了大模型在当有着无比深厚的潜力