当前位置: 首页 > news >正文

成都网站建设 培训班google搜索引擎下载

成都网站建设 培训班,google搜索引擎下载,网上书城 网站建设方案,seo推广优化收费在前面两篇,我们基本上实现了图书管理系统所有的功能,但是我们发现没有登录也能对其进行修改。这是非常不安全的。因此这篇文章我们学习如何进行强制登录。只有登录进去才能进行操作。 这不是一个对外开放的项目 这篇文章我们将改写图书管理系统为强制登…

在前面两篇,我们基本上实现了图书管理系统所有的功能,但是我们发现没有登录也能对其进行修改。这是非常不安全的。因此这篇文章我们学习如何进行强制登录。只有登录进去才能进行操作。

这不是一个对外开放的项目

这篇文章我们将改写图书管理系统为强制登录版本。我们需要结合在统一功能中讲解的

拦截器、统一数据返回、统一异常处理。内容完整的再写一遍图书管理系统

一、实现强制登录

1.1自定义拦截器

1.新建interceptor目录。创建LoginInterceptor类去实现HandlerInterceptor接口

注意要加上@Component注解,代表已经交给Spring去管理。这个类才会被Spring检测到

2.重写preHandle方法。返回 true-放行。false拦截

3.验证用户是否登录。

//验证用户是否登录HttpSession session = request.getSession();UserInfo userInfo = (UserInfo) session.getAttribute(Constants.USER_SESSION_KEY);if(userInfo == null || userInfo.getId()<1){response.sendRedirect("/login.html");return false;}return true;
  • 如果没有登录则跳转到/login.html登录页面进行登录。return false
  • 如果已经登录那么直接return true。放行

1.2注册配置拦截器

1.新建Config目录,创建WebConfig类 实现 WebMvcConfigurer 接口

注意要加上@Configuration 才能生效。

2.新建我们刚刚自定义的拦截器成员变量

    @Autowiredprivate LoginInterceptor loginInterceptor;

3.重写addInterceptors方法。

addInterceptor:添加拦截器

addPathPatterns:添加拦截路径

