Browse Source

first commit

xusonglin 5 years ago
parent
commit
6b64d27b25
65 changed files with 2266 additions and 0 deletions
  1. 15 0
      src/main/java/com/jkcredit/sysnews/SysNewsApplication.java
  2. 38 0
      src/main/java/com/jkcredit/sysnews/config/AccessControlAllowOriginFilter.java
  3. 24 0
      src/main/java/com/jkcredit/sysnews/config/AjaxAccessDeniedHandler.java
  4. 24 0
      src/main/java/com/jkcredit/sysnews/config/AjaxAuthenticationEntryPoint.java
  5. 33 0
      src/main/java/com/jkcredit/sysnews/config/AjaxAuthenticationFailureHandler.java
  6. 35 0
      src/main/java/com/jkcredit/sysnews/config/AjaxAuthenticationSuccessHandler.java
  7. 24 0
      src/main/java/com/jkcredit/sysnews/config/AjaxLogoutSuccessHandler.java
  8. 36 0
      src/main/java/com/jkcredit/sysnews/config/AuthenticationEntryPointHandler.java
  9. 70 0
      src/main/java/com/jkcredit/sysnews/config/JwtAuthenticationFilter.java
  10. 35 0
      src/main/java/com/jkcredit/sysnews/config/MyPermissionEvaluator.java
  11. 39 0
      src/main/java/com/jkcredit/sysnews/config/MybatisPlusConfigurer.java
  12. 42 0
      src/main/java/com/jkcredit/sysnews/config/RbacAuthorityService.java
  13. 125 0
      src/main/java/com/jkcredit/sysnews/config/SecurityConfiguration.java
  14. 46 0
      src/main/java/com/jkcredit/sysnews/config/SwaggerConfiguration.java
  15. 14 0
      src/main/java/com/jkcredit/sysnews/mapper/NavigationBarMapper.java
  16. 20 0
      src/main/java/com/jkcredit/sysnews/mapper/NewsArticleMapper.java
  17. 16 0
      src/main/java/com/jkcredit/sysnews/mapper/PermissionMapper.java
  18. 18 0
      src/main/java/com/jkcredit/sysnews/mapper/PhotoMapper.java
  19. 16 0
      src/main/java/com/jkcredit/sysnews/mapper/UserMapper.java
  20. 27 0
      src/main/java/com/jkcredit/sysnews/model/dto/newsArticle/NewsArticleDto.java
  21. 22 0
      src/main/java/com/jkcredit/sysnews/model/dto/photo/PhotoDto.java
  22. 33 0
      src/main/java/com/jkcredit/sysnews/model/po/links/LinksPo.java
  23. 36 0
      src/main/java/com/jkcredit/sysnews/model/po/navigationBar/NavigationBarPo.java
  24. 44 0
      src/main/java/com/jkcredit/sysnews/model/po/newsArticle/NewsArticlePo.java
  25. 28 0
      src/main/java/com/jkcredit/sysnews/model/po/permission/PermissionPo.java
  26. 33 0
      src/main/java/com/jkcredit/sysnews/model/po/photo/PhotoPo.java
  27. 31 0
      src/main/java/com/jkcredit/sysnews/model/po/user/UserPo.java
  28. 27 0
      src/main/java/com/jkcredit/sysnews/model/vo/common/ResponseVo.java
  29. 31 0
      src/main/java/com/jkcredit/sysnews/model/vo/newsArticle/NewsArticleVo.java
  30. 22 0
      src/main/java/com/jkcredit/sysnews/model/vo/photo/PhotoVo.java
  31. 43 0
      src/main/java/com/jkcredit/sysnews/resource/base/BaseResource.java
  32. 13 0
      src/main/java/com/jkcredit/sysnews/resource/base/BizResource.java
  33. 14 0
      src/main/java/com/jkcredit/sysnews/resource/base/WebResource.java
  34. 97 0
      src/main/java/com/jkcredit/sysnews/resource/web/newsArticle/NewsArticleResource.java
  35. 28 0
      src/main/java/com/jkcredit/sysnews/resource/web/newsArticle/fb/NewsArticleFB.java
  36. 17 0
      src/main/java/com/jkcredit/sysnews/resource/web/newsArticle/fb/NewsArticleQueryFB.java
  37. 110 0
      src/main/java/com/jkcredit/sysnews/resource/web/photo/PhotoResource.java
  38. 23 0
      src/main/java/com/jkcredit/sysnews/resource/web/photo/fb/PhotoEditFB.java
  39. 25 0
      src/main/java/com/jkcredit/sysnews/resource/web/photo/fb/PhotoFB.java
  40. 18 0
      src/main/java/com/jkcredit/sysnews/resource/web/photo/fb/PhotoQueryFB.java
  41. 36 0
      src/main/java/com/jkcredit/sysnews/service/base/BaseService.java
  42. 24 0
      src/main/java/com/jkcredit/sysnews/service/newsArticle/NewsArticleService.java
  43. 121 0
      src/main/java/com/jkcredit/sysnews/service/newsArticle/NewsArticleServiceImpl.java
  44. 15 0
      src/main/java/com/jkcredit/sysnews/service/permission/PermissionService.java
  45. 26 0
      src/main/java/com/jkcredit/sysnews/service/permission/PermissionServiceImpl.java
  46. 27 0
      src/main/java/com/jkcredit/sysnews/service/photo/PhotoService.java
  47. 149 0
      src/main/java/com/jkcredit/sysnews/service/photo/PhotoServiceImpl.java
  48. 58 0
      src/main/java/com/jkcredit/sysnews/service/security/CustomUserDetailsService.java
  49. 15 0
      src/main/java/com/jkcredit/sysnews/service/user/UserService.java
  50. 28 0
      src/main/java/com/jkcredit/sysnews/service/user/UserServiceImpl.java
  51. 13 0
      src/main/java/com/jkcredit/sysnews/spi/lang/constant/CommonConstant.java
  52. 17 0
      src/main/java/com/jkcredit/sysnews/spi/lang/exception/ServiceException.java
  53. 41 0
      src/main/java/com/jkcredit/sysnews/spi/web/data/ResponseData.java
  54. 19 0
      src/main/java/com/jkcredit/sysnews/util/AssertUtils.java
  55. 25 0
      src/main/java/com/jkcredit/sysnews/util/BeanUtil.java
  56. 31 0
      src/main/java/com/jkcredit/sysnews/util/JwtTokenUtil.java
  57. 32 0
      src/main/java/com/jkcredit/sysnews/util/UploadUtil.java
  58. 14 0
      src/main/resources/application-dev.yml
  59. 14 0
      src/main/resources/application-prod.yml
  60. 17 0
      src/main/resources/application.yml
  61. 51 0
      src/main/resources/mapper/NewsArticleMapper.xml
  62. 19 0
      src/main/resources/mapper/PermissionMapper.xml
  63. 42 0
      src/main/resources/mapper/PhotoMapper.xml
  64. 29 0
      src/main/resources/mapper/UserMapper.xml
  65. 11 0
      src/test/java/com/jkcredit/sysnews/SysNewsApplicationTests.java

+ 15 - 0
src/main/java/com/jkcredit/sysnews/SysNewsApplication.java

@@ -0,0 +1,15 @@
+package com.jkcredit.sysnews;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@SpringBootApplication
+public class SysNewsApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(SysNewsApplication.class, args);
+    }
+
+}

+ 38 - 0
src/main/java/com/jkcredit/sysnews/config/AccessControlAllowOriginFilter.java

@@ -0,0 +1,38 @@
+package com.jkcredit.sysnews.config;
+
+import org.springframework.stereotype.Component;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/1/13 14:09
+ * @version: V1.0
+ **/
+@Component
+public class AccessControlAllowOriginFilter implements Filter {
+
+    @Override
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+        HttpServletResponse response = (HttpServletResponse) servletResponse;
+        response.setHeader("Access-Control-Allow-Origin", "*");
+        response.setHeader("Access-Control-Allow-Credentials", "true");
+        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
+        response.setHeader("Access-Control-Max-Age", "3600");
+        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
+        filterChain.doFilter(servletRequest, response);
+    }
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+
+    }
+
+    @Override
+    public void destroy() {
+
+    }
+}

+ 24 - 0
src/main/java/com/jkcredit/sysnews/config/AjaxAccessDeniedHandler.java

@@ -0,0 +1,24 @@
+package com.jkcredit.sysnews.config;
+
+import com.alibaba.fastjson.JSON;
+import com.jkcredit.sysnews.model.vo.common.ResponseVo;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.web.access.AccessDeniedHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+public class AjaxAccessDeniedHandler implements AccessDeniedHandler {
+
+    @Override
+    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
+        httpServletResponse.setContentType("application/json;charset=UTF-8");
+        httpServletResponse.setContentType("application/json");
+        httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
+        httpServletResponse.getWriter().write(JSON.toJSONString(new ResponseVo(403, "无权限", "")));
+    }
+}

+ 24 - 0
src/main/java/com/jkcredit/sysnews/config/AjaxAuthenticationEntryPoint.java

