Springboot+JPA+Hibernate搭建后台服务

▼魔方 西西 提交于 2020-03-17 09:26:05

1 环境

1.1环境配置与搭建

eclipse创建springboot项目的三种方法

1.2连接gitee进行版本控制

Eclipse将项目以Git方式分享上传到码云gitee上

1.3 maven配置国内镜像

eclipse里的maven配置国内镜像
由于我下载的eclipse不自带配置文件,去网上找了一个配置文件进行更改。

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
	<localRepository>/Users/syc/.m2/repository</localRepository>
	<pluginGroups>
	</pluginGroups>
	<proxies>
	</proxies>
	<servers>
	</servers>
	<mirrors>
		<mirror>
			<id>alimaven</id>
			<name>aliyun maven</name>
			<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
			<mirrorOf>central</mirrorOf>
		</mirror>
	</mirrors>
	<profiles>
		<profile>
			<id>securecentral</id>
			<repositories>
				<repository>
					<id>central</id>
					<url>https://repo1.maven.org/maven2</url>
					<releases>
						<enabled>true</enabled>
					</releases>
				</repository>
			</repositories>
			<pluginRepositories>
				<pluginRepository>
					<id>central</id>
					<url>https://repo1.maven.org/maven2</url>
					<releases>
						<enabled>true</enabled>
					</releases>
				</pluginRepository>
			</pluginRepositories>
		</profile>
	</profiles>
</settings>

1.3 pom.xml

poi-ooxml负责excel导出,kaptcha负责验证码生成

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.4.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.hxb</groupId>
	<artifactId>task-1</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>task-1</name>
	<description>task project</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		 <dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.10-FINAL</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.10-FINAL</version>
		</dependency>
		  <dependency>
            <groupId>com.github.penggle</groupId>
            <artifactId>kaptcha</artifactId>
            <version>2.3.2</version>
        </dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

2程序开发

2.1跨域

Spring CORS介绍
本人使用WebMvcConfigurer进行跨域处理

package com.hxb.task.util;
/**
 * 
 * 全局跨域配置
 * 
 * Created by macro on 2019/7/27.
 * 
 */
import org.springframework.context.annotation.Configuration; 
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 

@Configuration
public class GlobalCorsConfig implements WebMvcConfigurer { 
 
  @Override
  public void addCorsMappings(CorsRegistry registry) { 
    registry.addMapping("/**") 
    	.allowedOrigins("*") //.allowedOrigins("http://localhost:8090") 
        .allowCredentials(true) 
        .allowedMethods("GET", "POST", "DELETE", "PUT") 
        .maxAge(3600); 
  } 
}

2.2权限控制

通过@Value获取application.yml配置文件中的配置项

package com.hxb.task.util;
import java.io.IOException;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;

import com.hxb.task.model.Function;
import com.hxb.task.model.User;

/**
 * 权限过滤器
 *
 */
@WebFilter(filterName = "SessionFilter", urlPatterns = "/*")
@Order(2)//用于控制过滤器的优先级
public class SessionFilter implements Filter {
	private static final Logger LOGGER = LoggerFactory.getLogger(SessionFilter.class);