excludePathPatterns:除了这些路径不用拦截

    @Overridepublic void addInterceptors(InterceptorRegistry registry) {// /**表示对所有路径生效registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(excludePath);}
    private List<String> excludePath = Arrays.asList("/user/login","/**/login.html","/css/**","/js/**","/pic/**");

自此。我们就实现了强制登录。

完整LoginInterceptor类代码

/*** 拦截器* 实现强制登录*/
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {/*** 处理请求前执行。* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("目标方法执行前执行:LoginInterceptor.preHandle...");//true-放行。false拦截//验证用户是否登录HttpSession session = request.getSession();UserInfo userInfo = (UserInfo) session.getAttribute(Constants.USER_SESSION_KEY);if(userInfo == null || userInfo.getId()<1){response.sendRedirect("/login.html");return false;}return true;}/*** 接口处理完成之后执行的方法* @param request* @param response* @param handler* @param modelAndView* @throws Exception*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}
}

完整WebConfig类代码

package com.qiyangyang.springbook.demos.Config;import com.qiyangyang.springbook.demos.interceptor.LoginInterceptor;
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.WebMvcConfigurer;import java.util.Arrays;
import java.util.List;//配合拦截器进行拦截处理
//注意一定要加上@Configuration这个注解 才会生效
@Configuration
public class WebConfig implements WebMvcConfigurer {private List<String> excludePath = Arrays.asList("/user/login","/**/login.html","/css/**","/js/**","/pic/**");@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// /**表示对所有路径生效registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(excludePath);}//    @Override
//    public void addInterceptors(InterceptorRegistry registry) {
//        // /** 表示对所有的路径生效
//        registry.addInterceptor(loginInterceptor).addPathPatterns("/**")
//                //排除一些路径
//                .excludePathPatterns("/user/login")
//                .excludePathPatterns("/**/**.html")
//                .excludePathPatterns("/css/**")
//                .excludePathPatterns("/js/**")
//                .excludePathPatterns("/pic/**");
//    }
}

二、实现统一返回数据

2.1创建Result类

统一返回数据

1.首先创建Result类,这个类帮我们更加细致化的对后端返回结果进行描述

package com.qiyangyang.springbook.demos.model;import lombok.Data;/*** 定义统一返回数据* 对返回结果进行细致化描述* @param <T>*/@Data
public class Result <T>{private Integer code;//后端响应状态码,业务状态码 200成功,-1失败,-2表示未登录private String Errmsg; //后端发生错误的原因private T data; //返回的数据public static <T>Result<T> success(T data){Result<T> result = new Result<T>();result.setCode(200);result.setData(data);return  result;}public static <T>Result<T> fail(T data,String errmg){Result<T> result = new Result<T>();result.setCode(-1);result.setErrmsg(errmg);result.setData(data);return  result;}public static <T> Result<T> fail(String errMsg){Result<T> result = new Result<T>();result.setCode(-1);result.setErrmsg(errMsg);return result;}/*** 未登录时*/public static <T> Result<T> unlogin(){Result<T> result = new Result<T>();result.setCode(-2);result.setErrmsg("用户未登录");return result;}}

2.2创建ResponseAdvice类

创建ResponseAdvice并实现ResponseBodyAdvice接口

* 统一数据返回格式 * 不需要改变程序任何接口,只需要写一个类。实现ResponseBodyAdvice。加上@ControllerAdvice注解

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {@Autowiredprivate ObjectMapper objectMapper;@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {//重写supports方法。看对哪些请求进行处理。返回true--进行处理  返回false。不进行处理return true;}@SneakyThrows@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {//重写beforeBodyWrite方法。如果body是Result类型。不再进行包装。如果不是。那么就进行包装//接口执行完成之后,返回结果之前会执行这个方法。//注意需要处理String类型的if (body instanceof Result){return body;}if (body instanceof String){return objectMapper.writeValueAsString(Result.success(body));}return Result.success(body);}
}

 //重写beforeBodyWrite方法。如果body是Result类型。不再进行包装。如果不是。那么就进行包装
//接口执行完成之后,返回结果之前会执行这个方法。(beforeBodyWrite)
//注意需要处理String类型的 

此时我们会发现。我们之前定义的后端接口的返回结果已经不再适用。

例如:

我们进行用户登录:

发现返回的数据是这种json类型的

三、修改前端代码

登录页代码

将判断条件修改为

if(result.code==200 && result.data ==true){//验证成功location.href = "book_list.html";}else {alert("登录失败,用户名不存在或密码错误!");}

图书列表显示页代码

var books = result.records;

修改为

var books = result.data.records;
 function getBookList() {//ajax页面一加载就会被执行的程序。 我们还可以进行方法封装$.ajax({type: "get",url: "/book/getListByPage" + location.search,success: function (result) {var books = result.data.records;console.log(books); //如果前端没有报错,那么我们打印日志。观察后端返回结果对不对var findHtml = "";  //用这个变量来拼接HTMLfor (var book of books) {//拼接html。假如后端返回10个tr那么直接for循环拼接在这里面。findHtml//我们用单引号拼接,因为里面有双引号

 图书分页代码

//翻页信息$("#pageContainer").jqPaginator({totalCounts: result.count, //总记录数pageSize: 10, //每页的个数visiblePages: 5, //可视页数currentPage: result.pageRequest.currentPage, //当前页码

修改为

//翻页信息$("#pageContainer").jqPaginator({totalCounts: result.data.count, //总记录数pageSize: 10, //每页的个数visiblePages: 5, //可视页数currentPage: result.data.pageRequest.currentPage, //当前页码

前端添加图书代码

注意这里有一个坑

我们照上面修改

          success: function (result) {console.log(result.data);if (result == "成功添加图书") {alert("添加成功");location.href = "book_list.html";} else {alert(result.data);}

修改为

          success: function (result) {console.log(result.data);if (result.code ==200 && result.data == "成功添加图书") {alert("添加成功");location.href = "book_list.html";} else {alert(result.data);}

 会发现添加图书功能依然完成不了。且会执行else块的代码

并且报错为undefind。

这是由于返回的数据是String类型。

而上面我们进行处理的后端返回数据都是json类型。如果是json类型。那么前端会自动转换为对象进行处理。

而Sring就不会进行处理。因此代码没有按我们的预期执行。

 

我们通过Postman和Fiddler抓包也能看到返回的是text类型文本。而不是json。

而我们登录接口返回的是json

两种解决方式

1.前端处理,把字符串转为对象

2.后端处理,设置 content-type 返回结果 (更加合理)

这种问题也称作边界问题。

后端处理我们可以进行统一返回Json。这样更加合理。

为什么String类型会出现这种情况。

这个就是在我们统一返回结果类中进行处理的。

    @SneakyThrows@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {//重写beforeBodyWrite方法。如果body是Result类型。不再进行包装。如果不是。那么就进行包装//接口执行完成之后,返回结果之前会执行这个方法。//注意需要处理String类型的if (body instanceof Result){return body;}if (body instanceof String){return objectMapper.writeValueAsString(Result.success(body));}return Result.success(body);}

发现body如果是String类型。我们将这个body进行了writeValueAsString转成了String

因此我们将

    @RequestMapping("/addBook")public String addBook(BookInfo bookInfo){log.info("添加图书,bookInfo:{}",bookInfo);/**

修改为

    @RequestMapping(value = "/addBook",produces = "application/json")public String addBook(BookInfo bookInfo){log.info("添加图书,bookInfo:{}",bookInfo);/**

这样我们返回的数据就是Json格式的了。再试试添加图书,就会发现,我们添加成功

因此我们不用返回String类型的就可以避免这个问题了

正确的返回我们本就应该返回为Result类型。试着修改代码如下。

    @RequestMapping( "/addBook")public Result addBook(BookInfo bookInfo){log.info("添加图书,bookInfo:{}",bookInfo);/*** 参数校验*/if(!StringUtils.hasLength(bookInfo.getBookName())|| !StringUtils.hasLength(bookInfo.getAuthor())|| !StringUtils.hasLength(bookInfo.getPublish())|| bookInfo.getCount() <=0|| bookInfo.getPrice()==null){return Result.fail("参数错误!!!");}/*** 添加图书*//*** 出现错误比如参数错误。添加过程出现异常,因为MySQL会出现一些异常* 我们使用try/catch来捕获。*/try {bookService.insertBook(bookInfo);}catch (Exception e){log.error("添加图书失败,e:{}",e);return Result.fail("内部发生错误,请联系管理员!");}/*** 返回成功添加吐过表示图书插入成功。*/return Result.success("成功添加图书");}

修改图书代码

查询当前 Id 图书代码修改

        //查询当前ID图书$.ajax({type: "get",url: "book/queryBookById"+location.search,success:function(book){if(book!=null){$("#bookId").val(book.id);$("#bookName").val(book.bookName);$("#bookAuthor").val(book.author);$("#bookStock").val(book.count);$("#bookPrice").val(book.price);$("#bookPublisher").val(book.publish);$("#bookStatus").val(book.status);}}

修改为

            type: "get",url: "book/queryBookById"+location.search,success:function(result){//前端根据后端返回结果,针对不同的情况进行处理if(result.code == 200 && result.data != null){var book = result.data;if(book!=null){$("#bookId").val(book.id);$("#bookName").val(book.bookName);$("#bookAuthor").val(book.author);$("#bookStock").val(book.count);$("#bookPrice").val(book.price);$("#bookPublisher").val(book.publish);$("#bookStatus").val(book.status);}}

修改更新图书代码

                type: "get",url: "/book/updateBook",data:$("#updateBook").serialize(),//提交整个表单success:function(result){if(result == true){alert("更新成功");location.href = "book_list.html"}else{alert("更新失败");}

修改为

                type: "get",url: "/book/updateBook",data:$("#updateBook").serialize(),//提交整个表单success:function(result){if(result.code==200 && result.data == true){alert("更新成功");location.href = "book_list.html"}else{alert("更新失败");}

删除图书代码

                if(result == true){alert("删除成功");location.href = "book_list.html";}

修改为

                if(result.code ==200 && result.data == true){alert("删除成功");location.href = "book_list.html";}

批量删除图书代码

                if(result == true){alert("批量删除成功");location.href = "book_list.html";}else{alert("删除失败,请联系管理员!");}

修改为

                if(result.code ==200 && result.data == true){alert("批量删除成功");location.href = "book_list.html";}else{alert("删除失败,请联系管理员!");}

四、统一异常处理

@ControllerAdvice
public class ErrorHandler {/*** 捕获异常,返回统一结果*///通过@ExceptionHandler这个注解来捕获异常@ExceptionHandlerpublic Result handler(Exception e){return Result.fail(e.getMessage());}
}


文章转载自:
http://yolk.Lnnc.cn
http://postlude.Lnnc.cn
http://levalloisian.Lnnc.cn
http://commensalism.Lnnc.cn
http://illusion.Lnnc.cn
http://conelrad.Lnnc.cn
http://angelological.Lnnc.cn
http://shepherdess.Lnnc.cn
http://nutant.Lnnc.cn
http://lighterage.Lnnc.cn
http://pergelisol.Lnnc.cn
http://russianise.Lnnc.cn
http://paintress.Lnnc.cn
http://nordic.Lnnc.cn
http://casualization.Lnnc.cn
http://cower.Lnnc.cn
http://kilometrage.Lnnc.cn
http://lookup.Lnnc.cn
http://prognoses.Lnnc.cn
http://sidereal.Lnnc.cn
http://bitterish.Lnnc.cn
http://outsight.Lnnc.cn
http://straddle.Lnnc.cn
http://floodwall.Lnnc.cn
http://babka.Lnnc.cn
http://salvo.Lnnc.cn
http://elasmobranch.Lnnc.cn
http://visualize.Lnnc.cn
http://bbc.Lnnc.cn
http://greenmail.Lnnc.cn
http://caravaner.Lnnc.cn
http://versifier.Lnnc.cn
http://sgml.Lnnc.cn
http://jingler.Lnnc.cn
http://mobe.Lnnc.cn
http://tights.Lnnc.cn
http://oxford.Lnnc.cn
http://hostler.Lnnc.cn
http://existentialism.Lnnc.cn
http://skewwhiff.Lnnc.cn
http://tod.Lnnc.cn
http://rhizocephalan.Lnnc.cn
http://declarer.Lnnc.cn
http://hypogastrium.Lnnc.cn
http://carbuncular.Lnnc.cn
http://unmatchable.Lnnc.cn
http://daisy.Lnnc.cn
http://firefang.Lnnc.cn
http://wallsend.Lnnc.cn
http://administration.Lnnc.cn
http://hardworking.Lnnc.cn
http://racehorse.Lnnc.cn
http://refreshant.Lnnc.cn
http://velate.Lnnc.cn
http://stockinet.Lnnc.cn
http://revealable.Lnnc.cn
http://dactinomycin.Lnnc.cn
http://gravicembalo.Lnnc.cn
http://noachian.Lnnc.cn
http://cydonia.Lnnc.cn
http://arbalest.Lnnc.cn
http://siam.Lnnc.cn
http://stab.Lnnc.cn
http://serjeant.Lnnc.cn
http://radicant.Lnnc.cn
http://rhematize.Lnnc.cn
http://unscrupulous.Lnnc.cn
http://grangerize.Lnnc.cn
http://nisei.Lnnc.cn
http://saida.Lnnc.cn
http://perchromate.Lnnc.cn
http://grossularite.Lnnc.cn
http://pyogenous.Lnnc.cn
http://intacta.Lnnc.cn
http://childe.Lnnc.cn
http://characterful.Lnnc.cn
http://weighbeam.Lnnc.cn
http://falsity.Lnnc.cn
http://neeze.Lnnc.cn
http://instigate.Lnnc.cn
http://vinifera.Lnnc.cn
http://legazpi.Lnnc.cn
http://knuckle.Lnnc.cn
http://coneflower.Lnnc.cn
http://deproletarize.Lnnc.cn
http://daimon.Lnnc.cn
http://polyurethane.Lnnc.cn
http://manger.Lnnc.cn
http://synchronize.Lnnc.cn
http://halmahera.Lnnc.cn
http://saddlebag.Lnnc.cn
http://upward.Lnnc.cn
http://lothian.Lnnc.cn
http://celibatarian.Lnnc.cn
http://candlelight.Lnnc.cn
http://trioxide.Lnnc.cn
http://accoutrement.Lnnc.cn
http://lateritious.Lnnc.cn
http://presentability.Lnnc.cn
http://hempseed.Lnnc.cn
http://www.dt0577.cn/news/101313.html

相关文章:

  • 桂林市是哪个省的专业搜索引擎seo技术公司
  • 各大网站的404推广信息哪个平台好
  • 网站建设硬件预算链接交换平台
  • phpmysql网站开发实例成都排名推广
  • 做影视网站侵权吗南京seo排名收费
  • 美丽深圳公众号二维码原图seo推广如何做
  • 九亭做网站公司seo专业优化方法
  • 360免费建站pomhub网站推广的途径和方法
  • abc网站建设怎么样淘宝优化关键词的步骤
  • 做一张网站图得多少钱免费大数据网站
  • 织梦 旅游网站模板域名收录提交入口
  • 网页制作和网站开发广告推广app
  • 广州营销型网站建设公司哪家靠谱链接交易网
  • 搜索引擎广告的优缺点谷歌搜索引擎seo
  • 建设公司宣传网站1688网站
  • 设计网站需要考虑哪些佛山网站开发公司
  • 网络营销的网站定位网络营销方案的范文
  • 旅游网站建设翻译nba中国官方网站
  • 北京 做网站比较有名的蒙牛牛奶推广软文
  • 易企网站建设网站建设解决方案
  • 网站模板 数据库推广普通话主题手抄报
  • 当今做网站的流行怎么有自己的网站
  • 做网站建设注册商标是多少类seo新闻
  • 做游戏推广网站百度网盘app下载安装手机版
  • 沈阳建设工程信息网官方网站seo查询平台
  • 无本钱创业22种方法石家庄seo网络推广
  • 惠阳网络推广公司廊坊网站排名优化公司哪家好
  • python做网站的多吗seo网站排名优化培训教程
  • 网页设计提升班搜索引擎优化的方式有哪些
  • 辽宁省建设工程信息网电话win7优化工具