@@ -0,0 +1,24 @@
+package com.jkcredit.sysnews.config;
+
+import com.alibaba.fastjson.JSON;
+import com.jkcredit.sysnews.model.vo.common.ResponseVo;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+public class AjaxAuthenticationEntryPoint implements AuthenticationEntryPoint {
+
+    @Override
+    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
+        httpServletResponse.setContentType("application/json;charset=UTF-8");
+        httpServletResponse.setContentType("application/json");
+        httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+        httpServletResponse.getWriter().write(JSON.toJSONString(new ResponseVo(401, "未登录", "")));
+    }
+}

+ 33 - 0
src/main/java/com/jkcredit/sysnews/config/AjaxAuthenticationFailureHandler.java

@@ -0,0 +1,33 @@
+package com.jkcredit.sysnews.config;
+
+import com.alibaba.fastjson.JSON;
+import com.jkcredit.sysnews.model.vo.common.ResponseVo;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+public class AjaxAuthenticationFailureHandler implements AuthenticationFailureHandler {
+
+    @Override
+    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
+        /**
+         * if (e instanceof UsernameNotFoundException || e instanceof BadCredentialsException) {
+         *                 map.put("message","用户名或密码错误");
+         *             } else if (e instanceof DisabledException) {
+         *                 map.put("message","账户被禁用");
+         *             } else {
+         *                 map.put("message","登录失败!");
+         *             }
+         */
+        httpServletResponse.setContentType("application/json;charset=UTF-8");
+        httpServletResponse.setContentType("application/json");
+        httpServletResponse.setStatus(HttpServletResponse.SC_OK);
+        httpServletResponse.getWriter().write(JSON.toJSONString(new ResponseVo(500, "用户名或密码错误", "")));
+    }
+}

+ 35 - 0
src/main/java/com/jkcredit/sysnews/config/AjaxAuthenticationSuccessHandler.java

@@ -0,0 +1,35 @@
+package com.jkcredit.sysnews.config;
+
+import com.alibaba.fastjson.JSON;
+import com.jkcredit.sysnews.model.vo.common.ResponseVo;
+import com.jkcredit.sysnews.util.JwtTokenUtil;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class AjaxAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
+
+    @Override
+    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
+        User userDetails = (User) authentication.getPrincipal();
+
+        String jwtToken = JwtTokenUtil.generateToken(userDetails.getUsername(), 3600 * 24, "_secret", userDetails.getAuthorities());
+        Map<String, String> result = new HashMap<>();
+        result.put("token", jwtToken);
+
+        httpServletResponse.setContentType("application/json;charset=UTF-8");
+        httpServletResponse.setContentType("application/json");
+        httpServletResponse.setStatus(HttpServletResponse.SC_OK);
+        httpServletResponse.getWriter().write(JSON.toJSONString(new ResponseVo(200, "登录成功", result)));
+    }
+}
+

+ 24 - 0
src/main/java/com/jkcredit/sysnews/config/AjaxLogoutSuccessHandler.java

@@ -0,0 +1,24 @@
+package com.jkcredit.sysnews.config;
+
+import com.alibaba.fastjson.JSON;
+import com.jkcredit.sysnews.model.vo.common.ResponseVo;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+public class AjaxLogoutSuccessHandler implements LogoutSuccessHandler {
+
+    @Override
+    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
+        httpServletResponse.setContentType("application/json;charset=UTF-8");
+        httpServletResponse.setContentType("application/json");
+        httpServletResponse.setStatus(HttpServletResponse.SC_OK);
+        httpServletResponse.getWriter().write(JSON.toJSONString(new ResponseVo(200, "登出成功", "")));
+    }
+}

+ 36 - 0
src/main/java/com/jkcredit/sysnews/config/AuthenticationEntryPointHandler.java

@@ -0,0 +1,36 @@
+package com.jkcredit.sysnews.config;
+
+import com.alibaba.fastjson.JSON;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/1/7 21:30
+ * @version: V1.0
+ **/
+@Component
+public class AuthenticationEntryPointHandler implements AuthenticationEntryPoint {
+    @Override
+    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
+        response.setContentType("application/json;charset=utf-8");
+        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+        PrintWriter out = response.getWriter();
+        Map<String, Object> map = new HashMap<>();
+        map.put("code", 403);
+        map.put("message", "未登录");
+        out.write(JSON.toJSONString(map));
+        out.flush();
+        out.close();
+    }
+}

+ 70 - 0
src/main/java/com/jkcredit/sysnews/config/JwtAuthenticationFilter.java

@@ -0,0 +1,70 @@
+package com.jkcredit.sysnews.config;
+
+import com.alibaba.fastjson.JSONArray;
+import com.jkcredit.sysnews.service.security.CustomUserDetailsService;
+import com.jkcredit.sysnews.util.JwtTokenUtil;
+import io.jsonwebtoken.Claims;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+
+import javax.annotation.Resource;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/27 23:50
+ * @version: V1.0
+ **/
+public class JwtAuthenticationFilter extends BasicAuthenticationFilter {
+    @Resource
+    CustomUserDetailsService userDetailsService;
+
+    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
+        super(authenticationManager);
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
+
+        String header = request.getHeader("Authorization");
+        if (header == null || !header.startsWith("Bearer ")) {
+            chain.doFilter(request, response);
+            return;
+        }
+        try {
+            UsernamePasswordAuthenticationToken authentication = getAuthentication(header, request, response);
+            SecurityContextHolder.getContext().setAuthentication(authentication);
+        }catch (Exception e){
+            e.toString();
+        }
+
+        chain.doFilter(request, response);
+    }
+
+    private UsernamePasswordAuthenticationToken getAuthentication(String header, HttpServletRequest request, HttpServletResponse response) {
+        String authToken = header.substring("Bearer ".length());
+        Claims claims = JwtTokenUtil.parseToken(authToken, "_secret");
+        String username = claims.getSubject();
+//        List<GrantedAuthority> grantedAuthorities = (List<GrantedAuthority>) claims.get("authorities");
+        List<SimpleGrantedAuthority> grantedAuthorityList = JSONArray.parseArray(claims.get("authorities").toString()).toJavaList(SimpleGrantedAuthority.class);
+        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
+            User principal = new User(username, "", grantedAuthorityList);
+            UsernamePasswordAuthenticationToken authentication =
+                    new UsernamePasswordAuthenticationToken(principal, null, grantedAuthorityList);
+            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+            return authentication;
+        }
+        return null;
+    }
+}

+ 35 - 0
src/main/java/com/jkcredit/sysnews/config/MyPermissionEvaluator.java

@@ -0,0 +1,35 @@
+package com.jkcredit.sysnews.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.access.PermissionEvaluator;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.io.Serializable;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/1/8 23:20
+ * @version: V1.0
+ **/
+@Configuration
+public class MyPermissionEvaluator implements PermissionEvaluator {
+    @Override
+    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
+        boolean accessible = false;
+        String privilege = targetDomainObject + ":" + permission;
+        for (GrantedAuthority authority : authentication.getAuthorities()) {
+            if (privilege.equalsIgnoreCase(authority.getAuthority())) {
+                accessible = true;
+                break;
+            }
+        }
+        return accessible;
+    }
+
+    @Override
+    public boolean hasPermission(Authentication authentication, Serializable serializable, String s, Object o) {
+        return false;
+    }
+}

+ 39 - 0
src/main/java/com/jkcredit/sysnews/config/MybatisPlusConfigurer.java

@@ -0,0 +1,39 @@
+package com.jkcredit.sysnews.config;
+
+import com.baomidou.mybatisplus.core.injector.ISqlInjector;
+import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
+import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/28 9:06 AM
+ * @version: V1.0
+ **/
+@Configuration
+@MapperScan("com.jkcredit.sysnews.mapper")
+public class MybatisPlusConfigurer {
+    /**
+     * 分页插件
+     *
+     * @return PaginationInterceptor
+     */
+    @Bean
+    public PaginationInterceptor paginationInterceptor() {
+        return new PaginationInterceptor();
+    }
+
+
+    /**
+     * 逻辑删除
+     *
+     * @return
+     */
+    @Bean
+    public ISqlInjector sqlInjector() {
+        return new LogicSqlInjector();
+    }
+}

+ 42 - 0
src/main/java/com/jkcredit/sysnews/config/RbacAuthorityService.java

@@ -0,0 +1,42 @@
+package com.jkcredit.sysnews.config;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+import org.springframework.util.AntPathMatcher;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashSet;
+import java.util.Set;
+
+@Component("rbacauthorityservice")
+public class RbacAuthorityService {
+    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
+
+        Object userInfo = authentication.getPrincipal();
+
+        boolean hasPermission = false;
+
+        if (userInfo instanceof UserDetails) {
+
+            String username = ((UserDetails) userInfo).getUsername();
+
+            //获取资源
+            Set<String> urls = new HashSet();
+            urls.add("/app/**"); // 这些 url 都是要登录后才能访问,且其他的 url 都不能访问!
+
+            AntPathMatcher antPathMatcher = new AntPathMatcher();
+
+            for (String url : urls) {
+                if (antPathMatcher.match(url, request.getRequestURI())) {
+                    hasPermission = true;
+                    break;
+                }
+            }
+
+            return hasPermission;
+        } else {
+            return false;
+        }
+    }
+}