	/**无需权限验证的路径,以逗号隔开*/
	@Value("${project.authorityUrl}")
	private String authorityUrl;
	
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
			FilterChain filterChain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) servletRequest;;
        
		String[] authorityUrls=authorityUrl.split(",");
		String urlPath = request.getRequestURI();
		LOGGER.debug("开始权限验证,路径:"+urlPath);
		for(int i=0;i<authorityUrls.length;i++)
		{
			if(urlPath.startsWith(authorityUrls[i])){
				LOGGER.debug("当前请求无需验证");				
				filterChain.doFilter(servletRequest, servletResponse);
				return;
			}	
		}
		
		HttpSession session = request.getSession();
		if(session==null){
			LOGGER.debug("session过期");
			//未登录或者session过期
			request.getRequestDispatcher("/unauthorized").forward(servletRequest, servletResponse);
  			return;
		}
		
		User user = (User)session.getAttribute("userSession");//从session中取user对象
		List<Function> userFunctions = (List<Function>) session.getAttribute("userFunctions");//从session中取功能列表
		if (user==null) {			
				LOGGER.debug("session过期,userSession为空");
				request.getRequestDispatcher("/unauthorized").forward(servletRequest, servletResponse);
		}
		else{
				try {					
					for(Function func : userFunctions){
						if(func.getPath()!=null&&(urlPath.equals(func.getPath())||urlPath.startsWith(func.getPath()+"/")||urlPath.startsWith(func.getPath()+"?"))){
							LOGGER.debug("通过权限验证");				
							filterChain.doFilter(servletRequest, servletResponse);
							return;
						}
					}
				} catch (Exception e) {
					LOGGER.error("权限验证失败class SessionFilter:"+ e.getMessage(),e);
					request.getRequestDispatcher("/forbidden").forward(servletRequest, servletResponse);
				}
				LOGGER.debug("用户进行了非功能权限内的操作!uri:" + urlPath);
				request.getRequestDispatcher("/forbidden").forward(servletRequest, servletResponse);
		}
	}
	
	public void init(FilterConfig arg0) throws ServletException {
		LOGGER.info("session filter 初始化");
	}
	
	public void destroy() {
	}	
}

2.3日志配置

application.yml

logging:
  #level 日志等级 指定命名空间的日志输出
  level:
    com.hxb.task: debug
  #file 指定输出文件的存储路径
  file: logs
  #pattern 指定输出场景的日志输出格式
  pattern:
    console: "%d %-5level %logger : %msg%n"
    file: "%d %-5level [%thread] %logger : %msg%n"

使用方法

private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);
LOGGER.debug("xxx");

2.4验证码使用

application.yml

kaptcha:
  border: "yes"         #  是否有边框,默认为yes,可选yes、no
  border.color: 105,179,90    #边框颜色
  textproducer:     
    font:
      color: blue     #  验证码字体颜色
      size: 30        # 文本字符大小
      names: 宋体,楷体,微软雅黑     #文本字体样式
    char:
      length: 4     #验证码文本字符长度
  image:
    width: 120      # 图片宽度
    height: 40      # 图片高度
  session:
    key: code     # 存储session key

controller代码

@Autowired
private Producer captchaProducer = null;
    
@ResponseBody
@RequestMapping(value = "/kaptcha", method = RequestMethod.GET)
public void getJCaptchaImage(HttpServletRequest request,HttpServletResponse response) throws Exception {
	 HttpSession session = request.getSession();
     response.setDateHeader("Expires", 0);
     response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
     response.addHeader("Cache-Control", "post-check=0, pre-check=0");
     response.setHeader("Pragma", "no-cache");
     response.setContentType("image/jpeg");
     //生成验证码
     String capText = captchaProducer.createText();
     session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
     //向客户端写出
     BufferedImage bi = captchaProducer.createImage(capText);
     ServletOutputStream out = response.getOutputStream();
     ImageIO.write(bi, "jpg", out);
     try {
         out.flush();
     } finally {
         out.close();
     }
}
  
@ResponseBody
@RequestMapping(value = "/validate")
public Boolean login(String code, HttpServletRequest request) {
    Boolean result = false;
    String verifyCodeExpected = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
    if (verifyCodeExpected.equals(code)) {
        LOGGER.debug("验证成功"+verifyCodeExpected+"-"+code);
        result=true;
    }
    else
    {
    	 LOGGER.debug("验证失败"+verifyCodeExpected+"-"+code);
    }
    return result;
}

2.5excel导入导出

