前后端项目整合

目录

前端,去掉mock

设置跨域

修改前端登录请求路径

 全局异常处理

改代码


前端,去掉mock

直接注释或删除main.js中引入的mock.js就可以

 去掉之后前端肯定请求报错,接下来就是设置跨域

设置跨域

这段,前端项目都给写好了,打开就可以

最后,我的修改成这样,port是前端项目端口,target是后端请求路径

  devServer: {
    // development server port 8000
    port: 8001,
    // If you want to turn on the proxy, please remove the mockjs /src/main.jsL11
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        ws: false,
        changeOrigin: true,
        pathRewrite: { // 路径重写,
          '^/api': '' // 替换target中的请求地址,也就是说以后你在请求http://api.codingmore.top/v2/XXXXX这个地址的时候直接写成/api即可。
        }
      }
    }
  },

后端设置

package com.han.springbootshiro.config.shiro;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@Configuration
public class CorsConfig implements Filter {

    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 允许任何域名使用
        corsConfiguration.addAllowedOriginPattern("*");
        // 允许任何头
        corsConfiguration.addAllowedHeader("*");
        // 允许任何方法(post、get等)
        corsConfiguration.addAllowedMethod("*");
        //允许cookie
        corsConfiguration.setAllowCredentials(true);// 是否支持安全证书(必需参数)
        corsConfiguration.setMaxAge(3600L);// 预检请求的有效期,单位为秒。
        corsConfiguration.addExposedHeader("set-cookie");
        corsConfiguration.addExposedHeader("access-control-allow-headers");
        corsConfiguration.addExposedHeader("access-control-allow-methods");
        corsConfiguration.addExposedHeader("access-control-allow-origin");
        corsConfiguration.addExposedHeader("access-control-max-age");
        corsConfiguration.addExposedHeader("X-Frame-Options");

        return corsConfiguration;
    }


    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        // 对接口配置跨域设置
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsFilter(source);
    }



    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
        response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpStatus.NO_CONTENT.value());
            return;
        } else {
            filterChain.doFilter(request, response);
        }
    }

    @Bean
    public FilterRegistrationBean replaceTokenFilter(){
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setDispatcherTypes(DispatcherType.REQUEST);
        registration.setFilter( new CorsConfig ());
        registration.addUrlPatterns("/*");
        registration.setName("crosFilter ");
        registration.setOrder(1);
        return registration;
    }
}

修改前端登录请求路径

修改 src/api/login.js 中请求路径,修改成自己的项目请求路径就可以了,我的是这样

export function login (parameter) {
  return request({
    url: '/system/user/login',
    method: 'post',
    data: parameter
  })
}

export function getInfo () {
  return request({
    url: '/system/user/userInfo',
    method: 'get'
    
  })
}

export function logout () {
  return request({
    url: '/system/user/logout',
    method: 'get'
  })
}

注意请求方式要和后端一致,就是method,我的后端方法使get请求方式,所以还需要修改一下

 @PostMapping("login")
    public Result login(@RequestBody User user){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUsername(), user.getPassword());
        subject.login(usernamePasswordToken);
        return new Result().success().setData(subject.getSession().getId());
    }

现在登录的话,会发现 即使输入正确的用户名密码,后端也会报错

是因为前端密码进行了md5加密,加密后密码肯定与数据库密码匹配不上

删除加密就好了,要是有需要,可以在整合完毕后再加

 全局异常处理

刚才登录错误的时候,前端提示的直接是后端的报错信息,这个不是我们想要的,在后端进行统一的异常处理

package com.han.springbootshiro.aop;

import com.han.springbootshiro.common.Result;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * @author han
 */
@RestControllerAdvice
public class GloabException {


    @ExceptionHandler(UnknownAccountException.class)
    public Result handler(UnknownAccountException unknownAccountException){
        Result<Object> result = new Result().error();
        result.setMsg("未知用户");
        return result;
    }

    @ExceptionHandler(IncorrectCredentialsException.class)
    public Result handler(IncorrectCredentialsException incorrectCredentialsException){
        Result<Object> result = new Result().error();
        result.setMsg("密码错误");
        return result;
    }