+ 125 - 0
src/main/java/com/jkcredit/sysnews/config/SecurityConfiguration.java

@@ -0,0 +1,125 @@
+package com.jkcredit.sysnews.config;
+
+import org.springframework.beans.factory.BeanInitializationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/1/3 10:14
+ * @version: V1.0
+ **/
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+@Import(SecurityProblemSupport.class)
+public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
+    @Autowired
+    AjaxAuthenticationEntryPoint authenticationEntryPoint;  //  未登陆时返回 JSON 格式的数据给前端(否则为 html)
+
+    @Autowired
+    AjaxAuthenticationSuccessHandler authenticationSuccessHandler;  // 登录成功返回的 JSON 格式数据给前端(否则为 html)
+
+    @Autowired
+    AjaxAuthenticationFailureHandler authenticationFailureHandler;  //  登录失败返回的 JSON 格式数据给前端(否则为 html)
+
+    @Autowired
+    AjaxLogoutSuccessHandler logoutSuccessHandler;  // 注销成功返回的 JSON 格式数据给前端(否则为 登录时的 html)
+
+    @Autowired
+    AjaxAccessDeniedHandler accessDeniedHandler;    // 无权访问返回的 JSON 格式数据给前端(否则为 403 html 页面)
+
+    private final UserDetailsService userDetailsService;
+    private final AuthenticationManagerBuilder authenticationManagerBuilder;
+
+    public SecurityConfiguration(UserDetailsService userDetailsService,
+                                 AuthenticationManagerBuilder authenticationManagerBuilder) {
+        this.userDetailsService = userDetailsService;
+        this.authenticationManagerBuilder = authenticationManagerBuilder;
+    }
+
+    @PostConstruct
+    public void init() {
+        try {
+            authenticationManagerBuilder
+                    .userDetailsService(userDetailsService)
+                    .passwordEncoder(passwordEncoder());
+        } catch (Exception e) {
+            throw new BeanInitializationException("Security configuration failed", e);
+        }
+    }
+
+    @Bean
+    @Override
+    public AuthenticationManager authenticationManagerBean() throws Exception {
+        return super.authenticationManagerBean();
+    }
+
+    // 此处需要使用@Bean引入,作用不是为了上面方法中使用
+    // 作用在于使用@Bean将PasswordEncoder作为Bean引入
+    // 同时此方法也可以指定加密方式
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+
+        // 去掉 CSRF
+        http.csrf().disable()
+                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 使用 JWT,关闭token
+                .and()
+
+                .httpBasic().authenticationEntryPoint(authenticationEntryPoint)
+
+                .and()
+                .authorizeRequests()
+                .antMatchers("/swagger-ui.html")
+                .permitAll()
+
+                .anyRequest()
+                .access("@rbacauthorityservice.hasPermission(request,authentication)") // RBAC 动态 url 认证
+
+                .and()
+                .formLogin()  //开启登录
+                .successHandler(authenticationSuccessHandler) // 登录成功
+                .failureHandler(authenticationFailureHandler) // 登录失败
+                .permitAll()
+
+                .and()
+                .logout()
+                .logoutSuccessHandler(logoutSuccessHandler)
+                .permitAll();
+
+        // 记住我
+        http.rememberMe().rememberMeParameter("remember-me")
+                .userDetailsService(userDetailsService).tokenValiditySeconds(3600);
+
+        http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); // 无权访问 JSON 格式的数据
+//        http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); // JWT Filter
+        http.addFilter(new JwtAuthenticationFilter(authenticationManager()));
+    }
+
+    @Override
+    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+        auth
+                .userDetailsService(userDetailsService)
+                .passwordEncoder(passwordEncoder());
+    }
+}

+ 46 - 0
src/main/java/com/jkcredit/sysnews/config/SwaggerConfiguration.java

@@ -0,0 +1,46 @@
+package com.jkcredit.sysnews.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 15:59
+ * @version: V1.0
+ **/
+public class SwaggerConfiguration {
+    // todo
+    @Bean
+    public Docket createRestApi() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(apiInfo())//调用apiInfo方法,创建一个ApiInfo实例,里面是展示在文档页面信息内容
+                .select()
+                //控制暴露出去的路径下的实例
+                //如果某个接口不想暴露,可以使用以下注解
+                //@ApiIgnore 这样,该接口就不会暴露在 swagger2 的页面下
+                .apis(RequestHandlerSelectors.basePackage("com.example.zwd.springbootswagger2.controller"))
+                .paths(PathSelectors.any())
+                .build();
+    }
+    //构建 api文档的详细信息函数
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                //页面标题
+                .title("Spring Boot Swagger2 构建RESTful API")
+                //条款地址
+                .termsOfServiceUrl("http://despairyoke.github.io/")
+                .contact("zwd")
+                .version("1.0")
+                //描述
+                .description("API 描述")
+                .build();
+    }
+}

+ 14 - 0
src/main/java/com/jkcredit/sysnews/mapper/NavigationBarMapper.java

@@ -0,0 +1,14 @@
+package com.jkcredit.sysnews.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jkcredit.sysnews.model.po.navigationBar.NavigationBarPo;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/29 20:57
+ * @version: V1.0
+ **/
+public interface NavigationBarMapper extends BaseMapper<NavigationBarPo> {
+
+}

+ 20 - 0
src/main/java/com/jkcredit/sysnews/mapper/NewsArticleMapper.java

@@ -0,0 +1,20 @@
+package com.jkcredit.sysnews.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jkcredit.sysnews.model.dto.newsArticle.NewsArticleDto;
+import com.jkcredit.sysnews.model.po.newsArticle.NewsArticlePo;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 22:47
+ * @version: V1.0
+ **/
+public interface NewsArticleMapper extends BaseMapper<NewsArticlePo> {
+    IPage<NewsArticlePo> getNewsArticles(Page page, @Param("query")NewsArticleDto newsArticleDto);
+
+    NewsArticlePo getNewsArticleById(Long id);
+}

+ 16 - 0
src/main/java/com/jkcredit/sysnews/mapper/PermissionMapper.java

@@ -0,0 +1,16 @@
+package com.jkcredit.sysnews.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jkcredit.sysnews.model.po.permission.PermissionPo;
+
+import java.util.List;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/27 23:11
+ * @version: V1.0
+ **/
+public interface PermissionMapper extends BaseMapper<PermissionPo> {
+    List<PermissionPo> getPermissionsByUserId(Long userId);
+}

+ 18 - 0
src/main/java/com/jkcredit/sysnews/mapper/PhotoMapper.java

@@ -0,0 +1,18 @@
+package com.jkcredit.sysnews.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jkcredit.sysnews.model.dto.photo.PhotoDto;
+import com.jkcredit.sysnews.model.po.photo.PhotoPo;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 0:52
+ * @version: V1.0
+ **/
+public interface PhotoMapper extends BaseMapper<PhotoPo> {
+    IPage<PhotoPo> getPhotos(Page page, @Param("query")PhotoDto photoDto);
+}

+ 16 - 0
src/main/java/com/jkcredit/sysnews/mapper/UserMapper.java

@@ -0,0 +1,16 @@
+package com.jkcredit.sysnews.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jkcredit.sysnews.model.po.user.UserPo;
+
+import java.util.Optional;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/27 22:55
+ * @version: V1.0
+ **/
+public interface UserMapper extends BaseMapper<UserPo> {
+    Optional<UserPo> getUserByUsername(String username);
+}

+ 27 - 0
src/main/java/com/jkcredit/sysnews/model/dto/newsArticle/NewsArticleDto.java

@@ -0,0 +1,27 @@
+package com.jkcredit.sysnews.model.dto.newsArticle;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 23:05
+ * @version: V1.0
+ **/
+@Data
+public class NewsArticleDto implements Serializable {
+    private static final long serialVersionUID = 8514340584369948319L;
+    private Long id;
+
+    private String title;
+
+    private String newsAbstract;
+
+    private String content;
+
+    private Long photoId;
+
+    private Long navigationBarId;
+}

+ 22 - 0
src/main/java/com/jkcredit/sysnews/model/dto/photo/PhotoDto.java

@@ -0,0 +1,22 @@
+package com.jkcredit.sysnews.model.dto.photo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 0:29
+ * @version: V1.0
+ **/
+@Data
+public class PhotoDto implements Serializable {
+    private static final long serialVersionUID = 255689497266802675L;
+    private Long id;
+    private String name;
+    private String url;
+    private Integer type;
+    private Integer activated;
+    private Integer status;
+}

+ 33 - 0
src/main/java/com/jkcredit/sysnews/model/po/links/LinksPo.java

@@ -0,0 +1,33 @@
+package com.jkcredit.sysnews.model.po.links;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/29 20:51
+ * @version: V1.0
+ **/
+@Data
+@ToString
+@TableName("links")
+public class LinksPo implements Serializable {
+    private static final long serialVersionUID = -5116129250631663779L;
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String name;
+    private String url;
+    private Long photoId;
+    private Integer activated;
+    private Date createTime;
+    private Date updateTime;
+    private Integer status;
+}

