后端使用Springboot 前端通过无线网路接口与后端相连
以下是具体代码实现
后端:
PolicyController
点击查看代码
package com.example.demo.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.Policy;
import com.example.demo.service.PolicyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/policy")
public class PolicyController {@Autowiredprivate PolicyService policyService;@GetMapping("/search")public Page<Policy> search(@RequestParam(defaultValue = "") String keyword,@RequestParam(defaultValue = "1") Integer current,@RequestParam(defaultValue = "10") Integer size) {Page<Policy> page = new Page<>(current, size);LambdaQueryWrapper<Policy> wrapper = new LambdaQueryWrapper<>();// 模糊匹配名称、关键词或政策文本wrapper.like(Policy::getName, keyword).or().like(Policy::getKeyword, keyword).or().like(Policy::getText, keyword);return policyService.page(page, wrapper);}@GetMapping("/{id}")public Policy getById(@PathVariable Long id) {return policyService.getById(id);}
}
点击查看代码
package com.example.demo.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;import java.util.Date;@Data
public class Policy {@TableId(type = IdType.AUTO)private Long id;private String name;private String type;private String category;@TableField("`range`")private String range;private String document;private String form;private String organ;private Date viadata;private Date pubdata;private Date perdata;@TableField("`field`")private String field;private String theme;private String keyword;private String superior;private String precursor;private String succeed;private String state;private String text;private String pdf;private String redundancy;@TableField("`rank`")private String rank;private String policykey;private String newrank;@TableField("`year`")private String year;private String newkey;private String secondtheme;private Integer allsum;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getType() {return type;}public void setType(String type) {this.type = type;}public String getCategory() {return category;}public void setCategory(String category) {this.category = category;}public String getRange() {return range;}public void setRange(String range) {this.range = range;}public String getDocument() {return document;}public void setDocument(String document) {this.document = document;}public String getForm() {return form;}public void setForm(String form) {this.form = form;}public String getOrgan() {return organ;}public void setOrgan(String organ) {this.organ = organ;}public Date getViadata() {return viadata;}public void setViadata(Date viadata) {this.viadata = viadata;}public Date getPubdata() {return pubdata;}public void setPubdata(Date pubdata) {this.pubdata = pubdata;}public Date getPerdata() {return perdata;}public void setPerdata(Date perdata) {this.perdata = perdata;}public String getField() {return field;}public void setField(String field) {this.field = field;}public String getTheme() {return theme;}public void setTheme(String theme) {this.theme = theme;}public String getKeyword() {return keyword;}public void setKeyword(String keyword) {this.keyword = keyword;}public String getSuperior() {return superior;}public void setSuperior(String superior) {this.superior = superior;}public String getPrecursor() {return precursor;}public void setPrecursor(String precursor) {this.precursor = precursor;}public String getSucceed() {return succeed;}public void setSucceed(String succeed) {this.succeed = succeed;}public String getState() {return state;}public void setState(String state) {this.state = state;}public String getText() {return text;}public void setText(String text) {this.text = text;}public String getPdf() {return pdf;}public void setPdf(String pdf) {this.pdf = pdf;}public String getRedundancy() {return redundancy;}public void setRedundancy(String redundancy) {this.redundancy = redundancy;}public String getRank() {return rank;}public void setRank(String rank) {this.rank = rank;}public String getPolicykey() {return policykey;}public void setPolicykey(String policykey) {this.policykey = policykey;}public String getNewrank() {return newrank;}public void setNewrank(String newrank) {this.newrank = newrank;}public String getYear() {return year;}public void setYear(String year) {this.year = year;}public String getNewkey() {return newkey;}public void setNewkey(String newkey) {this.newkey = newkey;}public String getSecondtheme() {return secondtheme;}public void setSecondtheme(String secondtheme) {this.secondtheme = secondtheme;}public Integer getAllsum() {return allsum;}public void setAllsum(Integer allsum) {this.allsum = allsum;}
}
点击查看代码
package com.example.demo.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.Policy;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface PolicyMapper extends BaseMapper<Policy> {
}
点击查看代码
package com.example.demo.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.entity.Policy;
import com.example.demo.mapper.PolicyMapper;
import com.example.demo.service.PolicyService;
import org.springframework.stereotype.Service;@Service
public class PolicyServiceImpl extends ServiceImpl<PolicyMapper, Policy> implements PolicyService {
}
点击查看代码
package com.example.demo.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.entity.Policy;public interface PolicyService extends IService<Policy> {
}
点击查看代码
package com.example.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}}
前端
Policy
点击查看代码
package com.qi.demo.entityimport java.util.Datedata class Policy(val id: Long,val name: String?,val type: String?,val category: String?,val range: String?,val document: String?,val form: String?,val organ: String?,val viadata: Date?,val pubdata: Date?,val perdata: Date?,val field: String?,val theme: String?,val keyword: String?,val text: String?,val pdf: String?
)
点击查看代码
package com.qi.demo.networkimport retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactoryobject ServiceCreator {private const val BASE_URL = "http://172.20.10.4:8090/"private val retrofit = Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build()fun <T> create(serviceClass: Class<T>): T = retrofit.create(serviceClass)inline fun <reified T> create(): T = create(T::class.java)
}
点击查看代码
package com.qi.demo.serviceimport com.qi.demo.entity.Policy
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Queryinterface PolicyService {@GET("policy/search")fun search(@Query("keyword") keyword: String,@Query("current") current: Int = 1,@Query("size") size: Int = 10): Call<Page<Policy>>@GET("policy/{id}")fun getById(@Path("id") id: Long): Call<Policy>
}data class Page<T>(val records: List<T>,val total: Long,val size: Int,val current: Int
)
点击查看代码
package com.qi.demoimport android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.widget.EditText
import android.widget.ImageButton
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.qi.demo.entity.Policy
import com.qi.demo.network.ServiceCreator
import com.qi.demo.service.Page
import com.qi.demo.service.PolicyService
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Responseclass MainActivity : AppCompatActivity() {private lateinit var searchInput: EditTextprivate lateinit var searchButton: ImageButtonprivate lateinit var recyclerView: RecyclerViewprivate lateinit var adapter: PolicyAdapterprivate val policyService = ServiceCreator.create<PolicyService>()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)enableEdgeToEdge()setContentView(R.layout.activity_main)initViews()setupRecyclerView()setupSearchButton()}private fun initViews() {searchInput = findViewById(R.id.searchInput)searchButton = findViewById(R.id.searchButton)recyclerView = findViewById(R.id.recyclerView)}private fun setupRecyclerView() {adapter = PolicyAdapter { policy ->// 点击政策项时打开详情openPolicyDetail(policy.id)}recyclerView.layoutManager = LinearLayoutManager(this)recyclerView.adapter = adapter}private fun setupSearchButton() {searchButton.setOnClickListener {val keyword = searchInput.text.toString()searchPolicies(keyword)}}private fun searchPolicies(keyword: String) {policyService.search(keyword).enqueue(object : Callback<Page<Policy>> {override fun onResponse(call: Call<Page<Policy>>, response: Response<Page<Policy>>) {response.body()?.let { page ->adapter.submitList(page.records)}}override fun onFailure(call: Call<Page<Policy>>, t: Throwable) {Toast.makeText(this@MainActivity, "搜索失败:${t.message}", Toast.LENGTH_SHORT).show()Log.e("MainActivity", "搜索失败", t)}})}private fun openPolicyDetail(id: Long) {policyService.getById(id).enqueue(object : Callback<Policy> {override fun onResponse(call: Call<Policy>, response: Response<Policy>) {response.body()?.let { policy ->// 如果有PDF链接,打开PDFpolicy.pdf?.let { pdfUrl ->val intent = Intent(Intent.ACTION_VIEW, Uri.parse(pdfUrl))startActivity(intent)} ?: run {// 否则显示文本内容val intent = Intent(this@MainActivity, PolicyDetailActivity::class.java)intent.putExtra("policyText", policy.text)intent.putExtra("policyName", policy.name)startActivity(intent)}}}override fun onFailure(call: Call<Policy>, t: Throwable) {Toast.makeText(this@MainActivity, "获取详情失败:${t.message}", Toast.LENGTH_SHORT).show()Log.e("MainActivity", "获取详情失败", t)}})}
}
点击查看代码
package com.qi.demoimport android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.qi.demo.entity.Policyclass PolicyAdapter(private val onItemClick: (Policy) -> Unit) :ListAdapter<Policy, PolicyAdapter.ViewHolder>(PolicyDiffCallback()) {override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {val view = LayoutInflater.from(parent.context).inflate(R.layout.item_policy, parent, false)return ViewHolder(view, onItemClick)}override fun onBindViewHolder(holder: ViewHolder, position: Int) {holder.bind(getItem(position))}class ViewHolder(view: View, private val onItemClick: (Policy) -> Unit) :RecyclerView.ViewHolder(view) {private val nameText: TextView = view.findViewById(R.id.policyName)private val organText: TextView = view.findViewById(R.id.policyOrgan)private val dateText: TextView = view.findViewById(R.id.policyDate)fun bind(policy: Policy) {nameText.text = policy.nameorganText.text = policy.organdateText.text = policy.pubdata?.toString() ?: ""itemView.setOnClickListener { onItemClick(policy) }}}
}class PolicyDiffCallback : DiffUtil.ItemCallback<Policy>() {override fun areItemsTheSame(oldItem: Policy, newItem: Policy): Boolean {return oldItem.id == newItem.id}override fun areContentsTheSame(oldItem: Policy, newItem: Policy): Boolean {return oldItem == newItem}
}
点击查看代码
package com.qi.demoimport android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivityclass PolicyDetailActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_policy_detail)val policyText = intent.getStringExtra("policyText") ?: ""val policyName = intent.getStringExtra("policyName") ?: ""findViewById<TextView>(R.id.policyTitle).text = policyNamefindViewById<TextView>(R.id.policyContent).text = policyText}
}
点击查看代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="16dp"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><EditTextandroid:id="@+id/searchInput"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:hint="请输入政策关键词"android:padding="12dp"android:background="@drawable/search_background"android:layout_marginEnd="8dp"/><ImageButtonandroid:id="@+id/searchButton"android:layout_width="48dp"android:layout_height="48dp"android:src="@drawable/ic_search"android:background="?attr/selectableItemBackgroundBorderless"android:contentDescription="搜索"/></LinearLayout><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:layout_marginTop="16dp"/></LinearLayout>
点击查看代码
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:padding="16dp"><TextViewandroid:id="@+id/policyTitle"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="20sp"android:textStyle="bold"android:textColor="@color/black"android:gravity="center"android:layout_marginBottom="16dp"/><TextViewandroid:id="@+id/policyContent"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp"android:lineSpacingMultiplier="1.2"/></LinearLayout>
</ScrollView>
点击查看代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginHorizontal="8dp"android:layout_marginVertical="4dp"app:cardCornerRadius="8dp"app:cardElevation="2dp"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:padding="16dp"><TextViewandroid:id="@+id/policyName"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp"android:textColor="@color/black"android:textStyle="bold"/><TextViewandroid:id="@+id/policyOrgan"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="8dp"android:textSize="14sp"/><TextViewandroid:id="@+id/policyDate"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="4dp"android:textSize="12sp"android:textColor="@android:color/darker_gray"/></LinearLayout></androidx.cardview.widget.CardView>