甘肃旅游服务平台是一个基于SpringBoot+Vue技术栈开发的B/S架构管理系统,专为旅游行业设计的数字化解决方案。这个项目特别适合计算机相关专业学生用于毕业设计、课程设计或自学Java全栈开发。
我在实际开发这类旅游管理系统时发现,它完美融合了前后端分离架构的优势:后端采用SpringBoot提供RESTful API,前端使用Vue构建响应式界面,数据库选用MySQL存储业务数据。这种技术组合既能满足企业级应用的需求,又保持了足够的学习友好性。
SpringBoot作为后端框架的选择主要基于以下考量:
核心依赖示例:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
Vue.js的选用主要考虑:
典型页面组件结构:
code复制src/
├── components/
│ ├── Header.vue
│ ├── Footer.vue
│ └── ...
├── views/
│ ├── Home.vue
│ ├── Attractions.vue
│ └── ...
└── App.vue
MySQL数据库设计遵循第三范式,主要包含:
sql复制CREATE TABLE `users` (
`id` int NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
`role` enum('admin','operator','user') NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
sql复制CREATE TABLE `attractions` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`description` text,
`location` varchar(255) NOT NULL,
`image_url` varchar(255) DEFAULT NULL,
`price` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
实体关系图关键点:
后端Controller示例:
java复制@RestController
@RequestMapping("/api/attractions")
public class AttractionController {
@Autowired
private AttractionService attractionService;
@GetMapping
public ResponseEntity<List<Attraction>> getAllAttractions(
@RequestParam(required = false) String keyword) {
return ResponseEntity.ok(attractionService.searchAttractions(keyword));
}
@PostMapping
public ResponseEntity<Attraction> createAttraction(
@RequestBody AttractionDTO dto) {
return ResponseEntity.status(HttpStatus.CREATED)
.body(attractionService.createAttraction(dto));
}
}
前端Vue组件关键代码:
javascript复制export default {
data() {
return {
attractions: [],
searchQuery: ''
}
},
methods: {
async fetchAttractions() {
try {
const res = await axios.get('/api/attractions', {
params: { keyword: this.searchQuery }
})
this.attractions = res.data
} catch (error) {
console.error('获取景点列表失败:', error)
}
}
},
created() {
this.fetchAttractions()
}
}
Spring Security配置要点:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.loginProcessingUrl("/api/auth/login")
.and()
.logout()
.logoutUrl("/api/auth/logout");
}
}
启动顺序:
bash复制# 后端
mvn spring-boot:run
# 前端
npm install
npm run serve
Nginx配置示例:
nginx复制server {
listen 80;
server_name yourdomain.com;
location / {
root /path/to/vue/dist;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
解决方案:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
}
后端处理代码:
java复制@PostMapping("/upload")
public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return ResponseEntity.badRequest().body("请选择文件");
}
try {
String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
Path path = Paths.get("uploads/" + fileName);
Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
return ResponseEntity.ok("/uploads/" + fileName);
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("上传失败: " + e.getMessage());
}
}
前端实现:
javascript复制async uploadImage(file) {
const formData = new FormData()
formData.append('file', file)
try {
const res = await axios.post('/api/upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
})
return res.data
} catch (error) {
throw new Error('图片上传失败')
}
}
我在实际开发中发现,这个项目最值得借鉴的是其清晰的架构分层:controller处理请求,service实现业务逻辑,repository操作数据库,这种分层模式使得代码维护变得非常容易。对于初学者来说,理解这种架构模式比掌握具体技术细节更重要。