+ 36 - 0
src/main/java/com/jkcredit/sysnews/model/po/navigationBar/NavigationBarPo.java

@@ -0,0 +1,36 @@
+package com.jkcredit.sysnews.model.po.navigationBar;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/29 20:46
+ * @version: V1.0
+ **/
+@Data
+@ToString
+@TableName("navigation_bar")
+public class NavigationBarPo implements Serializable {
+    private static final long serialVersionUID = -218690040563280483L;
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String name;
+    private Long parentId;
+    private String parentIds;
+    private Integer level;
+    private String url;
+    private Integer homePageFlag;
+    private Integer homePageOrder;
+    private Integer activated;
+    private Date createTime;
+    private Date updateTime;
+}

+ 44 - 0
src/main/java/com/jkcredit/sysnews/model/po/newsArticle/NewsArticlePo.java

@@ -0,0 +1,44 @@
+package com.jkcredit.sysnews.model.po.newsArticle;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/29 20:42
+ * @version: V1.0
+ **/
+@Data
+@ToString
+@TableName("news_article")
+public class NewsArticlePo implements Serializable {
+    private static final long serialVersionUID = -840655960099220658L;
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private String title;
+
+    private String newsAbstract;
+
+    private String content;
+
+    private Long photoId;
+
+    private Long navigationBarId;
+
+    private Integer activated;
+
+    private Date createTime;
+
+    private Date updateTime;
+
+    private String photoUrl;
+}

+ 28 - 0
src/main/java/com/jkcredit/sysnews/model/po/permission/PermissionPo.java

@@ -0,0 +1,28 @@
+package com.jkcredit.sysnews.model.po.permission;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.ToString;
+
+import java.util.Date;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/27 14:29
+ * @version: V1.0
+ **/
+@Data
+@ToString
+@TableName("permission")
+public class PermissionPo {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String permission;
+    private String permissionName;
+    private Date createTime;
+    private Date updateTime;
+    private Integer activated;
+}

+ 33 - 0
src/main/java/com/jkcredit/sysnews/model/po/photo/PhotoPo.java

@@ -0,0 +1,33 @@
+package com.jkcredit.sysnews.model.po.photo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/29 20:49
+ * @version: V1.0
+ **/
+@Data
+@ToString
+@TableName("photo")
+public class PhotoPo implements Serializable {
+    private static final long serialVersionUID = -5569542075580659632L;
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String name;
+    private String url;
+    private Integer type;
+    private Integer activated;
+    private Date createTime;
+    private Date updateTime;
+    private Integer status;
+}

+ 31 - 0
src/main/java/com/jkcredit/sysnews/model/po/user/UserPo.java

@@ -0,0 +1,31 @@
+package com.jkcredit.sysnews.model.po.user;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/27 15:13
+ * @version: V1.0
+ **/
+@Data
+@ToString
+@TableName("user")
+public class UserPo implements Serializable {
+    private static final long serialVersionUID = -8120054530803298110L;
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String username;
+    private String password;
+    private Date createTime;
+    private Date updateTime;
+    private Integer activated;
+}

+ 27 - 0
src/main/java/com/jkcredit/sysnews/model/vo/common/ResponseVo.java

@@ -0,0 +1,27 @@
+package com.jkcredit.sysnews.model.vo.common;
+
+import lombok.Data;
+import lombok.ToString;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/1/7 22:49
+ * @version: V1.0
+ **/
+@Data
+@ToString
+public class ResponseVo {
+    private Integer code;
+    private String responseMessage;
+    private Object responseData;
+
+    public ResponseVo() {
+    }
+
+    public ResponseVo(Integer code, String responseMessage, Object responseData) {
+        this.code = code;
+        this.responseMessage = responseMessage;
+        this.responseData = responseData;
+    }
+}

+ 31 - 0
src/main/java/com/jkcredit/sysnews/model/vo/newsArticle/NewsArticleVo.java

@@ -0,0 +1,31 @@
+package com.jkcredit.sysnews.model.vo.newsArticle;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 22:59
+ * @version: V1.0
+ **/
+@Data
+public class NewsArticleVo implements Serializable {
+    private static final long serialVersionUID = -5600110791265453469L;
+    private Long id;
+
+    private String title;
+
+    private String newsAbstract;
+
+    private Long photoId;
+
+    private Long navigationBarId;
+
+    private Date createTime;
+
+    private String photoUrl;
+
+}

+ 22 - 0
src/main/java/com/jkcredit/sysnews/model/vo/photo/PhotoVo.java

@@ -0,0 +1,22 @@
+package com.jkcredit.sysnews.model.vo.photo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 21:15
+ * @version: V1.0
+ **/
+@Data
+public class PhotoVo implements Serializable {
+    private static final long serialVersionUID = -6821262346475877213L;
+
+    private Long id;
+    private String name;
+    private String url;
+    private Integer type;
+    private Integer status;
+}

+ 43 - 0
src/main/java/com/jkcredit/sysnews/resource/base/BaseResource.java

@@ -0,0 +1,43 @@
+package com.jkcredit.sysnews.resource.base;
+
+import com.baidu.unbiz.fluentvalidator.FluentValidator;
+import com.baidu.unbiz.fluentvalidator.Result;
+import com.baidu.unbiz.fluentvalidator.jsr303.HibernateSupportedValidator;
+import com.jkcredit.sysnews.spi.lang.exception.ServiceException;
+import org.modelmapper.ModelMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import javax.annotation.PostConstruct;
+import javax.validation.Validator;
+
+import static com.baidu.unbiz.fluentvalidator.ResultCollectors.toSimple;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/29 20:23
+ * @version: V1.0
+ **/
+public class BaseResource {
+
+    @Autowired
+    private Validator validator;
+
+    protected ModelMapper mapper;
+
+    protected <T> void validate(T fb) {
+        Result result = FluentValidator.checkAll()
+                .on(fb, new HibernateSupportedValidator<T>().setHiberanteValidator(validator))
+                .doValidate()
+                .result(toSimple());
+
+        if (!result.isSuccess()) {
+            throw new ServiceException(result.getErrors().toString());
+        }
+    }
+
+    @PostConstruct
+    protected void initMapper() {
+        mapper = new ModelMapper();
+    }
+}

+ 13 - 0
src/main/java/com/jkcredit/sysnews/resource/base/BizResource.java

@@ -0,0 +1,13 @@
+package com.jkcredit.sysnews.resource.base;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 0:22
+ * @version: V1.0
+ **/
+@RequestMapping("/biz")
+public class BizResource extends BaseResource  {
+}

+ 14 - 0
src/main/java/com/jkcredit/sysnews/resource/base/WebResource.java

@@ -0,0 +1,14 @@
+package com.jkcredit.sysnews.resource.base;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/29 20:23
+ * @version: V1.0
+ **/
+@RequestMapping("/app")
+public class WebResource extends BaseResource {
+
+}

+ 97 - 0
src/main/java/com/jkcredit/sysnews/resource/web/newsArticle/NewsArticleResource.java

@@ -0,0 +1,97 @@
+package com.jkcredit.sysnews.resource.web.newsArticle;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jkcredit.sysnews.model.dto.newsArticle.NewsArticleDto;
+import com.jkcredit.sysnews.model.dto.photo.PhotoDto;
+import com.jkcredit.sysnews.model.vo.newsArticle.NewsArticleVo;
+import com.jkcredit.sysnews.model.vo.photo.PhotoVo;
+import com.jkcredit.sysnews.resource.base.WebResource;
+import com.jkcredit.sysnews.resource.web.newsArticle.fb.NewsArticleFB;
+import com.jkcredit.sysnews.resource.web.newsArticle.fb.NewsArticleQueryFB;
+import com.jkcredit.sysnews.resource.web.photo.fb.PhotoFB;
+import com.jkcredit.sysnews.service.newsArticle.NewsArticleService;
+import com.jkcredit.sysnews.spi.lang.exception.ServiceException;
+import com.jkcredit.sysnews.spi.web.data.ResponseData;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 0:24
+ * @version: V1.0
+ **/
+@Slf4j
+@RestController
+public class NewsArticleResource extends WebResource {
+    @Autowired
+    NewsArticleService newsArticleService;
+
+    @GetMapping("/page/newsArticle")
+    @PreAuthorize("hasPermission('article','read')")
+    public ResponseData getNewsArticle(Page page, NewsArticleQueryFB queryFB) {
+        try {
+            NewsArticleDto newsArticleDto = mapper.map(queryFB, NewsArticleDto.class);
+            IPage<NewsArticleVo> newsArticleVoIPage = newsArticleService.getNewsArticles(page, newsArticleDto);
+            return ResponseData.success(newsArticleVoIPage);
+        } catch (ServiceException e) {
+            return ResponseData.failed("获取新闻列表失败");
+        }
+    }
+
+    @GetMapping("/newsArticle/{id}")
+    @PreAuthorize("hasPermission('article','read')")
+    public ResponseData getNewsArticleById(@PathVariable("id") Long id) {
+        try {
+            NewsArticleVo newsArticleVo = newsArticleService.getNewsArticleById(id);
+            return ResponseData.success(newsArticleVo);
+        } catch (Exception e) {
+            return ResponseData.failed("获取新闻信息失败");
+        }
+    }
+
+    @PostMapping("/newsArticle")
+    @PreAuthorize("hasPermission('article','edit')")
+    public ResponseData saveNewsArticle(NewsArticleFB newsArticleFB) {
+        try {
+            validate(newsArticleFB);
+
+            NewsArticleDto newsArticleDto = mapper.map(newsArticleFB, NewsArticleDto.class);
+            newsArticleService.saveNewsArticle(newsArticleDto);
+
+            return ResponseData.success("新增新闻成功");
+        } catch (ServiceException e) {
+            log.error(e.getMessage());
+            return ResponseData.failed("新增新闻失败,失败原因:" + e.getMessage());
+        }
+    }
+
+    @PutMapping("/newsArticle")
+    @PreAuthorize("hasPermission('article','edit')")
+    public ResponseData updateNewsArticle(NewsArticleFB newsArticleFB) {
+        try {
+            validate(newsArticleFB);
+            NewsArticleDto newsArticleDto = mapper.map(newsArticleFB, NewsArticleDto.class);
+            newsArticleService.editNewsArticle(newsArticleDto);
+
+            return ResponseData.success("编辑新闻成功");
+        } catch (ServiceException e) {
+            return ResponseData.failed("编辑新闻失败,失败原因" + e.getMessage());
+        }
+    }
+
+    @PutMapping("/newsArticle/{id}")
+    @PreAuthorize("hasPermission('article','edit')")
+    public ResponseData deleteNewsArticle(@PathVariable("id") Long id) {
+        try {
+            newsArticleService.deleteNewsArticle(id);
+            return ResponseData.success("删除新闻成功");
+        } catch (ServiceException e) {
+            log.error(e.getMessage());
+            return ResponseData.failed("删除新闻失败");
+        }
+    }
+}