2.6Controller

  1. application/x-www-form-urlencoded,这种情况的数据@RequestParam、@ModelAttribute、@RequestBody会导致无法接收。
  2. multipart/form-data,@RequestParam MultipateFile。(form表单里面有文件上传时,必须要指定enctype属性值为multipart/form-data,意思是以二进制流的形式传输文件。)
  3. application/json、application/xml等格式的数据,使用@RequestBody、@RequestParam来处理,同一个接口一般只使用一个RequestBody
package com.hxb.task.controller;

import com.hxb.task.api.CommonResult;
import com.hxb.task.model.Pos;
import com.hxb.task.service.PosService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import javax.servlet.http.HttpServletRequest;

/**
 * 职位管理Controller
 * Created by macro on 2019/4/19.
 */
@Controller
@RequestMapping("/pos")
public class PosController {
    @Autowired
    private PosService posService;

    private static final Logger LOGGER = LoggerFactory.getLogger(PosController.class);

    @RequestMapping(value = "/create", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult createPos(@RequestBody Pos pos) {
        CommonResult commonResult;
        try
        {
        	posService.createPos(pos);
        }
        catch(DataIntegrityViolationException e)
        {
        	LOGGER.error("职位名已存在:{}", pos);
            return CommonResult.failed("职位名已存在");
        }
        catch(Exception e)
        {    	
            LOGGER.error("创建职位失败:", e);
            return CommonResult.failed("操作失败");
        }
    	commonResult = CommonResult.success(pos);
        LOGGER.info("创建职位成功:{}", pos);
        return commonResult;
    }

    @RequestMapping(value = "/update/{id}", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult updatePos(@PathVariable("id") Integer id, @RequestBody Pos pos) {
        CommonResult commonResult;
        try
        {
        	posService.updatePos(id, pos);
        }
        catch(Exception e)
        {            
            LOGGER.error("更新职位失败:", e);
            return CommonResult.failed("操作失败");
        }
        commonResult = CommonResult.success(pos);
        LOGGER.debug("更新职位成功:{}", pos);
        return commonResult;
    }
    

    @RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult deletePos(@PathVariable("id") Integer id) {
        try
        {
        	posService.deletePos(id);
        }
        catch(DataIntegrityViolationException e)
        {
        	LOGGER.debug("删除职位失败 ", e);
            return CommonResult.failed("当前职位正在使用");
        }
        catch(Exception e)
        {
        	LOGGER.debug("删除职位失败 ", e);
            return CommonResult.failed("操作失败");
        }
        LOGGER.debug("删除职位成功 :id={}", id);
        return CommonResult.success(null);
    }

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<Page<Pos>> listPoss(HttpServletRequest request,@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
       @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,@RequestParam(value = "posId",required=false) String posIds,
       @ModelAttribute Pos pos) {

    	Page<Pos> posList = posService.listPoss(pageNum-1, pageSize,pos);
        return CommonResult.success(posList);
    }
    
    @RequestMapping(value = "/listAll", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<List<Pos>> listPosAll(@ModelAttribute Pos pos) {

    	List<Pos> posList = posService.listPosAll(pos);
        return CommonResult.success(posList);
    }
    
    @RequestMapping(value = "/id/{id}", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<Pos> pos(@PathVariable("id") Integer id) {
        return CommonResult.success(posService.getPos(id));
    }

}

2.7Service

package com.hxb.task.service;
import com.hxb.task.model.Pos;
import java.util.List;
import org.springframework.data.domain.Page;

public interface PosService {
	void createPos(Pos pos);

    void updatePos( Integer id,Pos pos);

    void deletePos(Integer id);

    Page<Pos>  listPoss(int pageNum, int pageSize,Pos pos);

    List<Pos>  listPosAll(Pos pos);
    
    Pos getPos(Integer id);
}

Transactional进行事务控制,向JpaRepository中传入Pageable,可进行分页,返回Page对象。

package com.hxb.task.service.impl;

import com.hxb.task.api.Menu;
import com.hxb.task.dao.FunctionDao;
import com.hxb.task.dao.PosDao;
import com.hxb.task.service.PosService;
import com.hxb.task.util.SystemServices;
import com.hxb.task.model.Function;
import com.hxb.task.model.Pos;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.annotation.Resource;


/**
 * TPosService实现类
 * Created by macro on 2019/4/19.
 */

@Service
public class PosServiceImpl implements PosService {
 
    @Resource
    PosDao posDao;
    
    @Resource
    FunctionDao functionDao;
    
    @Resource(name="SystemServices")
    SystemServices systemServices;
 
	
	public Page<Pos> listPoss(int pageNum, int pageSize, Pos pos) {
		Page<Pos> result =null;
		Pageable pageable =  PageRequest.of(pageNum, pageSize, Sort.Direction.ASC, "posId");
		result = posDao.listPoss(pos,pageable);
		return result;
	}

	public List<Pos> listPosAll( Pos pos) {

		List<Pos> result =null;
		result = posDao.listPosAll(pos);
		return result;
	}
	
	public Pos getPos(Integer id) {
		Optional<Pos> pos= posDao.findById(id);
		return pos.get();
	}

 
    @Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)
	public void createPos(Pos pos) {
        posDao.save(pos);
    }
    
    @Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)
    public void updatePos( Integer id,Pos pos) {
        Optional<Pos> s = posDao.findById(id);
        Pos old = s.get();
        old.setPosName(pos.getPosName());
        old.setPercent(pos.getPercent());
        old.setMemo(pos.getMemo());
        old.setScored(pos.getScored());
        posDao.save(old);
    }
    
    
    @Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)
    public void deletePos(Integer id) {
        posDao.deleteById(id);
    }
 }

2.8Dao

配置application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/task?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: root
    hikari: # Hikari 数据源专用配置
      maximum-pool-size: 20
      minimum-idle: 5
  jpa:
    database: MYSQL
    database-platform: org.hibernate.dialect.MySQL57Dialect 
    #自动建表,表类型innodb,也可用MySQL5Dialect
    hibernate:
      ddl-auto: update
    show-sql: true

1.通过:#{#pos.posName} =null or s.posName like %:#{#pos.posName}% 语句,当变量为空时,不当做查询条件使用。
2.传入Pageable,可进行分页,返回Page对象。
3.继承JpaRepository,JpaRepository功能

package com.hxb.task.dao;

import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.hxb.task.model.Pos;

@Repository
public interface PosDao extends JpaRepository<Pos, Integer> {

