[英]How to display image on Jsp page from database using Hibernate and spring MVC
[英]How to display @Lob image from mysql database using spring mvc and jsp
有鏈接到github: https : //github.com/Lukszn/ProjectProfile我正在使用Spring 4.3.7.RELEASE,MySQL Connector Java:5.1.39和hibrnate:5.2.9。 最終,我有用戶和他的帳戶模型。 在帳戶中,我有@Lob accPicture和一些Strings(+ get / set)。 我正在嘗試從stackoverflow和文檔中獲取很多答案來顯示“帳戶圖片”,但沒有成功。 最后想想我該怎么做:創建了自己的ImageController。 我已成功將圖像存儲在數據庫中,但是當我嘗試在我的jsp中顯示它時,它顯示“ HTTP狀態400-客戶端發送的請求在語法上不正確”。 首先,我向您展示我的用戶模型:
@Entity
@Table(name = "users")
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(unique = true)
@NotBlank
@Size(min=4,max=20)
private String login;
@NotBlank
private String password;
@Column(unique = true)
@Email
@NotBlank
private String email;
private String permission;
@OneToMany()
private List<Account> accounts;
public User(final String login, final String password, final String email) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(login));
Preconditions.checkArgument(!Strings.isNullOrEmpty(password));
Preconditions.checkArgument(!Strings.isNullOrEmpty(email));
this.login = login;
this.password = password;
this.email = email;
}
public User() {
}
}
+ get/set
帳戶模型:
@Entity
@Table(name = "accounts")
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private boolean ifBasicAccount;
private String accTitle;
private String accFirstName;
private String accLastName;
private String accBirthdate;
private String accPhoneNumber;
private String accEducation;
private String accExperience;
private String accAbilities;
private String accInterests;
private String accProjects;
private String accDescription;
@Lob
private byte[] accPicture;
@ManyToOne
private User user;
public Account() {
}
+ get/set
下一個帳戶控制器:
@Controller
public class AccountController {
@Autowired
AccountRepository accountRepository;
@Autowired
UserRepository userRepository;
@RequestMapping(method = RequestMethod.GET, value ="addAccount")
public String addAccount(Model model) {
Account account = new Account();
model.addAttribute("account", account);
return "addAccount";
}
@RequestMapping(method = RequestMethod.POST, value ="addAccount")
public String addAccount(@ModelAttribute Account account, HttpSession session) {
User user = userRepository.findOne((Long) session.getAttribute("user_id"));
account.setIfBasicAccount(false);
account.setUser(user);
accountRepository.save(account);
return "redirect:/accounts";
}
@RequestMapping("/accounts")
public String accountList(Model model, HttpSession ses) {
long userId = (Long) ses.getAttribute("user_id");
List<Account> accounts = accountRepository.findUserAccounts(userId);
model.addAttribute("accounts", accounts);
return "accounts";
}
@RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
public String editAccountForm(Model model, @PathVariable long id) {
Account account = accountRepository.findOne(id);
model.addAttribute("account",account);
return "editAccountForm";
}
@RequestMapping(value = "/edit/{id}", method = RequestMethod.POST)
public String editAccount(@ModelAttribute Account account, @PathVariable long id) {
Account accountToUpdate = accountRepository.findOne(id);
accountToUpdate.setAccTitle(account.getAccTitle());
accountToUpdate.setAccFirstName(account.getAccFirstName());
accountToUpdate.setAccLastName(account.getAccLastName());
accountToUpdate.setAccBirthdate(account.getAccBirthdate());
accountToUpdate.setAccPhoneNumber(account.getAccPhoneNumber());
accountToUpdate.setAccEducation(account.getAccEducation());
accountToUpdate.setAccExperience(account.getAccExperience());
accountToUpdate.setAccAbilities(account.getAccAbilities());
accountToUpdate.setAccInterests(account.getAccInterests());
accountToUpdate.setAccProjects(account.getAccProjects());
accountToUpdate.setAccDescription(account.getAccDescription());
accountRepository.save(accountToUpdate);
return "redirect:/accounts";
}
@RequestMapping("/delete")
public String deleteAccount(Model model) {
return "deleteAccount";
}
@RequestMapping("/read/{id}")
public String read(@PathVariable long id) {
return accountRepository.findOne(id).toString();
}
@RequestMapping("/delete/{id}")
public String delete(@PathVariable long id) {
Account account = accountRepository.findOne(id);
accountRepository.delete(account);
return "redirect:/accounts";
}
}
最后一個ImageController:
@Controller
@RequestMapping("/user")
public class ImageController {
private AccountRepository accountRepository;
@RequestMapping(value = "/accounts", method = RequestMethod.GET)
public void showImage(@RequestParam("id") Long id, HttpServletResponse response, HttpServletRequest request)
throws ServletException, IOException {
Account account = accountRepository.getOne(id);
response.setContentType("image/jpeg, image/jpg, image/png, image/gif");
response.getOutputStream().write(account.getAccPicture());
response.getOutputStream().close();
}
}
我的.jsp顯示帳戶:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix = "fmt" uri = "http://java.sun.com/jsp/jstl/fmt" %>
<%@ page isELIgnored="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ include file="/WEB-INF/parts/header.jsp" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<div align="center">
<table class="table table-striped">
<h1>Accounts:</h1>
<c:forEach items="${accounts}" var="account" begin="0" varStatus="theCount">
<tr>
<td>${theCount.index+1}</td>
<td><b>Nazwa: </b>${account.accTitle}</td>
<td><b>Opis: </b>${account.accDescription}</td>
<td><img src="/ProjectProfile/user/accounts?id=${account.id}"/></td>
<td><a style="width: 180px;height: 20px;" href="./edit/${account.id}" class="badge badge-primary">Show/Edit</a></td>
<td><a style="width: 180px;height: 20px;" href="./delete/${account.id}" class="badge badge-danger">Delete</a></td>
</tr>
</c:forEach>
</table>
<a href="<c:url value="/addAccount"/>">Add Account</a>
</body>
</html>
也許我需要使用Base64Encoder,但我不知道如何? ....我使用pom.xml和AppConfig進行配置。 請檢查這個項目,也許有人可以幫忙?
<img id="photo" src="data:image/png;base64,${PHOTOYOUNEED}" />
在負責將圖片發送到html的控制器中:
(...)
String photoencodeBase64 = modelX.getStringPhoto();
modelAndView.addObject("PHOTOYOUNEED", photoencodeBase64 );
並且我還在模型中使用此方法將byte []轉換為base64中的字符串:
public static String convertBinImageToString(byte[] binImage) {
if(binImage!=null && binImage.length>0) {
return Base64.getEncoder().encodeToString(binImage);
}
else
return "";
}
我在模型內部的getStringPhoto()getter中調用它。
好的Eunito,讓我們看看...更改了Account.java(model):
@Entity
@Table(name = "accounts")
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private boolean ifBasicAccount;
private String accTitle;
private String accFirstName;
private String accLastName;
private String accBirthdate;
private String accPhoneNumber;
private String accEducation;
private String accExperience;
private String accAbilities;
private String accInterests;
private String accProjects;
private String accDescription;
@Lob
private byte[] accPicture;
private String stringPhoto;
@ManyToOne
private User user;
public Account() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAccTitle() {
return accTitle;
}
public void setAccTitle(String accTitle) {
this.accTitle = accTitle;
}
public String getAccFirstName() {
return accFirstName;
}
public void setAccFirstName(String accFirstName) {
this.accFirstName = accFirstName;
}
public String getAccLastName() {
return accLastName;
}
public void setAccLastName(String accLastName) {
this.accLastName = accLastName;
}
public String getAccBirthdate() {
return accBirthdate;
}
public void setAccBirthdate(String accBirthdate) {
this.accBirthdate = accBirthdate;
}
public String getAccPhoneNumber() {
return accPhoneNumber;
}
public void setAccPhoneNumber(String accPhoneNumber) {
this.accPhoneNumber = accPhoneNumber;
}
public String getAccEducation() {
return accEducation;
}
public void setAccEducation(String accEducation) {
this.accEducation = accEducation;
}
public String getAccExperience() {
return accExperience;
}
public void setAccExperience(String accExperience) {
this.accExperience = accExperience;
}
public String getAccAbilities() {
return accAbilities;
}
public void setAccAbilities(String accAbilities) {
this.accAbilities = accAbilities;
}
public String getAccInterests() {
return accInterests;
}
public void setAccInterests(String accInterests) {
this.accInterests = accInterests;
}
public String getAccProjects() {
return accProjects;
}
public void setAccProjects(String accProjects) {
this.accProjects = accProjects;
}
public String getAccDescription() {
return accDescription;
}
public void setAccDescription(String accDescription) {
this.accDescription = accDescription;
}
public byte[] getAccPicture() {
return accPicture;
}
public void setAccPicture(byte[] accPicture) {
this.accPicture = accPicture;
}
public String getStringPhoto() {
return convertBinImageToString(accPicture);
}
public void setStringPhoto(String stringPhoto) {
this.stringPhoto = stringPhoto;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public boolean isIfBasicAccount() {
return ifBasicAccount;
}
public void setIfBasicAccount(boolean ifBasicAccount) {
this.ifBasicAccount = ifBasicAccount;
}
public static String convertBinImageToString(byte[] accPicture) {
if(accPicture!=null && accPicture.length>0) {
return Base64.getEncoder().encodeToString(accPicture);
}
else
return "";
}
}
我有兩個Account控制器(一個僅用於顯示圖像-我不太確定那是一件好事,因為我有兩個相同的RequestMappings)。 因此,請參見更改后的ImageController:
@Controller
@RequestMapping("/admin/user")
public class ImageController {
@Autowired
AccountRepository accountRepository;
@RequestMapping(value = "/accounts", method = RequestMethod.GET)
public void showImage(@RequestParam("id") long id, Model model) {
Account account = accountRepository.findById(id);
String photoencodeBase64 = account.getStringPhoto();
model.addAttribute("accPicture", photoencodeBase64);
}
}
和.jsp顯示圖片:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix = "fmt" uri = "http://java.sun.com/jsp/jstl/fmt" %>
<%@ page isELIgnored="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ include file="/WEB-INF/parts/header.jsp" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<div align="center">
<table class="table table-striped">
<h1>Accounts:</h1>
<c:forEach items="${accounts}" var="account" begin="0" varStatus="theCount">
<tr>
<td>${theCount.index+1}</td>
<td><b>Title: </b>${account.accTitle}</td>
<td><b>Description: </b>${account.accDescription}</td>
<td><b>Image: </b><img id="photo" src="data:image/png;base64,${account.accPicture}" /></td>
<td><a style="width: 180px;height: 20px;" href="./edit/${account.id}" class="badge badge-primary">Show/Edit</a></td>
<td><a style="width: 180px;height: 20px;" href="./delete/${account.id}" class="badge badge-danger">Delete</a></td>
</tr>
</c:forEach>
</table>
<a href="<c:url value="/addAccount"/>">Add Account</a>
</body>
</html>
所以發生了什么-當我添加新帳戶時->寫標題,名稱等並從文件中添加圖像,我的瀏覽器顯示HTTP Status 400 - The request sent by the client was syntactically incorrect.
->我需要查看所有用戶帳戶。 在STS控制台中沒有任何反應。 在MySQL中也是如此。
為什么不使用Spring Content JPA ? 這可以提供存儲服務和其他端點,用於管理與jpa實體關聯的內容。
pom.xml
<!-- Java API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-jpa</artifactId>
<version>0.1.0</version>
</dependency>
<!-- REST API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-rest</artifactId>
<version>0.1.0</version>
</dependency>
組態
@Configuration
@EnableJpaStores
@Import("org.springframework.content.rest.config.RestConfiguration.class")
public class MysqlConfig {
// schema management
//
@Value("/org/springframework/content/jpa/schema-drop-mysql.sql")
private Resource dropRepositoryTables;
@Value("/org/springframework/content/jpa/schema-mysql.sql")
private Resource dataRepositorySchema;
@Bean
DataSourceInitializer datasourceInitializer() {
ResourceDatabasePopulator databasePopulator =
new ResourceDatabasePopulator();
databasePopulator.addScript(dropReopsitoryTables);
databasePopulator.addScript(dataReopsitorySchema);
databasePopulator.setIgnoreFailedDrops(true);
DataSourceInitializer initializer = new DataSourceInitializer();
initializer.setDataSource(dataSource());
initializer.setDatabasePopulator(databasePopulator);
return initializer;
}
}
要關聯內容,請將Spring Content批注添加到您的帳戶實體。
Account.java
@Entity
public class Account {
// replace @Lob field with
@ContentId
private String contentId;
@ContentLength
private long contentLength = 0L;
// if you have rest endpoints
@MimeType
private String mimeType = "text/plain";
創建一個“商店”:
AccountImagesStore.java
@StoreRestResource(path="accountImages)
public interface AccountImagesStore extends ContentStore<Account, String> {
}
這就是創建REST端點@ /accountImages
。 當您的應用程序啟動時,Spring Content將查看您的依賴項(請參閱Spring Content JPA / REST),查看您的AccountImagesStore
接口,並為JPA注入該接口的實現。 它還將注入一個@Controller
,將@http請求轉發到該實現。 這省去了您自己實現的任何麻煩,而我想這就是您的追求。
所以...
curl -X POST /accountImages/{account-id}
帶有multipart / form-data請求的請求會將圖像存儲在數據庫中,並將其與ID為account-id
的帳戶實體相關聯。
curl /accountImages/{account-id}
將再次獲取它,依此類推...支持完整的CRUD。
因此,您需要在JSP中顯示的只是一個圖像標簽:
有一對夫婦快速入門指南的在這里 。 參考指南在這里 。 而且還有視頻教程在這里 。 編碼位大約從1/2開始。
高溫超導
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.