+ 28 - 0
src/main/java/com/jkcredit/sysnews/resource/web/newsArticle/fb/NewsArticleFB.java

@@ -0,0 +1,28 @@
+package com.jkcredit.sysnews.resource.web.newsArticle.fb;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/2 0:46
+ * @version: V1.0
+ **/
+@Data
+public class NewsArticleFB implements Serializable {
+    private static final long serialVersionUID = 8091367992494330969L;
+
+    private Long id;
+
+    private String title;
+
+    private String newsAbstract;
+
+    private String content;
+
+    private Long photoId;
+
+    private Long navigationBarId;
+}

+ 17 - 0
src/main/java/com/jkcredit/sysnews/resource/web/newsArticle/fb/NewsArticleQueryFB.java

@@ -0,0 +1,17 @@
+package com.jkcredit.sysnews.resource.web.newsArticle.fb;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 22:55
+ * @version: V1.0
+ **/
+@Data
+public class NewsArticleQueryFB implements Serializable {
+    private static final long serialVersionUID = -3852768878379510622L;
+    private String title;
+}

+ 110 - 0
src/main/java/com/jkcredit/sysnews/resource/web/photo/PhotoResource.java

@@ -0,0 +1,110 @@
+package com.jkcredit.sysnews.resource.web.photo;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jkcredit.sysnews.model.dto.photo.PhotoDto;
+import com.jkcredit.sysnews.model.vo.photo.PhotoVo;
+import com.jkcredit.sysnews.resource.base.WebResource;
+import com.jkcredit.sysnews.resource.web.photo.fb.PhotoEditFB;
+import com.jkcredit.sysnews.resource.web.photo.fb.PhotoFB;
+import com.jkcredit.sysnews.resource.web.photo.fb.PhotoQueryFB;
+import com.jkcredit.sysnews.service.photo.PhotoService;
+import com.jkcredit.sysnews.spi.lang.exception.ServiceException;
+import com.jkcredit.sysnews.spi.web.data.ResponseData;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 0:25
+ * @version: V1.0
+ **/
+@Slf4j
+@RestController
+public class PhotoResource extends WebResource {
+    @Autowired
+    PhotoService photoService;
+
+    @PostMapping("/upload")
+    @PreAuthorize("hasPermission('photo','upload')")
+    public ResponseData upload(@RequestParam("photo") MultipartFile photo) {
+        if (photo == null) {
+            return ResponseData.failed("上传失败,图片不能为空!");
+        }
+        try {
+            String url = photoService.upload(photo);
+            return ResponseData.success((Object) url);
+        } catch (ServiceException e) {
+            return ResponseData.failed("图片上传失败");
+        }
+    }
+
+    @GetMapping("/page/photos")
+    @PreAuthorize("hasPermission('photo','read')")
+    public ResponseData getPhotos(Page page, PhotoQueryFB queryFB) {
+        try {
+            PhotoDto photoDto = mapper.map(queryFB, PhotoDto.class);
+            IPage<PhotoVo> photos = photoService.getPhotos(page, photoDto);
+            return ResponseData.success(photos);
+        } catch (ServiceException e) {
+            return ResponseData.failed("获取图片列表失败");
+        }
+    }
+
+    @GetMapping("/photo/{id}")
+    @PreAuthorize("hasPermission('photo','read')")
+    public ResponseData getPhotoById(@PathVariable("id") Long id) {
+        try {
+            PhotoVo photoVo = photoService.getPhotoById(id);
+            return ResponseData.success(photoVo);
+        } catch (Exception e) {
+            return ResponseData.failed("获取图片信息失败");
+        }
+    }
+
+    @PostMapping("/photo")
+    @PreAuthorize("hasPermission('photo','edit')")
+    public ResponseData savePhoto(PhotoFB photoFB) {
+        try {
+            validate(photoFB);
+
+            PhotoDto photoDto = mapper.map(photoFB, PhotoDto.class);
+            photoService.savePhoto(photoDto);
+
+            return ResponseData.success("新增图片成功");
+        } catch (ServiceException e) {
+            log.error(e.getMessage());
+            return ResponseData.failed("新增图片失败,失败原因:" + e.getMessage());
+        }
+    }
+
+    @PutMapping("/photo")
+    @PreAuthorize("hasPermission('photo','edit')")
+    public ResponseData updatePhoto(PhotoEditFB photoFB) {
+        try {
+            validate(photoFB);
+            PhotoDto photoDto = mapper.map(photoFB, PhotoDto.class);
+            photoService.editPhoto(photoDto);
+
+            return ResponseData.success("编辑图片数据成功");
+        } catch (ServiceException e) {
+            return ResponseData.failed("编辑图片数据,失败原因" + e.getMessage());
+        }
+    }
+
+    @PutMapping("/photo/{id}")
+    @PreAuthorize("hasPermission('photo','edit')")
+    public ResponseData deletePhoto(@PathVariable("id") Long id) {
+        try {
+            photoService.deletePhoto(id);
+            return ResponseData.success("删除图片成功");
+        } catch (ServiceException e) {
+            log.error(e.getMessage());
+            return ResponseData.failed("删除用户失败");
+        }
+    }
+}

+ 23 - 0
src/main/java/com/jkcredit/sysnews/resource/web/photo/fb/PhotoEditFB.java

@@ -0,0 +1,23 @@
+package com.jkcredit.sysnews.resource.web.photo.fb;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.io.Serializable;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 21:41
+ * @version: V1.0
+ **/
+@Data
+public class PhotoEditFB implements Serializable {
+    private static final long serialVersionUID = -2265248442090887908L;
+
+    @NotNull(message = "图片id不能为空")
+    private Long id;
+    private String name;
+    private Integer status;
+}

+ 25 - 0
src/main/java/com/jkcredit/sysnews/resource/web/photo/fb/PhotoFB.java

@@ -0,0 +1,25 @@
+package com.jkcredit.sysnews.resource.web.photo.fb;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.util.Date;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 21:27
+ * @version: V1.0
+ **/
+@Data
+public class PhotoFB {
+    @NotNull(message = "图片名称不能为空")
+    private String name;
+
+    @NotNull(message = "图片地址不能为空")
+    private String url;
+
+    @NotNull(message = "图片类型不能为空")
+    private Integer type;
+}

+ 18 - 0
src/main/java/com/jkcredit/sysnews/resource/web/photo/fb/PhotoQueryFB.java

@@ -0,0 +1,18 @@
+package com.jkcredit.sysnews.resource.web.photo.fb;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 21:11
+ * @version: V1.0
+ **/
+@Data
+public class PhotoQueryFB implements Serializable {
+    private static final long serialVersionUID = 7982101743998041038L;
+    private String name;
+    private Integer status;
+}

+ 36 - 0
src/main/java/com/jkcredit/sysnews/service/base/BaseService.java

@@ -0,0 +1,36 @@
+package com.jkcredit.sysnews.service.base;
+
+import com.baidu.unbiz.fluentvalidator.FluentValidator;
+import com.baidu.unbiz.fluentvalidator.Result;
+import com.baidu.unbiz.fluentvalidator.jsr303.HibernateSupportedValidator;
+import com.jkcredit.sysnews.spi.lang.exception.ServiceException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import javax.validation.Validator;
+
+import static com.baidu.unbiz.fluentvalidator.ResultCollectors.toSimple;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2019/2/27 20:55
+ * @version: V1.0
+ **/
+@Slf4j
+public class BaseService {
+
+    @Autowired
+    private Validator validator;
+
+    protected <T> void validate(T fb) {
+        Result result = FluentValidator.checkAll()
+                .on(fb, new HibernateSupportedValidator<T>().setHiberanteValidator(validator))
+                .doValidate()
+                .result(toSimple());
+
+        if (!result.isSuccess()) {
+            throw new ServiceException(result.getErrors().toString());
+        }
+    }
+}