    @ExceptionHandler(Exception.class)
    public Result handler(Exception exception){
        Result<Object> result = new Result().error();
        result.setMsg("网络错误");
        return result;
    }

}

我只定义了这几个异常,大家有需要,可以自行增加

改代码

再次登录,发现提示信息也不是我们后端返回的msg

继续 修改

src/utils/request.js

封装的request中有响应拦截器,在拦截器中做一下修改

// response interceptor
request.interceptors.response.use((response) => {
const { code, msg, data } = response.data
  if (code !== 200) {
    if (code === 401) {
      store.dispatch('Logout').then(() => {
        this.$router.push('/user/login')
      })
    }
    const errorMsg = msg || '未知错误'
    // eslint-disable-next-line no-undef
    return Promise.reject(errorMsg)
  } else {
    return data
  }
}, errorHandler)

发起请求返回的code只要不是200,我们就认为报错了,把报错信息返回去,也就是msg,否则正常返回data中数据就可以。

login.vue

请求失败的方法,err本身就是 错误信息

 所以修改成这样就可以了

requestFailed (err) {
      this.isLoginError = true
      this.$notification['error']({
        message: '错误',
        description: err || '请求出现错误,请稍后再试',
        duration: 4
      })
    }

 现在用户名密码错误的话,错误提示信息正确,但是用户名密码正确的话,一直报错。。。。很无奈,

找了半天,发现用户名密码正确的情况下一直走的是requestFailed (err) 方法,

看返回的code是200没错,找了半天才发现是在Login方法里报错了,这个reponse其实就是data,这个方法后端直接返回的是个sessionid,data.result应该是这个报错,修改一下

 修改完后是这样,如果跟我返回的信息不一样,可以自己打日志,按照自己的代码修改

// 登录
    Login ({ commit }, userInfo) {
      return new Promise((resolve, reject) => {
        login(userInfo).then(response => {
          console.log(response)
          const result = response
          storage.set(ACCESS_TOKEN, result, new Date().getTime() + 7 * 24 * 60 * 60 * 1000)
          commit('SET_TOKEN', result)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

修改之后,报错变了,现在是请求用户信息失败,好,接着修改

 看一下后台报错,

Request method 'GET' not supported,

请求方式有问题,修改请求方式,

依然报错,看前端控制台,返回数据正常,而且是调用了userInfo之后,又调用了logOut方法,应该是获取到userInfo信息之后,解析异常

 在userInfo中打印一下返回的信息

 发现自己返回的信息中没有result,修改 const result = response

// 获取用户信息
    GetInfo ({ commit }) {
      return new Promise((resolve, reject) => {
        getInfo().then(response => {
          const result = response
          if (result.permissions && result.permissions.length > 0) {
            const permissions = result.permissions
            commit('SET_PERMISSIONS', permissions)
            commit('SET_INFO', result)
          } else {
            reject(new Error('getInfo: roles must be a non-null array !'))
          }

          commit('SET_NAME', { name: result.name, welcome: welcome() })
          commit('SET_AVATAR', result.avatar)

          resolve(response)
        }).catch(error => {
          reject(error)
        })
      })
    },

再次登录,跳转到了404页面,看一下控制台打印的路由跳转信息,先是跳转到/dashboard/workplace,然后跳转到404页面,这样应该是没有权限造成的,

我们可以定义一个不需要权限的空页面,或者没有权限不让他登录就可以 router.config.js

Empty是来自ant design vue 的一个空组件

 还有permission.js中登录后默认跳转路由也改一下

 修改完后登录是这样

 如果需要展示其他页面,可以把router.config.js 中对应页面的权限删掉就可以了

 或者可以在数据库给对应角色加上权限就可以了

需要新增页面的,也是在router.config.js中编写路由,导入对应的组件,这里不在展示

到现在,前后端分离算是整合完毕

在下一步是整合redis做shiro缓存,会话管理,然后就是密码加密

Logo

前往低代码交流专区

更多推荐