    @Query(value = "select s from Pos s where s.posId=:posId")
    Pos getPos(@Param("posId") Integer posId);
 
    @Query(value = "select s from Pos s where ( :#{#pos.posName} =null or s.posName like %:#{#pos.posName}% )  ")
    Page<Pos> listPoss(@Param("pos") Pos pos, Pageable pageable);
    
    @Query(value = "select s from Pos s where ( :#{#pos.posName} =null or s.posName like %:#{#pos.posName}% )  ")
    List<Pos> listPosAll(@Param("pos") Pos pos);
    
	/* nativeQuery =true的情况下可直接执行sql语句
	    @Query(value = "SELECT distinct a.* FROM	t_function a LEFT JOIN role_function b ON a.func_no = b.functions_func_no  LEFT JOIN user_role c ON b.roles_role_id = c.roles_role_id WHERE	c.users_user_id = ?1 ORDER BY	func_no ASC",nativeQuery = true)
	    List<Function> getFunctionList(Integer userId);
	*/
	
	/* jpql中存在in的情况
	        @Query(value = "select s from Score s where ( :#{#score.year} =null or s.year = :#{#score.year}) and"
    		+ "( :#{#score.quarter} =null or s.quarter = :#{#score.quarter}) and "
    		+ "( :#{#score.status} =null or s.status = :#{#score.status}) and s.org.orgId in (?1)  ")
    List<Score> listScoreAll(@Param("orgs") List<Integer> orgs,@Param("score") Score score);
	*/
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!