+ 24 - 0
src/main/java/com/jkcredit/sysnews/service/newsArticle/NewsArticleService.java

@@ -0,0 +1,24 @@
+package com.jkcredit.sysnews.service.newsArticle;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jkcredit.sysnews.model.dto.newsArticle.NewsArticleDto;
+import com.jkcredit.sysnews.model.vo.newsArticle.NewsArticleVo;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 22:46
+ * @version: V1.0
+ **/
+public interface NewsArticleService {
+    IPage<NewsArticleVo> getNewsArticles(Page page, NewsArticleDto newsArticleDto);
+
+    NewsArticleVo getNewsArticleById(Long id);
+
+    void saveNewsArticle(NewsArticleDto newsArticleDto);
+
+    void editNewsArticle(NewsArticleDto newsArticleDto);
+
+    void deleteNewsArticle(Long id);
+}

+ 121 - 0
src/main/java/com/jkcredit/sysnews/service/newsArticle/NewsArticleServiceImpl.java

@@ -0,0 +1,121 @@
+package com.jkcredit.sysnews.service.newsArticle;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jkcredit.sysnews.mapper.NewsArticleMapper;
+import com.jkcredit.sysnews.model.dto.newsArticle.NewsArticleDto;
+import com.jkcredit.sysnews.model.po.newsArticle.NewsArticlePo;
+import com.jkcredit.sysnews.model.vo.newsArticle.NewsArticleVo;
+import com.jkcredit.sysnews.service.base.BaseService;
+import com.jkcredit.sysnews.service.photo.PhotoService;
+import com.jkcredit.sysnews.spi.lang.constant.CommonConstant;
+import com.jkcredit.sysnews.spi.lang.exception.ServiceException;
+import com.jkcredit.sysnews.util.AssertUtils;
+import com.jkcredit.sysnews.util.BeanUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 22:46
+ * @version: V1.0
+ **/
+@Slf4j
+@Service
+public class NewsArticleServiceImpl extends BaseService implements NewsArticleService {
+    @Value("${photo.absolutePath}")
+    private String absolutePath;
+    @Value("${photo.relativePath}")
+    private String relativePath;
+
+    @Resource
+    NewsArticleMapper mapper;
+    @Autowired
+    PhotoService photoService;
+
+    @Override
+    public IPage<NewsArticleVo> getNewsArticles(Page page, NewsArticleDto newsArticleDto) {
+        IPage<NewsArticlePo> newsArticlePoIPage = mapper.getNewsArticles(page, newsArticleDto);
+        return newsArticlePoIPage.convert(this::convert);
+    }
+    private NewsArticleVo convert(NewsArticlePo po) {
+        NewsArticleVo vo = new NewsArticleVo();
+        BeanUtils.copyProperties(po, vo);
+        vo.setPhotoUrl(absolutePath + vo.getPhotoUrl());
+        return vo;
+    }
+
+    @Override
+    public NewsArticleVo getNewsArticleById(Long id) {
+        NewsArticlePo newsArticlePo = mapper.getNewsArticleById(id);
+        NewsArticleVo newsArticleVo = new NewsArticleVo();
+        BeanUtil.copyProperties(newsArticleVo, newsArticlePo);
+        newsArticleVo.setPhotoUrl(absolutePath + newsArticleVo.getPhotoUrl());
+        return newsArticleVo;
+    }
+
+    @Override
+    public void saveNewsArticle(NewsArticleDto newsArticleDto) {
+        validate(newsArticleDto);
+        NewsArticlePo newsArticlePo = new NewsArticlePo();
+        BeanUtil.copyProperties(newsArticlePo, newsArticleDto);
+        newsArticlePo.setCreateTime(new Date());
+
+        try {
+            mapper.insert(newsArticlePo);
+        } catch (Exception e) {
+            log.error("新增新闻失败,失败原因:{}", e.getMessage());
+            throw new ServiceException("新增新闻失败");
+        }
+    }
+
+    @Override
+    public void editNewsArticle(NewsArticleDto newsArticleDto) {
+        validate(newsArticleDto);
+
+        NewsArticlePo newsArticlePo = mapper.getNewsArticleById(newsArticleDto.getId());
+        AssertUtils.assertNotNull(newsArticleDto, CommonConstant.ARTICLE_NOT_EXIST);
+
+        try {
+            if (!StringUtils.isBlank(newsArticleDto.getTitle())) {
+                newsArticlePo.setTitle(newsArticleDto.getTitle());
+            }
+            if (!StringUtils.isBlank(newsArticleDto.getNewsAbstract())) {
+                newsArticlePo.setNewsAbstract(newsArticleDto.getNewsAbstract());
+            }
+            if (!StringUtils.isBlank(newsArticleDto.getContent())) {
+                newsArticlePo.setContent(newsArticleDto.getContent());
+            }
+            if (newsArticleDto.getPhotoId() != null) {
+                photoService.deletePhoto(newsArticlePo.getPhotoId());
+                newsArticlePo.setPhotoId(newsArticleDto.getPhotoId());
+            }
+            mapper.updateById(newsArticlePo);
+        } catch (Exception e) {
+            log.error("编辑新闻失败,失败原因:{}", e.getMessage());
+            throw new ServiceException("编辑新闻失败");
+        }
+    }
+
+    @Override
+    public void deleteNewsArticle(Long id) {
+        NewsArticlePo newsArticlePo = mapper.getNewsArticleById(id);
+        newsArticlePo.setActivated(CommonConstant.ACTIVATED_DELETED);
+        newsArticlePo.setUpdateTime(new Date());
+
+        try {
+            mapper.updateById(newsArticlePo);
+        } catch (Exception e) {
+            log.error("删除新闻失败,失败原因:{}", e.getMessage());
+            throw new ServiceException("删除新闻失败");
+        }
+    }
+}

+ 15 - 0
src/main/java/com/jkcredit/sysnews/service/permission/PermissionService.java

@@ -0,0 +1,15 @@
+package com.jkcredit.sysnews.service.permission;
+
+import com.jkcredit.sysnews.model.po.permission.PermissionPo;
+
+import java.util.List;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/27 23:19
+ * @version: V1.0
+ **/
+public interface PermissionService {
+    List<PermissionPo> getPermissionsByUserId(Long userId);
+}

+ 26 - 0
src/main/java/com/jkcredit/sysnews/service/permission/PermissionServiceImpl.java

@@ -0,0 +1,26 @@
+package com.jkcredit.sysnews.service.permission;
+
+import com.jkcredit.sysnews.mapper.PermissionMapper;
+import com.jkcredit.sysnews.model.po.permission.PermissionPo;
+import com.jkcredit.sysnews.service.base.BaseService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/27 23:20
+ * @version: V1.0
+ **/
+@Service
+public class PermissionServiceImpl extends BaseService implements PermissionService {
+    @Resource
+    PermissionMapper permissionMapper;
+
+    @Override
+    public List<PermissionPo> getPermissionsByUserId(Long userId) {
+        return permissionMapper.getPermissionsByUserId(userId);
+    }
+}

+ 27 - 0
src/main/java/com/jkcredit/sysnews/service/photo/PhotoService.java

@@ -0,0 +1,27 @@
+package com.jkcredit.sysnews.service.photo;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jkcredit.sysnews.model.dto.photo.PhotoDto;
+import com.jkcredit.sysnews.model.vo.photo.PhotoVo;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 0:26
+ * @version: V1.0
+ **/
+public interface PhotoService {
+    String upload(MultipartFile photo);
+
+    IPage<PhotoVo> getPhotos(Page page, PhotoDto photoDto);
+
+    void savePhoto(PhotoDto photoDto);
+
+    void editPhoto(PhotoDto photoDto);
+
+    void deletePhoto(Long id);
+
+    PhotoVo getPhotoById(Long id);
+}

+ 149 - 0
src/main/java/com/jkcredit/sysnews/service/photo/PhotoServiceImpl.java

@@ -0,0 +1,149 @@
+package com.jkcredit.sysnews.service.photo;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jkcredit.sysnews.mapper.PhotoMapper;
+import com.jkcredit.sysnews.model.dto.photo.PhotoDto;
+import com.jkcredit.sysnews.model.po.photo.PhotoPo;
+import com.jkcredit.sysnews.model.vo.photo.PhotoVo;
+import com.jkcredit.sysnews.service.base.BaseService;
+import com.jkcredit.sysnews.spi.lang.constant.CommonConstant;
+import com.jkcredit.sysnews.spi.lang.exception.ServiceException;
+import com.jkcredit.sysnews.util.AssertUtils;
+import com.jkcredit.sysnews.util.BeanUtil;
+import com.jkcredit.sysnews.util.UploadUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import java.io.File;
+import java.util.Date;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 0:26
+ * @version: V1.0
+ **/
+@Slf4j
+@Service
+public class PhotoServiceImpl extends BaseService implements PhotoService {
+    @Value("${photo.absolutePath}")
+    private String absolutePath;
+    @Value("${photo.relativePath}")
+    private String relativePath;
+
+    @Resource
+    PhotoMapper photoMapper;
+
+    @Override
+    public String upload(MultipartFile photo) {
+        String filePath = absolutePath + relativePath;
+        String realPath = UploadUtil.upload(photo, filePath);
+        if (!StringUtils.isBlank(realPath)) {
+            return realPath;
+        } else {
+            log.error("图片上传失败");
+            throw new ServiceException("图片上传失败");
+        }
+    }
+
+    @Override
+    public IPage<PhotoVo> getPhotos(Page page, PhotoDto photoDto) {
+        IPage<PhotoPo> photoPoIPage = photoMapper.getPhotos(page, photoDto);
+        return photoPoIPage.convert(this::convert);
+    }
+
+    private PhotoVo convert(PhotoPo po) {
+        PhotoVo vo = new PhotoVo();
+        BeanUtils.copyProperties(po, vo);
+        vo.setUrl(absolutePath + vo.getUrl());
+        return vo;
+    }
+
+    @Override
+    public void savePhoto(PhotoDto photoDto) {
+        validate(photoDto);
+
+        String photoPath = photoDto.getUrl();
+        String[] photoPathArgs = photoPath.split("/");
+        String url = "/" +photoPathArgs[photoPathArgs.length-3] + "/" + photoPathArgs[photoPathArgs.length-2]
+                + "/" + photoPathArgs[photoPathArgs.length-1];
+        photoDto.setUrl(url);
+
+        PhotoPo photoPo = new PhotoPo();
+        BeanUtil.copyProperties(photoPo, photoDto);
+
+        photoPo.setCreateTime(new Date());
+
+        try {
+            photoMapper.insert(photoPo);
+        } catch (Exception e) {
+            log.error("新增图片数据失败,失败原因:{}", e.getMessage());
+            throw new ServiceException("新增图片数据失败");
+        }
+    }
+
+    @Override
+    public void editPhoto(PhotoDto photoDto) {
+        validate(photoDto);
+
+        PhotoPo photoPo = photoMapper.selectById(photoDto.getId());
+        AssertUtils.assertNotNull(photoPo, CommonConstant.PHOTO_NOT_EXIST);
+
+        if (!StringUtils.isBlank(photoDto.getName())) {
+            photoPo.setName(photoDto.getName());
+        }
+        if (photoDto.getStatus() != null) {
+            photoPo.setStatus(photoDto.getStatus());
+        }
+        photoPo.setUpdateTime(new Date());
+        try {
+            photoMapper.updateById(photoPo);
+        } catch (Exception e) {
+            log.error("修改图片数据失败,失败原因:{}", e.getMessage());
+            throw new ServiceException("修改图片数据异常");
+        }
+    }
+
+    @Override
+    public void deletePhoto(Long id) {
+        PhotoPo photoPo = photoMapper.selectById(id);
+        AssertUtils.assertNotNull(photoPo, CommonConstant.PHOTO_NOT_EXIST);
+
+        String url = photoPo.getUrl();
+        String realPath = absolutePath + url;
+        File file = new File(realPath);
+
+        boolean deleteResult = false;
+        if (file.exists()) {
+            deleteResult = file.delete();
+        }
+
+        if (deleteResult) {
+            photoPo.setActivated(CommonConstant.ACTIVATED_DELETED);
+            photoPo.setUpdateTime(new Date());
+            try {
+                photoMapper.updateById(photoPo);
+            } catch (Exception e) {
+                log.error("删除图片失败,失败原因:{}", e.getMessage());
+                throw new ServiceException("删除图片失败");
+            }
+        } else {
+            throw new ServiceException("删除图片失败");
+        }
+    }
+
+    @Override
+    public PhotoVo getPhotoById(Long id) {
+        PhotoPo photoPo = photoMapper.selectById(id);
+        PhotoVo photoVo = new PhotoVo();
+        BeanUtil.copyProperties(photoVo, photoPo);
+        photoVo.setUrl(absolutePath + photoVo.getUrl());
+        return photoVo;
+    }
+}

+ 58 - 0
src/main/java/com/jkcredit/sysnews/service/security/CustomUserDetailsService.java

@@ -0,0 +1,58 @@
+package com.jkcredit.sysnews.service.security;
+
+import com.jkcredit.sysnews.model.po.permission.PermissionPo;
+import com.jkcredit.sysnews.model.po.user.UserPo;
+import com.jkcredit.sysnews.service.permission.PermissionService;
+import com.jkcredit.sysnews.service.user.UserService;
+import com.jkcredit.sysnews.spi.lang.exception.ServiceException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/27 14:35
+ * @version: V1.0
+ **/
+@Component("userDetailsService")
+@Slf4j
+public class CustomUserDetailsService implements UserDetailsService {
+    @Autowired
+    UserService userService;
+    @Autowired
+    PermissionService permissionService;
+
+    @Override
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+        log.info("Authenticating {}", username);
+        Optional<UserPo> userPo = userService.getUserByUsername(username);
+        return userPo.map(user -> createSpringSecurityUser(username, user))
+                .orElseThrow(() -> new UsernameNotFoundException("user " + username + " was not found in the database"));
+    }
+
+    private org.springframework.security.core.userdetails.User createSpringSecurityUser(String lowercaseLogin, UserPo user) {
+        if (!user.getActivated().equals(1)) {
+            throw new ServiceException("user " + lowercaseLogin + " was not activated");
+        }
+
+        List<PermissionPo> permissionPoList = permissionService.getPermissionsByUserId(user.getId());
+        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
+        for (PermissionPo permissionPo : permissionPoList) {
+            if (permissionPo.getActivated().equals(1)) {
+                SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(permissionPo.getPermission());
+                grantedAuthorities.add(simpleGrantedAuthority);
+            }
+        }
+        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities);
+    }
+}

+ 15 - 0
src/main/java/com/jkcredit/sysnews/service/user/UserService.java

@@ -0,0 +1,15 @@
+package com.jkcredit.sysnews.service.user;
+
+import com.jkcredit.sysnews.model.po.user.UserPo;
+
+import java.util.Optional;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/27 15:12
+ * @version: V1.0
+ **/
+public interface UserService {
+    Optional<UserPo> getUserByUsername(String username);
+}

+ 28 - 0
src/main/java/com/jkcredit/sysnews/service/user/UserServiceImpl.java

@@ -0,0 +1,28 @@
+package com.jkcredit.sysnews.service.user;
+
+import com.jkcredit.sysnews.mapper.UserMapper;
+import com.jkcredit.sysnews.model.po.user.UserPo;
+import com.jkcredit.sysnews.service.base.BaseService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.Optional;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/27 15:12
+ * @version: V1.0
+ **/
+@Service
+@Transactional(readOnly = true)
+public class UserServiceImpl extends BaseService implements UserService{
+    @Resource
+    UserMapper userMapper;
+
+    @Override
+    public Optional<UserPo> getUserByUsername(String username) {
+        return userMapper.getUserByUsername(username);
+    }
+}

+ 13 - 0
src/main/java/com/jkcredit/sysnews/spi/lang/constant/CommonConstant.java

@@ -0,0 +1,13 @@
+package com.jkcredit.sysnews.spi.lang.constant;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 21:48
+ * @version: V1.0
+ **/
+public class CommonConstant {
+    public static final String PHOTO_NOT_EXIST = "图片不存在";
+    public static final String ARTICLE_NOT_EXIST = "新闻不存在";
+    public static Integer ACTIVATED_DELETED = 2;
+}

+ 17 - 0
src/main/java/com/jkcredit/sysnews/spi/lang/exception/ServiceException.java

@@ -0,0 +1,17 @@
+package com.jkcredit.sysnews.spi.lang.exception;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2019/02/27 20:21
+ * @version: V1.0
+ **/
+public class ServiceException extends RuntimeException {
+
+    public ServiceException() {
+    }
+
+    public ServiceException(String message) {
+        super(message);
+    }
+}

+ 41 - 0
src/main/java/com/jkcredit/sysnews/spi/web/data/ResponseData.java

@@ -0,0 +1,41 @@
+package com.jkcredit.sysnews.spi.web.data;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/2/29 19:16
+ * @version: V1.0
+ **/
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class ResponseData {
+    public static final int SUCCESS = 1;
+    public static final int FAILED = 0;
+    public static final String SUCCESS_MESSAGE = "成功";
+
+
+    private Integer code;
+    private String responseMessage;
+    private Object responseData;
+
+    public static ResponseData success(String message) {
+        return new ResponseData(SUCCESS, message, null);
+    }
+
+    public static ResponseData failed(String message) {
+        return new ResponseData(FAILED, message, null);
+    }
+
+    public static ResponseData success(Object object) {
+        return new ResponseData(SUCCESS, SUCCESS_MESSAGE, object);
+    }
+
+    public static ResponseData success(String meaage, Object object) {
+        return new ResponseData(SUCCESS, meaage, object);
+    }
+}

+ 19 - 0
src/main/java/com/jkcredit/sysnews/util/AssertUtils.java

@@ -0,0 +1,19 @@
+package com.jkcredit.sysnews.util;
+
+import com.jkcredit.sysnews.spi.lang.exception.ServiceException;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/1/12 19:59
+ * @version: V1.0
+ **/
+public class AssertUtils {
+
+    public static void assertNotNull(Object obj, String message) {
+        if (obj == null) {
+            throw new ServiceException(message);
+        }
+    }
+
+}

+ 25 - 0
src/main/java/com/jkcredit/sysnews/util/BeanUtil.java

@@ -0,0 +1,25 @@
+package com.jkcredit.sysnews.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.beanutils.PropertyUtils;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/2 10:01
+ * @version: V1.0
+ **/
+@Slf4j
+public class BeanUtil {
+
+    public static void copyProperties(Object dest, Object orig) {
+        try {
+            PropertyUtils.copyProperties(dest, orig);
+        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+            log.error("属性复制错误, 错误原因: {}", e.getMessage(), e);
+        }
+    }
+
+}

+ 31 - 0
src/main/java/com/jkcredit/sysnews/util/JwtTokenUtil.java

@@ -0,0 +1,31 @@
+package com.jkcredit.sysnews.util;
+
+import com.alibaba.fastjson.JSON;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.util.*;
+
+public class JwtTokenUtil {
+
+    public static String generateToken(String subject, int expirationSeconds, String salt, Collection<GrantedAuthority> authorities) {
+        return Jwts.builder()
+                .setSubject(subject)
+                .claim("authorities", JSON.toJSONString(authorities))
+                .setExpiration(new Date(System.currentTimeMillis() + expirationSeconds * 1000))
+                .signWith(SignatureAlgorithm.HS512, salt) // 不使用公钥私钥
+//                .signWith(SignatureAlgorithm.RS256, privateKey)
+                .compact();
+    }
+
+    public static Claims parseToken(String token, String salt) {
+        Claims claims = Jwts.parser()
+                .setSigningKey(salt) // 不使用公钥私钥
+//                    .setSigningKey(publicKey)
+                .parseClaimsJws(token).getBody();
+        return claims;
+    }
+
+}

+ 32 - 0
src/main/java/com/jkcredit/sysnews/util/UploadUtil.java

@@ -0,0 +1,32 @@
+package com.jkcredit.sysnews.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.UUID;
+
+/**
+ * @description:
+ * @author: xusonglin
+ * @create: 2020/3/1 0:54
+ * @version: V1.0
+ **/
+@Slf4j
+public class UploadUtil {
+    public static String upload(MultipartFile file, String path) {
+        String realPath = path + File.separator + UUID.randomUUID().toString().replace("-","") + "-" + file.getOriginalFilename();
+        try {
+            File dest = new File(realPath);
+            if (!dest.getParentFile().exists()) {
+                dest.getParentFile().mkdir();
+            }
+            file.transferTo(dest);
+            return realPath;
+        } catch (IOException e) {
+            log.error("图片上传错误,错误原因:{}", e.getMessage(), e);
+            return null;
+        }
+    }
+}

+ 14 - 0
src/main/resources/application-dev.yml

@@ -0,0 +1,14 @@
+server:
+  port: 18083
+spring:
+    datasource:
+      url: jdbc:mysql://39.105.129.147:3306/sys_news?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
+      username: root
+      password: 123456
+      driver-class-name: com.mysql.cj.jdbc.Driver
+      platform: mysql
+mybatis-plus:
+  mapper-locations: classpath:mapper/*Mapper.xml
+photo:
+  absolutePath: C:\Users\Administrator\Desktop
+  relativePath: \excel\photo

+ 14 - 0
src/main/resources/application-prod.yml

@@ -0,0 +1,14 @@
+server:
+  port: 18083
+spring:
+  datasource:
+    url: jdbc:mysql://39.105.129.147:3306/sys_invoice?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
+    username: root
+    password: 123456
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    platform: mysql
+mybatis-plus:
+  mapper-locations: classpath:mapper/*Mapper.xml
+photo:
+  absolutePath:
+  relativePath:

+ 17 - 0
src/main/resources/application.yml

@@ -0,0 +1,17 @@
+spring:
+  application:
+    name: sys-news
+  servlet:
+    multipart:
+      enabled: true
+      max-file-size: 200MB
+  profiles:
+    active: dev
+  jpa:
+    show-sql: true
+  resources:
+    static-locations: classpath:static/,file:static/
+server:
+  servlet:
+    session:
+      timeout: 600

+ 51 - 0
src/main/resources/mapper/NewsArticleMapper.xml

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jkcredit.sysnews.mapper.NewsArticleMapper">
+    <resultMap id="baseResultMap" type="com.jkcredit.sysnews.model.po.newsArticle.NewsArticlePo">
+        <id column="id" property="id"/>
+        <result column="title" property="title"/>
+        <result column="news_abstract" property="newsAbstract"/>
+        <result column="content" property="content"/>
+        <result column="photo_id" property="photoId"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="activated" property="activated"/>
+        <result column="navigation_bar_id" property="navigationBarId"/>
+        <result column="photoUrl" property="photoUrl"/>
+    </resultMap>
+
+    <sql id="photo">
+        id,
+        title,
+        news_abstract,
+        photo_id,
+        navigation_bar_id,
+        create_time,
+        update_time,
+        activated
+    </sql>
+
+    <select id="getNewsArticles" resultMap="baseResultMap">
+        select
+            newsArticle.*, photo.url as photoUrl
+        from
+            news_article as newsArticle
+        left join photo on newsArticle.photo_id = photo.id
+        <where>
+            and newsArticle.activated = 1 and photo.activated = 1
+            <if test="query.title != null and query.title != ''">
+                and newsArticle.title like CONCAT('%',#{query.title},'%')
+            </if>
+            order by newsArticle.create_time desc
+        </where>
+    </select>
+
+    <select id="getNewsArticleById" resultMap="baseResultMap">
+        select
+        newsArticle.*, photo.url as photoUrl
+        from
+        news_article as newsArticle
+        left join photo on newsArticle.photo_id = photo.id
+        where newsArticle.id = #{id}
+    </select>
+</mapper>

+ 19 - 0
src/main/resources/mapper/PermissionMapper.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jkcredit.sysnews.mapper.PermissionMapper">
+    <resultMap id="baseResultMap" type="com.jkcredit.sysnews.model.po.permission.PermissionPo">
+        <id column="id" property="id"/>
+        <result column="permission" property="permission"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="activated" property="activated"/>
+        <result column="permission_name" property="permissionName"/>
+    </resultMap>
+
+    <select id="getPermissionsByUserId" resultMap="baseResultMap">
+        select permission.* from permission
+        left join role_permission rolePermission on permission.id = rolePermission.permission_id
+        left join user_role userRole on userRole.role_id = rolePermission.role_id
+        where userRole.user_id = #{userId}
+    </select>
+</mapper>

+ 42 - 0
src/main/resources/mapper/PhotoMapper.xml

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jkcredit.sysnews.mapper.PhotoMapper">
+    <!-- 通用查询映射结果 -->
+    <resultMap id="baseResultMap" type="com.jkcredit.sysnews.model.po.photo.PhotoPo">
+        <id column="id" property="id"/>
+        <result column="name" property="name"/>
+        <result column="url" property="url"/>
+        <result column="type" property="type"/>
+        <result column="status" property="status"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="activated" property="activated"/>
+    </resultMap>
+
+    <sql id="photo">
+        id,
+        name,
+        url,
+        type,
+        status,
+        create_time,
+        update_time,
+        activated
+    </sql>
+    <select id="getPhotos" resultMap="baseResultMap">
+        select
+        <include refid="photo"/>
+        from
+            photo
+        <where>
+            and activated = 1
+            <if test="query.name != null and query.name != ''">
+                and name like CONCAT('%',#{query.name},'%')
+            </if>
+            <if test="query.status != null and query.status != ''">
+                and status = #{query.status}
+            </if>
+            order by type asc, create_time desc
+        </where>
+    </select>
+</mapper>

+ 29 - 0
src/main/resources/mapper/UserMapper.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jkcredit.sysnews.mapper.UserMapper">
+    <!-- 通用查询映射结果 -->
+    <resultMap id="baseResultMap" type="com.jkcredit.sysnews.model.po.user.UserPo">
+        <id column="id" property="id"/>
+        <result column="username" property="username"/>
+        <result column="password" property="password"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="activated" property="activated"/>
+    </resultMap>
+
+    <sql id="userSql">
+        id,
+        username,
+        password,
+        create_time,
+        update_time,
+        activated
+    </sql>
+    <select id="getUserByUsername" resultMap="baseResultMap">
+        select
+            *
+        from
+            user
+        where username = #{username}
+    </select>
+</mapper>

+ 11 - 0
src/test/java/com/jkcredit/sysnews/SysNewsApplicationTests.java

@@ -0,0 +1,11 @@
+package com.jkcredit.sysnews;
+
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class SysNewsApplicationTests {
+
+    void contextLoads() {
+    }
+
+}